এসকিউএল সার্ভারে সঞ্চিত আপডেট সন্নিবেশ করুন


104

আমি একটি সঞ্চিত সংগ্রহ লিখেছি যা কোনও রেকর্ড উপস্থিত থাকলে আপডেট করবে, অন্যথায় এটি একটি সন্নিবেশ করবে। এটি দেখতে এমন কিছু দেখাচ্ছে:

update myTable set Col1=@col1, Col2=@col2 where ID=@ID
if @@rowcount = 0
insert into myTable (Col1, Col2) values (@col1, @col2)

এইভাবে এটি লেখার পিছনে আমার যুক্তিটি হ'ল আপডেটটি যেখানে ক্লজ ব্যবহার করে একটি অন্তর্নিহিত নির্বাচন সম্পাদন করবে এবং যদি এটি 0 প্রদান করে তবে সন্নিবেশ ঘটবে।

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

আমার যুক্তির শব্দ এখানে? আপনি কীভাবে কোনও সঞ্চিত সংকলন এবং কোনও সঞ্চিত প্রোকে এইটিকে আপডেট করবেন?

উত্তর:


61

আপনার অনুমানটি সঠিক, এটি করার সর্বোত্তম উপায় এবং এটি আপসার্ট / মার্জ বলে

ইউপিএসইআরটির গুরুত্ব - sqlservercentral.com থেকে :

উপরে উল্লিখিত ক্ষেত্রে প্রতিটি আপডেটের জন্য আমরা টেবিল থেকে একটি অতিরিক্ত পঠন সরিয়ে দিচ্ছি যদি আমরা উপস্থিতিগুলির পরিবর্তে ইউপিএসআরটি ব্যবহার করি। দুর্ভাগ্যক্রমে একটি সন্নিবেশের জন্য, উভয় ইউপিএসআরটি এবং যদি উপস্থিত থাকে তবে টেবিলে একই সংখ্যক পাঠ ব্যবহার করা হয় use অতএব অস্তিত্বের জন্য যাচাই করা কেবল তখনই করা উচিত যখন অতিরিক্ত আই / ওকে ন্যায়সঙ্গত করার কোনও কার্যকর কারণ থাকে is জিনিসগুলি করার অপ্টিমাইজড উপায় হ'ল ডিবিতে আপনার যতটা সম্ভব পঠনযোগ্য তা নিশ্চিত করা।

সেরা কৌশলটি আপডেটটি চেষ্টা করা। যদি কোনও সারি আপডেট দ্বারা প্রভাবিত না হয় তবে inোকান। বেশিরভাগ পরিস্থিতিতে, সারিটি ইতিমধ্যে উপস্থিত থাকবে এবং কেবলমাত্র একটি আই / ও প্রয়োজন হবে।

সম্পাদনা করুন : দয়া করে এই উত্তরটি এবং লিঙ্কযুক্ত ব্লগ পোস্টটি এই প্যাটার্নটিতে সমস্যাগুলি এবং এটি কীভাবে নিরাপদভাবে কাজ করা যায় সে সম্পর্কে শিখুন out


1
ঠিক আছে, এটি কমপক্ষে একটি প্রশ্নের উত্তর দিয়েছে, আমি মনে করি। এবং আমি কোড যুক্ত করিনি কারণ প্রশ্নের কোডটি আমার কাছে ইতিমধ্যে ঠিক মনে হয়েছিল। যদিও আমি এটি কোনও লেনদেনের মধ্যে রাখব, আপডেটের জন্য আমি বিচ্ছিন্নতা স্তরটিকে বিবেচনায় নিই না। আপনার উত্তরে এটি নির্দেশ করার জন্য ধন্যবাদ!
বিনআর

54

আপনি ব্যবহার করতে পারেন এমন একটি ভাল, সুরক্ষিত প্যাটার্নের জন্য দয়া করে আমার ব্লগে পোস্টটি পড়ুন । এখানে অনেক বিবেচনা রয়েছে এবং এই প্রশ্নের গৃহীত উত্তর নিরাপদ।

দ্রুত উত্তরের জন্য নিম্নলিখিত প্যাটার্নটি ব্যবহার করে দেখুন। এটি এসকিউএল 2000 এবং তারপরে আরও ভাল কাজ করবে। এসকিউএল 2005 আপনাকে অন্যরকম অপশন খোলে এবং এসকিউএল 2008 আপনাকে একটি মার্জ কমান্ড দেয় যা ত্রুটি পরিচালনা করে।

begin tran
   update t with (serializable)
   set hitCount = hitCount + 1
   where pk = @id
   if @@rowcount = 0
   begin
      insert t (pk, hitCount)
      values (@id,1)
   end
commit tran

1
আপনার ব্লগ পোস্টে আপনি উপস্থিতি পরীক্ষায় WITH (আপডেটলক, সিরিয়ালাইজযোগ্য) ইঙ্গিতটি ব্যবহার করে শেষ করেছেন। তবে, এমএসডিএন পড়তে বলা হয়েছে: "ইউপডলক - নির্দিষ্ট করে যে লেনদেনটি শেষ না হওয়া অবধি আপডেট লকগুলি নেওয়া এবং রাখা উচিত।" এর অর্থ কি এই সিরিয়ালাইজযোগ্য ইঙ্গিতটি অতিমাত্রায় কার্যকর কারণ লেনদেনের বাকি অংশগুলির জন্য আপডেট লকটি রাখা হবে, বা আমি কিছু ভুল বুঝেছি?
ড্যান ডিএফ

10

যদি এসকিউএল সার্ভার 2000/2005 ব্যবহার করা হয় তবে মূল কোডটি লেনদেনের সাথে আবদ্ধ হওয়া দরকার যাতে উপাত্তের দৃশ্যে ডেটা ধারাবাহিক থাকে make

BEGIN TRANSACTION Upsert
update myTable set Col1=@col1, Col2=@col2 where ID=@ID
if @@rowcount = 0
insert into myTable (Col1, Col2) values (@col1, @col2)
COMMIT TRANSACTION Upsert

এটি অতিরিক্ত কর্মক্ষমতা ব্যয় করবে, তবে ডেটা অখণ্ডতা নিশ্চিত করবে।

যোগ করুন, ইতিমধ্যে প্রস্তাবিত হিসাবে, MERGE যেখানে উপলব্ধ সেখানে ব্যবহার করা উচিত।


8

মার্জ, এসকিউএল সার্ভার 2008 এর নতুন বৈশিষ্ট্যগুলির মধ্যে একটি।


এবং আপনার একেবারে এটি হার্ড-টু-পঠিত হোমব্রিউউ আজেবাজেই বাদ দেওয়া উচিত। ভাল উদাহরণটি এখানে - mssqltips.com/sqlservertip/1704/…
ধনী ব্রায়ান্ট

6

আপনার কেবল এটি লেনদেন চালাতে হবে না, এটির জন্য উচ্চ বিচ্ছিন্নতা স্তরও প্রয়োজন। আমি সত্য যে ডিফল্ট বিচ্ছিন্নতা স্তর হ'ল পঠিত এবং এই কোডটি সিরিয়ালাইজযোগ্য প্রয়োজন।

SET transaction isolation level SERIALIZABLE
BEGIN TRANSACTION Upsert
UPDATE myTable set Col1=@col1, Col2=@col2 where ID=@ID
if @@rowcount = 0
  begin
    INSERT into myTable (ID, Col1, Col2) values (@ID @col1, @col2)
  end
COMMIT TRANSACTION Upsert

সম্ভবত @@ ত্রুটি পরীক্ষা এবং রোলব্যাক যোগ করা ভাল ধারণা হতে পারে।


@ মুনিশ গোয়াল কারণ ডাটাবেসে একাধিক কমান্ড এবং পূর্ববর্তী প্যারালেলে চলে। তারপরে অন্য থ্রেড আপডেট চালানোর ঠিক পরে এবং sertোকানো চালানোর আগে একটি সারি সন্নিবেশ করতে পারে।
টমাস টিন্তেরা

5

আপনি যদি এসকিউএল ২০০৮ এ মার্জ না করে থাকেন তবে আপনাকে অবশ্যই এটিতে পরিবর্তন করতে হবে:

যদি @@ সারি গণনা = 0 এবং @@ ত্রুটি = 0 হয়

অন্যথায় যদি আপডেটটি কোনও কারণে ব্যর্থ হয় তবে এটি চেষ্টা করবে এবং পরে প্রবেশ করানো হবে কারণ একটি ব্যর্থ বিবৃতিতে সারি গণনা 0


3

ইউপিএসআরটির বড় ফ্যান, পরিচালনা করার জন্য কোডটি সত্যই কমে যায়। আমি এটি করার অন্য উপায়টি এখানে: ইনপুট প্যারামিটারগুলির মধ্যে একটি হল আইডি, যদি আইডি নুল বা 0 হয় তবে আপনি জানেন যে এটি একটি INSERT, অন্যথায় এটি একটি আপডেট। ধরে নিন অ্যাপ্লিকেশনটি কোনও আইডি আছে কিনা তা জানে, সুতরাং সমস্ত পরিস্থিতিতে কাজ করবে না, তবে আপনি যদি করেন তবে অর্ধেকের মধ্যে মৃত্যুদণ্ড কার্যকর করা হবে।


2

পরিবর্তিত ডিমা ম্যালেনকো পোস্ট:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 

BEGIN TRANSACTION UPSERT 

UPDATE MYTABLE 
SET    COL1 = @col1, 
       COL2 = @col2 
WHERE  ID = @ID 

IF @@rowcount = 0 
  BEGIN 
      INSERT INTO MYTABLE 
                  (ID, 
                   COL1, 
                   COL2) 
      VALUES      (@ID, 
                   @col1, 
                   @col2) 
  END 

IF @@Error > 0 
  BEGIN 
      INSERT INTO MYERRORTABLE 
                  (ID, 
                   COL1, 
                   COL2) 
      VALUES      (@ID, 
                   @col1, 
                   @col2) 
  END 

COMMIT TRANSACTION UPSERT 

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


1

আপনার যুক্তিটি যথাযথ বলে মনে হচ্ছে তবে আপনি যদি একটি নির্দিষ্ট প্রাথমিক কীটিতে পাস করে থাকেন তবে সন্নিবেশ রোধ করতে আপনি কিছু কোড যুক্ত করার বিষয়টি বিবেচনা করতে চাইতে পারেন।

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.