পারমাণবিক লেনদেনে অনন্য লঙ্ঘন এড়ান


15

পোস্টগ্রিসএসকিউএলে পারমাণবিক লেনদেন তৈরি করা সম্ভব?

এই সারিগুলির সাথে আমার সারণী বিভাগ রয়েছে তা বিবেচনা করুন:

id|name
--|---------
1 |'tablets'
2 |'phones'

এবং কলামের নামটিতে অনন্য বাধা রয়েছে।

যদি আমি চেষ্টা করি:

BEGIN;
update "category" set name = 'phones' where id = 1;
update "category" set name = 'tablets' where id = 2;
COMMIT;

আমি পাচ্ছি:

ERROR:  duplicate key value violates unique constraint "category_name_key"
DETAIL:  Key (name)=(tablets) already exists.

উত্তর:


24

@ ক্রেইগ যা সরবরাহ করেছিল (এবং এর কিছু সংশোধন করে) তা ছাড়াও :

কার্যকরী Postgres 9.4 , UNIQUE, PRIMARY KEYএবং EXCLUDEসীমাবদ্ধতার অবিলম্বে চেক করা হয় প্রতিটি সারির পর যখন সংজ্ঞায়িত NOT DEFERRABLE। এটি অন্যান্য ধরণের NOT DEFERRABLEবাধা (বর্তমানে কেবলমাত্র REFERENCES(বিদেশী কী)) থেকে পৃথক যা প্রতিটি বিবৃতি পরে পরীক্ষা করা হয় । এসও সম্পর্কিত এই প্রশ্নের অধীনে আমরা এই সমস্ত কাজ করেছি:

এটা না যথেষ্ট একটি জন্য UNIQUE(অথবা PRIMARY KEYবা EXCLUDE) বাধ্যতা হতে DEFERRABLEসঙ্গে আপনার উপস্থাপন কোড করতে একাধিক বিবৃতি হবে।

এবং আপনি এই উদ্দেশ্যে ব্যবহার করতে পারবেন নাALTER TABLE ... ALTER CONSTRAINTপ্রতি ডকুমেন্টেশন:

ALTER CONSTRAINT

এই ফর্মটি পূর্বে তৈরি হওয়া সীমাবদ্ধতার বৈশিষ্ট্যগুলিকে পরিবর্তন করে। বর্তমানে কেবল বৈদেশিক কী বাধা পরিবর্তন করা যেতে পারে

বোল্ড জোর আমার। পরিবর্তে ব্যবহার করুন:

ALTER TABLE t
   DROP CONSTRAINT category_name_key
 , ADD  CONSTRAINT category_name_key UNIQUE(name) DEFERRABLE;

ড্রপ এবং একটি একক বিবৃতিতে ফিরে প্রতিবন্ধকতা যুক্ত করুন যাতে আপত্তিজনক সারিগুলিতে কারও জন্য ছিঁড়ে যাওয়ার কোনও সময় উইন্ডো নেই। বড় টেবিলগুলির জন্য এটি কোনওভাবে অন্তর্নিহিত অনন্য সূচি সংরক্ষণ করার জন্য লোভনীয় হবে, কারণ এটি মুছে ফেলা এবং পুনরায় তৈরি করা ব্যয়বহুল। হায়রে, এটি স্ট্যান্ডার্ড সরঞ্জামগুলির মাধ্যমে সম্ভব বলে মনে হচ্ছে না (যদি এর জন্য আপনার কাছে কোনও সমাধান থাকে, তবে দয়া করে আমাদের জানান!):

একটি জন্য একক বিবৃতি বাধ্যতা deferrable উপার্জন যথেষ্ট:

UPDATE category c
SET    name = c_old.name
FROM   category c_old
WHERE  c.id     IN (1,2)
AND    c_old.id IN (1,2)
AND    c.id <> c_old.id;

সিটিই সহ একটি প্রশ্নও একক বিবৃতি:

WITH x AS (
    UPDATE category SET name = 'phones' WHERE id = 1
    )
UPDATE category SET name = 'tablets' WHERE id = 2;

তবে একাধিক বিবৃতি সহ আপনার কোডের জন্য আপনাকে (অতিরিক্তভাবে) সীমাবদ্ধতাটি স্থগিত করতে হবে - বা এটিকে হিসাবে সংজ্ঞায়িত করা উচিত INITIALLY DEFERREDসাধারণত উপরের চেয়ে ব্যয়বহুল। তবে একটি বিবৃতিতে সমস্ত কিছু প্যাক করা সহজেই সম্ভব হবে না।

BEGIN;
SET CONSTRAINTS category_name_key DEFERRED;
UPDATE category SET name = 'phones'  WHERE id = 1;
UPDATE category SET name = 'tablets' WHERE id = 2;
COMMIT;

যদিও সীমাবদ্ধতার সাথে সীমাবদ্ধতার বিষয়ে সচেতন হন FOREIGN KEYপ্রতি ডকুমেন্টেশন:

রেফারেন্সযুক্ত কলামগুলি অবশ্যই রেফারেন্স সারণীতে একটি অ-স্থলযোগ্য অনন্য বা প্রাথমিক কী বাধাটির কলাম হতে হবে ।

সুতরাং আপনি একই সাথে উভয় থাকতে পারে।


13

আমি এটি বুঝতে পেরেছি যে, এখানে আপনার সমস্যাটি হ'ল প্রতিটি বিবৃতি দেওয়ার পরে বাধাটি পরীক্ষা করা হয় তবে আপনি লেনদেনের শেষে এটি পরীক্ষা করে দেখতে চান, সুতরাং এটি মধ্যবর্তী অবস্থাগুলি উপেক্ষা করে পূর্ব-রাষ্ট্রকে পূর্বের রাজ্যের সাথে তুলনা করে।

যদি তা হয় তবে এটি একটি মুলতুবি বাধা দিয়ে সম্ভব ।

নথিবদ্ধ হিসাবে দেখুন SET CONSTRAINTSএবং DEFERRABLEসীমাবদ্ধতা CREATE TABLE

মনে রাখবেন যে বিলম্বিত প্রতিবন্ধকতাগুলির ব্যয় রয়েছে - প্রতিশ্রুতিবদ্ধ সময়ে পরীক্ষা করার জন্য সিস্টেমকে তাদের একটি তালিকা রাখতে হবে, যাতে তারা প্রচুর পরিমাণে পরিবর্তন করে এমন লেনদেনের পক্ষে ভাল না। তারা চেক করতে ধীর।

সুতরাং আমি মনে করি আপনি সম্ভবত এটি করতে চান:

ALTER TABLE mytable ALTER CONSTRAINT category_name_key DEFERRABLE;

দ্রষ্টব্য যে সীমাবদ্ধতা ALTER TABLEসেট করার ক্ষেত্রে সীমাবদ্ধতা রয়েছে বলে মনে হচ্ছে DEFERRABLE; আপনি পরিবর্তে DROPএবং ADDসীমাবদ্ধতা আবার করতে পারে ।

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