PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

रोलबैक घटना पोस्टग्रेस्क्ल में ट्रिगर होती है

आप इसके लिए अनुक्रम का उपयोग नहीं कर सकते हैं। आपको एक एकल क्रमांकन बिंदु की आवश्यकता है जिसके माध्यम से सभी आवेषण को जाना होगा - अन्यथा "गैपलेस" विशेषता की गारंटी नहीं दी जा सकती है। आपको यह भी सुनिश्चित करने की आवश्यकता है कि उस तालिका से कभी भी कोई पंक्तियाँ नहीं हटाई जाएँगी।

क्रमांकन का अर्थ यह भी है कि केवल एक ही लेन-देन उस तालिका में पंक्तियों को सम्मिलित कर सकता है - अन्य सभी प्रविष्टियों को तब तक प्रतीक्षा करनी होगी जब तक कि "पिछला" सम्मिलित नहीं किया गया हो या वापस रोल किया गया हो।

एक पैटर्न यह कैसे कार्यान्वित किया जा सकता है एक तालिका है जहां "अनुक्रम" संख्याएं संग्रहीत की जाती हैं। आइए मान लें कि हमें इनवॉइस नंबरों के लिए इसकी आवश्यकता है जो कानूनी कारणों से अंतराल रहित होना चाहिए।

तो हम पहले "वर्तमान मान" रखने के लिए तालिका बनाते हैं:

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');

नया नंबर जेनरेट होता है। एक सेकंड लेन-देन को तब तक प्रतीक्षा करने की आवश्यकता होती है जब तक कि पहली प्रविष्टि प्रतिबद्ध या वापस नहीं हो जाती।

जैसा कि मैंने कहा:यह समाधान मापनीय नहीं है। बिल्कुल भी नहीं। यदि उस तालिका में बहुत सारी प्रविष्टियां हैं तो यह आपके आवेदन को बड़े पैमाने पर धीमा कर देगी। लेकिन आपके पास दोनों नहीं हो सकते:एक स्केलेबल और अंतराल रहित अनुक्रम का सही क्रियान्वयन।

मुझे यह भी पूरा यकीन है कि किनारे के मामले हैं जो उपरोक्त कोड द्वारा कवर नहीं किए गए हैं। तो बहुत संभव है कि आप अभी भी अंतराल के साथ समाप्त कर सकते हैं।




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. पोस्टग्रेएसक्यूएल किसी दिए गए आईडी के लिए सबसे हाल की प्रविष्टि का चयन

  2. आपके PostgreSQL परिनियोजन में देखने के लिए 7 चीजें

  3. सबसे आम PostgreSQL विफलता परिदृश्य

  4. JSON कॉलम में सरणी के तत्व के लिए क्वेरी

  5. मैं उद्धरण के अंदर प्लेसहोल्डर के साथ एक क्वेरी का उपयोग कैसे कर सकता हूं? (पर्ल/पोस्टग्रेस्क्ल)