এসকিউএল আউটপুট ধারাটির জন্য কি কলামটি sertedোকানো হচ্ছে না তা ফেরানো সম্ভব?


123

আমি আমার ডাটাবেসে কিছু পরিবর্তন করেছি এবং আমার পুরানো ডেটাটি নতুন টেবিলগুলিতে স্থানান্তর করতে হবে। তার জন্য, আমাকে মূল সারণী (অনুশীলন) থেকে ডেটা নেওয়ার একটি টেবিল (রিপোর্টপোশন) পূরণ করতে হবে এবং একটি দ্বিতীয় মধ্যবর্তী টেবিল (প্র্যাকটিস রিপোর্টারপশন) পূরণ করতে হবে।

ReportOption (ReportOptionId int PK, field1, field2...)
Practice (PracticeId int PK, field1, field2...)
PracticeReportOption (PracticeReportOptionId int PK, PracticeId int FK, ReportOptionId int FK, field1, field2...)

অনুশীলন থেকে রিপোর্টঅ্যাপশনে যেতে আমার যে সমস্ত ডেটা দরকার তা পেতে আমি একটি ক্যোয়ারী তৈরি করেছি, তবে মধ্যবর্তী সারণীটি পূরণ করতে আমার সমস্যা হচ্ছে

--Auxiliary tables
DECLARE @ReportOption TABLE (PracticeId int /*This field is not on the actual ReportOption table*/, field1, field2...)
DECLARE @PracticeReportOption TABLE (PracticeId int, ReportOptionId int, field1, field2)

--First I get all the data I need to move
INSERT INTO @ReportOption
SELECT P.practiceId, field1, field2...
  FROM Practice P

--I insert it into the new table, but somehow I need to have the repation PracticeId / ReportOptionId
INSERT INTO ReportOption (field1, field2...)
OUTPUT @ReportOption.PracticeId, --> this is the field I don't know how to get
       inserted.ReportOptionId
  INTO @PracticeReportOption (PracticeId, ReportOptionId)
SELECT field1, field2
  FROM @ReportOption

--This would insert the relationship, If I knew how to get it!
INSERT INTO @PracticeReportOption (PracticeId, ReportOptionId)
SELECT PracticeId, ReportOptionId
  FROM @ReportOption

আমি যদি এমন কোনও ক্ষেত্র উল্লেখ করতে পারি যা OUTPUT ধারাটিতে গন্তব্য টেবিলে নেই, তবে তা দুর্দান্ত হবে (আমার মনে হয় আমি পারব না, তবে আমি নিশ্চিতভাবে জানি না)। আমার প্রয়োজনীয়তা কীভাবে সম্পাদন করতে হবে?


1
আপনি যে টেবিলের যে কোনও কলামকে আপনার সারণীতে একটি সারি সন্নিবেশ OUTPUTকরিয়ে দিতে পারবেন। সুতরাং আপনি যদি আপনার INSERTবিবৃতিতে প্রদত্ত কলামটির জন্য কোনও মান সরবরাহ না করেন , আপনি এখনও সেই OUTPUTধারাটি ক্লজটিতে নির্দিষ্ট করতে পারেন । তবে আপনি অন্য টেবিল থেকে এসকিউএল ভেরিয়েবল বা কলামগুলি ফিরিয়ে দিতে পারবেন না।
marc_s

2
@মার্ক_ আপনার জবাবের জন্য ধন্যবাদ, তবে আমার কাছে গন্তব্য টেবিলে আমার প্রয়োজন ক্ষেত্র নেই (আমার অনুশীলন আইড দরকার, যা রিপোর্টপোশনে নেই)
আলেজান্দ্রো বি।

উত্তর:


191

আপনি প্রবেশের MERGEপরিবর্তে এটি ব্যবহার করে করতে পারেন :

সুতরাং এটি প্রতিস্থাপন

INSERT INTO ReportOption (field1, field2...)
OUTPUT @ReportOption.PracticeId, --> this is the field I don't know how to get
       inserted.ReportOptionId
  INTO @PracticeReportOption (PracticeId, ReportOptionId)
SELECT field1, field2
  FROM @ReportOption

সঙ্গে

MERGE INTO ReportOption USING @ReportOption AS temp ON 1 = 0
WHEN NOT MATCHED THEN
    INSERT (field1, field2)
    VALUES (temp.Field1, temp.Field2)
    OUTPUT temp.PracticeId, inserted.ReportOptionId, inserted.Field1, inserted.Field2
    INTO @PracticeReportOption (PracticeId, ReportOptionId, Field1, Field2);

মূলটি হ'ল এমন একটি প্রাক্কলিক ব্যবহার করা যা মার্জ অনুসন্ধানের ক্ষেত্রে কখনই সত্য হবে না (1 = 0), সুতরাং আপনি সর্বদা সন্নিবেশ সম্পাদন করবেন তবে উত্স এবং গন্তব্য সারণী উভয় ক্ষেত্রেই ক্ষেত্রগুলিতে অ্যাক্সেস থাকবে।


এটি পরীক্ষা করার জন্য আমি ব্যবহৃত পুরো কোডটি এখানে:

CREATE TABLE ReportOption (ReportOptionID INT IDENTITY(1, 1), Field1 INT, Field2 INT)
CREATE TABLE Practice (PracticeID INT IDENTITY(1, 1), Field1 INT, Field2 INT)
CREATE TABLE PracticeReportOption (PracticeReportOptionID INT IDENTITY(1, 1), PracticeID INT, ReportOptionID INT, Field1 INT, Field2 INT)

INSERT INTO Practice VALUES (1, 1), (2, 2), (3, 3), (4, 4)


MERGE INTO ReportOption r USING Practice p ON 1 = 0
WHEN NOT MATCHED THEN
    INSERT (field1, field2)
    VALUES (p.Field1, p.Field2)
    OUTPUT p.PracticeId, inserted.ReportOptionId, inserted.Field1, inserted.Field2
    INTO PracticeReportOption (PracticeId, ReportOptionId, Field1, Field2);

SELECT  *
FROM    PracticeReportOption

DROP TABLE ReportOption
DROP TABLE Practice
DROP TABLE PracticeReportOption 

আরও পড়া এবং এই বিষয়টিতে আমি যা জানি তার উত্স এখানে


2
ধন্যবাদ, এই কৌশলটি! আমি একটি জাল টেম্প ফিল্ড ব্যবহার করতে যাচ্ছিলাম তবে এটি আরও মার্জিত।
আলেজান্দ্রো বি।

1
অসাধারণ! এই কৌশলটি সোনার দানা! সংগ্রহে প্রথম সারিতে যুক্ত!
ভাদিম লোবদা

1
Suweet! আমি আশা করি এটি মাঝেমধ্যে বগি মার্জ কমান্ডটি ব্যবহার না করে, তবে এটি অন্যথায় পুরোপুরি মার্জিত।
ট্যাব আললেমান

4
সতর্কাবস্থা. আমি একীভূত বিবৃতি ব্যবহার করেছি যা গত বছর ধরে ব্যবহারের সাথে বেড়েছে। সংরক্ষণের সময় আমরা সময়সীমা থাকা শুরু করি এবং এটি পরিণত হয় যে মার্জ স্টেটমেন্টটি সর্বদা আমাদের টেবিলগুলিকে লক করে রাখে প্রতি 4 মিনিটে আমাদের 35-160 সেকেন্ডের টেবিল লক হয়ে যায়। সারণী লকিং এড়াতে সন্নিবেশ / আপডেটগুলি সারণির সংখ্যা 500 প্রতি সীমাবদ্ধ করে সীমাবদ্ধ করা / আপডেট করতে ব্যবহার করতে আমি একাধিক মার্জ বিবৃতি পুনর্গঠন করতে চলেছি। আমি অনুমান করি যে এই অতি গুরুত্বপূর্ণ টেবিলটি প্রতিদিন প্রায় 2/2 ঘন্টা লক করা ছিল যা ধীরে ধীরে সাশ্রয় থেকে শুরু করে সময়সীমা পর্যন্ত সমস্ত কারণ তৈরি করে।
কিউব্রুট

3
এছাড়াও, অনেকের জন্য একটি চুক্তি ব্রেকারটি হ'ল মার্জটিতে পুরোপুরি ফিক্সযুক্ত বাগ রয়েছে যা উদ্ভট পরিস্থিতিতে পড়ে surface যেমন অ্যারন বারট্র্যান্ডের এই নিবন্ধটি দেখুন । মাইক্রোসফ্ট তাদের কিছু সংশোধন করতে অস্বীকার করছে, এবং আমার গোপন সন্দেহটি হ'ল এমএস তাদের পুরো এমএস সংযোগ পরিষেবাটি কেবল চেষ্টা করার জন্য এবং সেগুলি ঠিক করতে চান না এমন মার্জ স্টেটমেন্টে আমাদের এই সমস্ত বাগগুলি ভুলে যাওয়ার জন্য তাদের অবজ্ঞা করে ।
উল্টো ইঞ্জিনিয়ার

14

হতে পারে যে কেউ এমএস এসকিউএল সার্ভার 2005 বা তার চেয়ে কম ব্যবহার করেন তারা এই উত্তরটি দরকারী বলে খুঁজে পাবেন।


মার্জ কেবলমাত্র এসকিউএল সার্ভারের জন্য কাজ করবে ২০০৮ বা তারও বেশি। বিশ্রামের জন্য আমি আর একটি কাজের সন্ধান পেয়েছি যা আপনাকে ম্যাপিংয়ের টেবিল তৈরির ক্ষমতা দেয়।

রেজোলিউশনটি এসকিউএল 2005 এর মতো দেখতে কেমন হবে তা এখানে:

DECLARE @ReportOption TABLE (ReportOptionID INT IDENTITY(1, 1), Field1 INT, Field2 INT)
DECLARE @Practice TABLE(PracticeID INT IDENTITY(1, 1), Field1 INT, Field2 INT)
DECLARE @PracticeReportOption TABLE(PracticeReportOptionID INT IDENTITY(1, 1), PracticeID INT, ReportOptionID INT, Field1 INT, Field2 INT)

INSERT INTO @Practice (Field1, Field2) VALUES (1, 1)
INSERT INTO @Practice (Field1, Field2) VALUES (2, 2)
INSERT INTO @Practice (Field1, Field2) VALUES (3, 3)
INSERT INTO @Practice (Field1, Field2) VALUES (4, 4)

INSERT INTO @ReportOption (field1, field2)
    OUTPUT INSERTED.ReportOptionID, INSERTED.Field1, INSERTED.Field2 INTO @PracticeReportOption (ReportOptionID, Field1, Field2)
    SELECT Field1, Field2 FROM @Practice ORDER BY PracticeID ASC;


WITH CTE AS ( SELECT PracticeID, ROW_NUMBER() OVER ( ORDER BY PracticeID ASC ) AS ROW FROM @Practice )
UPDATE M SET M.PracticeID = S.PracticeID 
    FROM @PracticeReportOption AS M
    JOIN CTE AS S ON S.ROW = M.PracticeReportOptionID

    SELECT * FROM @PracticeReportOption

মূল কৌশলটি হ'ল আমরা উত্স এবং গন্তব্য সারণীর আদেশকৃত ডেটা দিয়ে ম্যাপিং টেবিলটি দু'বার পূরণ করছি। আরও তথ্যের জন্য এখানে: এসকিউএল সার্ভার 2005-এ OUTPUT ব্যবহার করে sertedোকানো ডেটা মার্জ করা


1
এটি আমার সমস্যা সমাধান করবে না। আমি প্রয়োজন Outputআমার Insertএকটি আউটপুট এর Tableযে একটি অন্তর্ভুক্ত Identityলক্ষ্য থেকে মান Tableএকটি অ সঙ্গে Insertউৎস থেকে -ed মান (পি কে) Tableএকটি ভিন্ন ব্যাচ মধ্যে) ব্যবহার (BTW, তাই আমি তারপর পারা (যে আউটপুট Tableএকটি পূরণ করতে Columnএ মান Tableসহ উত্স Identity)। একটি ছাড়া Merge, আমি কল্পনা করতে পারি যে: ক) শুরু করতে হবে Transaction, খ) পরবর্তী পেতে Identity, গ) টেম্পুতে comp Tableোকানো গণনা Identity, ঘ) সেট Identity_Insert, ই) টেম্প থেকে Insertলক্ষ্যমাত্রায় , চ) পরিষ্কার । TableTableIdentity_Insert
টম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.