কোনও INSERT এর OUTPUT ধারাটির আদেশের উপর নির্ভর করা কি নিরাপদ?


19

এই টেবিল দেওয়া:

CREATE TABLE dbo.Target (
   TargetId int identity(1, 1) NOT NULL,
   Color varchar(20) NOT NULL,
   Action varchar(10) NOT NULL, -- of course this should be normalized
   Code int NOT NULL,
   CONSTRAINT PK_Target PRIMARY KEY CLUSTERED (TargetId)
);

দুটি সামান্য ভিন্ন পরিস্থিতিতে আমি সারি সন্নিবেশ করতে এবং পরিচয় কলাম থেকে মানগুলি ফিরিয়ে দিতে চাই।

দৃশ্যপট 1

INSERT dbo.Target (Color, Action, Code)
OUTPUT inserted.TargetId
SELECT t.Color, t.Action, t.Code
FROM
   (VALUES
      ('Blue', 'New', 1234),
      ('Blue', 'Cancel', 4567),
      ('Red', 'New', 5678)
   ) t (Color, Action, Code)
;

দৃশ্য 2

CREATE TABLE #Target (
   Color varchar(20) NOT NULL,
   Action varchar(10) NOT NULL,
   Code int NOT NULL,
   PRIMARY KEY CLUSTERED (Color, Action)
);

-- Bulk insert to the table the same three rows as above by any means

INSERT dbo.Target (Color, Action, Code)
OUTPUT inserted.TargetId
SELECT t.Color, t.Action, t.Code
FROM #Target
;

প্রশ্ন

আমি কি dbo.Targetটেবিল সন্নিবেশ থেকে প্রত্যাবর্তিত পরিচয় মানগুলির উপর নির্ভর করতে পারি যে তারা 1) VALUESধারা এবং 2) #Targetসারণীতে বিদ্যমান ক্রম হিসাবে ফিরে আসবে , যাতে আমি আউটপুট রাউসেটে তাদের অবস্থানটি মূল ইনপুটটিতে ফিরিয়ে আনতে পারি?

রেফারেন্সের জন্য

এখানে কিছু ছাঁটাই-ডাউন সি # কোড দেওয়া আছে যা অ্যাপ্লিকেশনটিতে কী ঘটছে তা দেখায় (দৃশ্য 1, শীঘ্রই ব্যবহারে রূপান্তরিত হবে SqlBulkCopy):

public IReadOnlyCollection<Target> InsertTargets(IEnumerable<Target> targets) {
   var targetList = targets.ToList();
   const string insertSql = @"
      INSERT dbo.Target (
         CoreItemId,
         TargetDateTimeUtc,
         TargetTypeId,
      )
      OUTPUT
         Inserted.TargetId
      SELECT
         input.CoreItemId,
         input.TargetDateTimeUtc,
         input.TargetTypeId,
      FROM
         (VALUES
            {0}
         ) input (
            CoreItemId,
            TargetDateTimeUtc,
            TargetTypeId
         );";
   var results = Connection.Query<DbTargetInsertResult>(
      string.Format(
         insertSql,
         string.Join(
            ", ",
            targetList
               .Select(target => $@"({target.CoreItemId
                  }, '{target.TargetDateTimeUtc:yyyy-MM-ddTHH:mm:ss.fff
                  }', {(byte) target.TargetType
                  })";
               )
         )
      )
      .ToList();
   return targetList
      .Zip( // The correlation that relies on the order of the two inputs being the same
         results,
         (inputTarget, insertResult) => new Target(
            insertResult.TargetId, // with the new TargetId to replace null.
            inputTarget.TargetDateTimeUtc,
            inputTarget.CoreItemId,
            inputTarget.TargetType
         )
      )
      .ToList()
      .AsReadOnly();
}

উত্তর:


22

আমি কি ডিবিও থেকে প্রত্যাবর্তিত পরিচয় মানগুলির উপর নির্ভর করতে পারি? টার্গেট টেবিল সারণি সারণি সারণি সন্নিবেশ করানো যেতে পারে 1) ভ্যালু ক্লজ এবং 2) # টার্গেট টেবিল যাতে আমি আউটপুট রোসেটে তাদের অবস্থানের সাথে তাদের সম্পর্ক স্থাপন করতে পারি আসল ইনপুট?

না, আপনি প্রকৃত নথিভুক্ত গ্যারান্টি ছাড়া গ্যারান্টিযুক্ত কোনও কিছুর উপর নির্ভর করতে পারবেন না। ডকুমেন্টেশনে স্পষ্টভাবে বলা হয়েছে যে এরকম কোনও গ্যারান্টি নেই।

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

এটি অনেকগুলি অনিবন্ধিত অনুমানের উপর নির্ভর করবে

  1. ধ্রুবক স্ক্যান থেকে সারিগুলি যে ক্রমটি আউটপুট হয় সেগুলি মান ধরণের হিসাবে একই ক্রমে থাকে (আমি কখনই সেগুলি পৃথক করে দেখিনি তবে আফাইক এটির নিশ্চয়তা নেই)।
  2. সারিগুলি যে ক্রমটি সন্নিবেশ করা হয় তা ক্রমাগত স্ক্যান থেকে আউটপুট ক্রম হিসাবে একই হবে (অবশ্যই সবসময় এটি হয় না)।
  3. যদি "প্রশস্ত" (প্রতি সূচক) নির্বাহের পরিকল্পনা ব্যবহার করা হয় তবে আউটপুট ধারা থেকে মানগুলি ক্লাস্টারড ইনডেক্স আপডেট অপারেটর থেকে টানা হবে এবং কোনও গৌণ সূচকের নয়।
  4. অর্ডারটি তারপরে সংরক্ষণের গ্যারান্টিযুক্ত - যেমন নেটওয়ার্কের মাধ্যমে সংক্রমণের জন্য প্যাকেজিং সারি করার সময়
  5. এমনকি যদি আদেশটি পূর্বাভাস হিসাবে দেখা যায় তবে সমান্তরাল সন্নিবেশের মতো বৈশিষ্ট্যগুলিতে প্রয়োগের পরিবর্তনগুলি ভবিষ্যতে অর্ডার পরিবর্তন করবে না (বর্তমানে যদি ক্লাসিকের কাছে ফলাফল ফেরত দেওয়ার জন্য OUTPUT ধারাটি সুনির্দিষ্টভাবে নির্দিষ্ট করা থাকে ... তবে সমান্তরাল পরিকল্পনাগুলি হ'ল INSERTs সহ সাধারণভাবে অক্ষম করা হয়েছে )

দফায় দু'টি ব্যর্থতার উদাহরণ (ক্লাস্টারড পিকে ধরে ধরে (Color, Action)) দেখা যায় যদি আপনি এই VALUESদফায় 600 সারি যুক্ত করেন । তারপরে োকানোর আগে পরিকল্পনার একটি সাজানোর অপারেটর রয়েছে যাতে ক্লজটিতে আপনার মূল ক্রমটি হারাতে পারে VALUES

যদিও আপনার লক্ষ্য অর্জনের একটি নথিভুক্ত উপায় রয়েছে এবং এটি হ'ল উত্সটিতে একটি নম্বর যুক্ত করা এবং তার MERGEপরিবর্তে ব্যবহার করাINSERT

MERGE dbo.Target
USING (VALUES (1, 'Blue', 'New', 1234),
              (2, 'Blue', 'Cancel', 4567),
              (3, 'Red', 'New', 5678) ) t (SourceId, Color, Action, Code)
ON 1 = 0
WHEN NOT MATCHED THEN
  INSERT (Color,
          Action,
          Code)
  VALUES (Color,
          Action,
          Code)
OUTPUT t.SourceId,
       inserted.TargetId; 

এখানে চিত্র বর্ণনা লিখুন

@কোন নাম দিয়ে একটি ঘোড়া

একীকরণ কি সত্যিই প্রয়োজনীয়? আপনি কি শুধু একটি করতে পারেন না insert into ... select ... from (values (..)) t (...) order by sourceid?

হ্যাঁ আপনি করতে পারেন। এসকিউএল সার্ভারে গ্যারান্টি অর্ডার করা ... এতে বলা হয়েছে

সন্নিবেশ স্থাপনের জন্য অর্ডার সহ নির্বাচন নির্বাচন করুন এমন অনুসন্ধানগুলি শনাক্তকরণের মানগুলি কীভাবে গণনা করা হয় তা সুনির্দিষ্ট করে তবে সারিগুলি যেভাবে সন্নিবেশ করা হয় তা নয়

সুতরাং আপনি ব্যবহার করতে পারে

INSERT dbo.Target (Color, Action, Code)
OUTPUT inserted.TargetId
SELECT t.Color, t.Action, t.Code
FROM
(VALUES (1, 'Blue', 'New', 1234),
        (2, 'Blue', 'Cancel', 4567),
        (3, 'Red', 'New', 5678) ) t (SourceId, Color, Action, Code)
ORDER BY t.SourceId

এখানে চিত্র বর্ণনা লিখুন

এটি গ্যারান্টি দেয় যে সনাক্তকরণের মানগুলি ক্রম অনুসারে নির্ধারিত হয়েছে t.SourceIdতবে তা নয় যে সেগুলি কোনও নির্দিষ্ট ক্রমে আউটপুট হয় বা নির্ধারিত পরিচয় কলাম মানগুলির কোনও ফাঁক থাকে না (উদাহরণস্বরূপ যদি সমবর্তী সন্নিবেশ করানোর চেষ্টা করা হয়)।


2
ফাঁক হওয়ার সম্ভাবনা এবং আউটপুট কোনও নির্দিষ্ট ক্রমে না থাকা সম্পর্কে এই সর্বশেষ বিটটি ইনপুটটিতে আবার সম্পর্ক স্থাপনের চেষ্টা করার জন্য বিষয়গুলিকে কিছুটা আকর্ষণীয় করে তোলে। আমি মনে করি আবেদনের মাধ্যমে কোনও অর্ডার কাজটি করবে তবে এটি কেবল নিরাপদ এবং স্পষ্ট মনে হয় এটি ব্যবহার করা MERGE
এরিক

আউটপুট ক্রমের গ্যারান্টি দিতে OUTPUT ... INTO [#temp]সিনট্যাক্স ব্যবহার করুন SELECT ... FROM [#temp] ORDER BY
ম্যাক্স ভার্নন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.