9.5 এবং আরও নতুন:
PostgreSQL 9.5 এবং আরও নতুন সমর্থন INSERT ... ON CONFLICT UPDATE
(এবং ON CONFLICT DO NOTHING
), অর্থাৎ উপস্থাপন।
সঙ্গে তুলনাON DUPLICATE KEY UPDATE
।
দ্রুত ব্যাখ্যা ।
ব্যবহারের জন্য ম্যানুয়ালটি দেখুন - বিশেষত সিন্ট্যাক্স ডায়াগ্রামে দ্বন্দ্ব_অধি ধারা এবং ব্যাখ্যামূলক পাঠ্য ।
নীচে দেওয়া 9.4 এবং এর চেয়ে বেশি পুরানো সমাধানগুলির বিপরীতে, এই বৈশিষ্ট্যটি একাধিক বিরোধী সারিগুলির সাথে কাজ করে এবং এর জন্য একচেটিয়া লকিং বা পুনরায় চেষ্টা করার প্রয়োজন নেই।
বৈশিষ্ট্য যুক্ত করার প্রতিশ্রুতি এখানে এবং এর বিকাশের চারপাশের আলোচনা এখানে ।
আপনি যদি 9.5-এ থাকেন এবং পশ্চাদপটে সামঞ্জস্যপূর্ণ হওয়ার প্রয়োজন না থাকলে আপনি এখন পড়া বন্ধ করতে পারেন ।
9.4 এবং আরও পুরানো:
পোস্টগ্রিসকিউএল-তে কোনও বিল্ট-ইন UPSERT
(বা MERGE
) সুবিধা নেই, এবং সমবর্তী ব্যবহারের ক্ষেত্রে দক্ষতার সাথে এটি করা খুব কঠিন।
এই নিবন্ধটি কার্যকরভাবে বিস্তারিতভাবে আলোচনা করেছে ।
সাধারণভাবে আপনাকে দুটি বিকল্পের মধ্যে পছন্দ করতে হবে:
- পুনরায় চেষ্টা করে পৃথক সন্নিবেশ / আপডেট অপারেশন; অথবা
- টেবিলটি লক করে ব্যাচ মার্জ করছে doing
স্বতন্ত্র সারির পুনরায় চেষ্টা করুন লুপ
যদি আপনি সংযোগের সাথে সংযোজন সম্পাদন করার চেষ্টা করতে চান তবে অনেকগুলি সংযোগ চাইলে পুনরায় চেষ্টা করে পৃথক সারি আপসার্ট ব্যবহার করা যুক্তিসঙ্গত বিকল্প।
PostgreSQL ডকুমেন্টেশনে একটি দরকারী পদ্ধতি রয়েছে যা আপনাকে এটি ডাটাবেসের অভ্যন্তরে একটি লুপে করতে দেয় । এটি হারানো আপডেটগুলি থেকে রক্ষা করে এবং সর্বাধিক নিষ্পাপ সমাধানগুলির বিপরীতে রেসগুলি সন্নিবেশ করায়। এটি কেবল READ COMMITTED
মোডে কাজ করবে এবং এটি কেবল নিরাপদ যদি এটি লেনদেনে আপনি একমাত্র কাজ করেন, যদিও। ট্রিগার বা গৌণ অনন্য কীগুলি অনন্য লঙ্ঘনের কারণ হলে ফাংশনটি সঠিকভাবে কাজ করবে না।
এই কৌশলটি খুব অদক্ষ। যখনই ব্যবহারিক আপনার কাজের সারি সারি করা উচিত এবং পরিবর্তে নীচে বর্ণিত হিসাবে একটি বাল্ক আপসেট করা উচিত।
এই সমস্যার সমাধানের চেষ্টা করা অনেকগুলি রোলব্যাকগুলি বিবেচনা করতে ব্যর্থ হয়, ফলে সেগুলি অসম্পূর্ণ আপডেটে আসে। একে অপরের সাথে দুটি লেনদেনের দৌড়; তাদের মধ্যে একটি সফলভাবে INSERT
এস; অন্যটি একটি সদৃশ কী ত্রুটি পায় এবং UPDATE
পরিবর্তে এটি করে। UPDATE
ব্লক জন্য অপেক্ষা INSERT
রোলব্যাক বা কমিট করতে। এটি যখন পিছনে ফিরে আসে, UPDATE
শর্তটি শূন্য সারিগুলির সাথে পুনরায় পরীক্ষা UPDATE
করে so আপনাকে ফলাফলের সারির সংখ্যা গণনা করতে হবে এবং যেখানে প্রয়োজন সেখানে আবার চেষ্টা করতে হবে।
কিছু চেষ্টা করা সমাধানগুলি SELECT দৌড় বিবেচনা করতে ব্যর্থ হয়। আপনি যদি স্পষ্ট এবং সহজ চেষ্টা করেন:
-- THIS IS WRONG. DO NOT COPY IT. It's an EXAMPLE.
BEGIN;
UPDATE testtable
SET somedata = 'blah'
WHERE id = 2;
-- Remember, this is WRONG. Do NOT COPY IT.
INSERT INTO testtable (id, somedata)
SELECT 2, 'blah'
WHERE NOT EXISTS (SELECT 1 FROM testtable WHERE testtable.id = 2);
COMMIT;
তারপরে যখন দুটি রান এক সাথে হয় তখন বেশ কয়েকটি ব্যর্থতা মোড থাকে। একটি আপডেট পুনরায় চেক সঙ্গে ইতিমধ্যে আলোচিত সমস্যা। আর এক যেখানে উভয় UPDATE
একই সময়ে শূন্য সারি মেলে এবং অবিরত। তারপর তারা উভয় কি EXISTS
পরীক্ষা, যা ঘটবে সামনেINSERT
। উভয়ই শূন্য সারি পায়, তাই উভয়ই তা করে INSERT
। একটি সদৃশ কী ত্রুটি সঙ্গে ব্যর্থ।
এজন্য আপনার পুনরায় চেষ্টা করার লুপ দরকার। আপনি ভাবতে পারেন যে আপনি চতুর এসকিউএল দিয়ে নকল কী বা ত্রুটিযুক্ত আপডেটগুলি প্রতিরোধ করতে পারেন, তবে আপনি পারবেন না। আপনাকে সারি গণনাগুলি পরীক্ষা করতে বা ডুপ্লিকেট কী ত্রুটিগুলি (নির্বাচিত পদ্ধতির উপর নির্ভর করে) পরিচালনা করতে হবে এবং পুনরায় চেষ্টা করতে হবে।
এর জন্য আপনার নিজের সমাধানটি রোল করবেন না। বার্তা সারি লাগানোর মতো, এটি সম্ভবত ভুল।
লক সহ বাল্ক আপসার্ট
কখনও কখনও আপনি একটি বাল্ক উপসর্গ করতে চান, যেখানে আপনার কাছে একটি নতুন ডেটা সেট রয়েছে যা আপনি কোনও পুরানো বিদ্যমান ডেটা সেটে মেশাতে চান। এটি স্বতন্ত্র সারি আপসার্টের চেয়ে ব্যাপকভাবে দক্ষ এবং যখনই ব্যবহারিক প্রয়োগ করা পছন্দ করা উচিত।
এই ক্ষেত্রে, আপনি সাধারণত নিম্নলিখিত প্রক্রিয়াটি অনুসরণ করেন:
CREATE
একটি TEMPORARY
টেবিল
COPY
বা টেম্প টেবিলটিতে নতুন ডেটা বাল্ক-sertোকান
LOCK
লক্ষ্য টেবিল IN EXCLUSIVE MODE
। এটি অন্য লেনদেনের অনুমতি দেয় SELECT
তবে টেবিলটিতে কোনও পরিবর্তন আনবে না।
UPDATE ... FROM
টেম্প টেবিলের মানগুলি ব্যবহার করে বিদ্যমান রেকর্ডগুলির একটি করুন ;
INSERT
লক্ষ্য সারণীতে ইতিমধ্যে বিদ্যমান না এমন একটি সারি করুন;
COMMIT
, লক মুক্তি।
উদাহরণস্বরূপ, প্রশ্নে দেওয়া উদাহরণের জন্য, INSERT
টেম্প টেবিলটি স্থাপনের জন্য বহু-মূল্যবান ব্যবহার করে :
BEGIN;
CREATE TEMPORARY TABLE newvals(id integer, somedata text);
INSERT INTO newvals(id, somedata) VALUES (2, 'Joe'), (3, 'Alan');
LOCK TABLE testtable IN EXCLUSIVE MODE;
UPDATE testtable
SET somedata = newvals.somedata
FROM newvals
WHERE newvals.id = testtable.id;
INSERT INTO testtable
SELECT newvals.id, newvals.somedata
FROM newvals
LEFT OUTER JOIN testtable ON (testtable.id = newvals.id)
WHERE testtable.id IS NULL;
COMMIT;
সম্পর্কিত পড়া
কি হবে MERGE
?
এসকিউএল-স্ট্যান্ডার্ডটিতে MERGE
প্রকৃত অর্থে বাজে সংজ্ঞা রয়েছে এবং প্রথমে কোনও টেবিল লক না করে সংরক্ষণের জন্য উপযুক্ত নয়।
এটি ডেটা মার্জ করার জন্য একটি সত্যই কার্যকর ওএলএপি বিবৃতি, তবে এটি সম্মতি-সুরক্ষার জন্য কোনও কার্যকর সমাধান নয়। অন্যান্য ডিবিএমএস ব্যবহারের MERGE
জন্য ব্যবহারকারীর জন্য প্রচুর পরামর্শ রয়েছে তবে এটি আসলে ভুল।
অন্যান্য ডিবি: