आप इसके लिए अनुक्रम का उपयोग नहीं कर सकते हैं। आपको एक एकल क्रमांकन बिंदु की आवश्यकता है जिसके माध्यम से सभी आवेषण को जाना होगा - अन्यथा "गैपलेस" विशेषता की गारंटी नहीं दी जा सकती है। आपको यह भी सुनिश्चित करने की आवश्यकता है कि उस तालिका से कभी भी कोई पंक्तियाँ नहीं हटाई जाएँगी।
क्रमांकन का अर्थ यह भी है कि केवल एक ही लेन-देन उस तालिका में पंक्तियों को सम्मिलित कर सकता है - अन्य सभी प्रविष्टियों को तब तक प्रतीक्षा करनी होगी जब तक कि "पिछला" सम्मिलित नहीं किया गया हो या वापस रोल किया गया हो।
एक पैटर्न यह कैसे कार्यान्वित किया जा सकता है एक तालिका है जहां "अनुक्रम" संख्याएं संग्रहीत की जाती हैं। आइए मान लें कि हमें इनवॉइस नंबरों के लिए इसकी आवश्यकता है जो कानूनी कारणों से अंतराल रहित होना चाहिए।
तो हम पहले "वर्तमान मान" रखने के लिए तालिका बनाते हैं:
create table slow_sequence
(
seq_name varchar(100) not null primary key,
current_value integer not null default 0
);
-- create a "sequence" for invoices
insert into slow_sequence values ('invoice');
अब हमें एक फ़ंक्शन की आवश्यकता है जो अगली संख्या उत्पन्न करेगा लेकिन यह गारंटी देता है कि कोई भी दो लेनदेन एक ही समय में अगली संख्या प्राप्त नहीं कर सकते हैं।
create or replace function next_number(p_seq_name text)
returns integer
as
$$
update slow_sequence
set current_value = current_value + 1
where seq_name = p_seq_name
returning current_value;
$$
language sql;
फ़ंक्शन काउंटर में वृद्धि करेगा और परिणामस्वरूप बढ़ा हुआ मान लौटाएगा। update
के कारण अनुक्रम के लिए पंक्ति अब लॉक हो गई है और कोई अन्य लेनदेन उस मान को अपडेट नहीं कर सकता है। यदि कॉलिंग लेन-देन वापस ले लिया गया है, तो अनुक्रम काउंटर के लिए अद्यतन भी है। यदि यह प्रतिबद्ध है, तो नया मान बना रहता है।
यह सुनिश्चित करने के लिए कि प्रत्येक लेनदेन फ़ंक्शन का उपयोग करता है, एक ट्रिगर बनाया जाना चाहिए।
विचाराधीन तालिका बनाएं:
create table invoice
(
invoice_number integer not null primary key,
customer_id integer not null,
due_date date not null
);
अब ट्रिगर फ़ंक्शन और ट्रिगर बनाएं:
create or replace function f_invoice_trigger()
returns trigger
as
$$
begin
-- the number is assigned unconditionally so that this can't
-- be prevented by supplying a specific number
new.invoice_number := next_number('invoice');
return new;
end;
$$
language plpgsql;
create trigger invoice_trigger
before insert on invoice
for each row
execute procedure f_invoice_trigger();
अब अगर एक लेन-देन ऐसा करता है:
insert into invoice (customer_id, due_date)
values (42, date '2015-12-01');
नया नंबर जेनरेट होता है। एक सेकंड लेन-देन को तब तक प्रतीक्षा करने की आवश्यकता होती है जब तक कि पहली प्रविष्टि प्रतिबद्ध या वापस नहीं हो जाती।
जैसा कि मैंने कहा:यह समाधान मापनीय नहीं है। बिल्कुल भी नहीं। यदि उस तालिका में बहुत सारी प्रविष्टियां हैं तो यह आपके आवेदन को बड़े पैमाने पर धीमा कर देगी। लेकिन आपके पास दोनों नहीं हो सकते:एक स्केलेबल और अंतराल रहित अनुक्रम का सही क्रियान्वयन।
मुझे यह भी पूरा यकीन है कि किनारे के मामले हैं जो उपरोक्त कोड द्वारा कवर नहीं किए गए हैं। तो बहुत संभव है कि आप अभी भी अंतराल के साथ समाप्त कर सकते हैं।