(এই বিষয় সম্পর্কে একটি নিবন্ধটি পুনরায় আবিষ্কার করার চেষ্টা করার সময় আমি এই প্রশ্নে এসেছি Now এখন আমি এটি খুঁজে পেয়েছি, অন্যরা বর্তমানে নির্বাচিত উত্তরের বিকল্প বিকল্পের সন্ধানের ক্ষেত্রে এটি এখানে পোস্ট করছি with row_number()
)
আমার এই একই ব্যবহারের মামলা আছে। আমাদের সাএসে একটি নির্দিষ্ট প্রকল্পের মধ্যে প্রবেশ করা প্রতিটি রেকর্ডের জন্য আমাদের একটি অনন্য, বর্ধনশীল সংখ্যা প্রয়োজন যা সমবর্তীগুলির মুখে তৈরি করা যেতে পারে INSERT
এবং আদর্শভাবে ফাঁকবিহীন।
এই নিবন্ধটি একটি দুর্দান্ত সমাধান বর্ণনা করেছে , যা আমি এখানে স্বাচ্ছন্দ্য এবং উত্তরোত্তর জন্য সংক্ষিপ্ত করব।
- একটি পৃথক সারণী রয়েছে যা পরবর্তী মান সরবরাহ করতে কাউন্টার হিসাবে কাজ করে। এটিতে দুটি কলাম থাকবে,
document_id
এবং counter
। বিকল্প হিসাবে counter
হবে DEFAULT 0
, আপনার যদি ইতিমধ্যে কোনও document
সত্ত্বা থাকে যা সমস্ত সংস্করণকে গোষ্ঠীভূত করে, একটি counter
সেখানে যুক্ত করা যেতে পারে।
- সারণীতে একটি
BEFORE INSERT
ট্রিগার যুক্ত করুন document_versions
যা পরমাণুভাবে কাউন্টারকে বাড়িয়ে তোলে ( UPDATE document_revision_counters SET counter = counter + 1 WHERE document_id = ? RETURNING counter
) এবং তারপরে NEW.version
সেই কাউন্টারটির মান সেট করে।
বিকল্পভাবে, আপনি অ্যাপ্লিকেশন স্তরে এটি করতে একটি সিটিই ব্যবহার করতে সক্ষম হতে পারেন (যদিও আমি এটি ধারাবাহিকতার জন্য ট্রিগার হতে পছন্দ করি):
WITH version AS (
UPDATE document_revision_counters
SET counter = counter + 1
WHERE document_id = 1
RETURNING counter
)
INSERT
INTO document_revisions (document_id, rev, other_data)
SELECT 1, version.counter, 'some other data'
FROM "version";
এটি নীতিগতভাবে অনুরূপ যে আপনি কীভাবে এটি প্রাথমিকভাবে সমাধানের চেষ্টা করছেন, একক বিবৃতিতে পাল্টা সারিটি সংশোধন করে INSERT
এটি প্রতিশ্রুতিবদ্ধ না হওয়া পর্যন্ত বাসি মানটি পড়তে অবরুদ্ধ করে ।
এটি কার্যকরভাবে psql
দেখানো থেকে একটি প্রতিলিপি এখানে :
scratch=# CREATE TABLE document_revisions (document_id integer, rev integer, other_data text, PRIMARY KEY (document_id, rev));
CREATE TABLE
scratch=# CREATE TABLE document_revision_counters (document_id integer PRIMARY KEY, counter integer DEFAULT 0);
CREATE TABLE
scratch=# WITH version AS (
INSERT INTO document_revision_counters (document_id) VALUES (2)
ON CONFLICT (document_id)
DO UPDATE SET counter = document_revision_counters.counter + 1
RETURNING counter;
)
INSERT
INTO document_revisions (document_id, rev, other_data)
SELECT 2, version.counter, 'doc 1 v1'
FROM "version";
INSERT 0 1
scratch=# WITH version AS (
INSERT INTO document_revision_counters (document_id) VALUES (2)
ON CONFLICT (document_id)
DO UPDATE SET counter = document_revision_counters.counter + 1
RETURNING counter;
)
INSERT
INTO document_revisions (document_id, rev, other_data)
SELECT 2, version.counter, 'doc 1 v2'
FROM "version";
INSERT 0 1
scratch=# WITH version AS (
INSERT INTO document_revision_counters (document_id) VALUES (2)
ON CONFLICT (document_id)
DO UPDATE SET counter = document_revision_counters.counter + 1
RETURNING counter;
)
INSERT
INTO document_revisions (document_id, rev, other_data)
SELECT 2, version.counter, 'doc 2 v1'
FROM "version";
INSERT 0 1
scratch=# SELECT * FROM document_revisions;
document_id | rev | other_data
-------------+-----+------------
2 | 1 | doc 1 v1
2 | 2 | doc 1 v2
2 | 1 | doc 2 v1
(3 rows)
আপনি দেখতে পাচ্ছেন, কীভাবে এটি INSERT
ঘটে সে সম্পর্কে আপনাকে সতর্কতা অবলম্বন করতে হবে , অতএব ট্রিগার সংস্করণটি যা দেখতে এরকম দেখাচ্ছে:
CREATE OR REPLACE FUNCTION set_doc_revision()
RETURNS TRIGGER AS $$ BEGIN
WITH version AS (
INSERT INTO document_revision_counters (document_id, counter) VALUES (NEW.document_id, 1)
ON CONFLICT (document_id)
DO UPDATE SET counter = document_revision_counters.counter + 1
RETURNING counter
)
SELECT INTO NEW.rev counter FROM version; RETURN NEW; END;
$$ LANGUAGE 'plpgsql';
CREATE TRIGGER set_doc_revision BEFORE INSERT ON document_revisions
FOR EACH ROW EXECUTE PROCEDURE set_doc_revision();
এটি INSERT
নির্ধারিত INSERT
উত্স থেকে উত্পন্ন উত্সর মুখোমুখি হয়ে আরও অনেক সোজা এগিয়ে এবং ডেটার অখণ্ডতা আরও দৃ rob় করে তোলে :
scratch=# INSERT INTO document_revisions (document_id, other_data) VALUES (1, 'baz');
INSERT 0 1
scratch=# INSERT INTO document_revisions (document_id, other_data) VALUES (1, 'foo');
INSERT 0 1
scratch=# INSERT INTO document_revisions (document_id, other_data) VALUES (1, 'bar');
INSERT 0 1
scratch=# INSERT INTO document_revisions (document_id, other_data) VALUES (42, 'meaning of life');
INSERT 0 1
scratch=# SELECT * FROM document_revisions;
document_id | rev | other_data
-------------+-----+-----------------
1 | 1 | baz
1 | 2 | foo
1 | 3 | bar
42 | 1 | meaning of life
(4 rows)