ऐसा करने का एकमात्र तरीका कोड नियंत्रण तालिका है ...
create table code_control
(year number(4,0) not null
, type varchar2(1) not null
, last_number number(38,0) default 1 not null
, primary key (year,type)
)
organization index
/
... जिसे इस तरह से रखा जाता है ...
create or replace function get_next_number
(p_year in number, p_type in varchar2)
return number
is
pragma autonomous_transaction;
cursor cur_cc is
select last_number + 1
from code_control cc
where cc.year= p_year
and cc.type = p_type
for update of last_number;
next_number number;
begin
open cur_cc;
fetch cur_cc into next_number;
if cur_cc%found then
update code_control
set last_number = next_number
where current of cur_cc;
else
insert into code_control (year,type)
values (p_year, p_type)
returning last_number into next_number;
end if;
commit;
return next_number;
end;
/
महत्वपूर्ण बात है चयन ... अद्यतन के लिए। निराशावादी लॉकिंग बहु-उपयोगकर्ता वातावरण में विशिष्टता की गारंटी देता है। PRAGMA यह सुनिश्चित करता है कि code_control
. को बनाए रखा जाए व्यापक लेनदेन को प्रदूषित नहीं करता है। यह हमें गतिरोध के बिना ट्रिगर में फ़ंक्शन को कॉल करने की अनुमति देता है।
यहाँ आपके जैसी कुंजी वाली एक तालिका है:
create table t42
(year number(4,0) not null
, type varchar2(1) not null
, id number(38,0)
, primary key (year,type, id)
)
/
create or replace trigger t42_trg
before insert on t42 for each row
begin
:new.id := get_next_number(:new.year, :new.type);
end;
/
t42
. को पॉप्युलेट करने से पहले मेरे पास कुछ नहीं है :
SQL> select * from code_control;
no rows selected
SQL> select * from t42;
no rows selected
SQL> insert into t42 (year, type) values (2016, 'A');
1 row created.
SQL> insert into t42 (year, type) values (2016, 'A');
1 row created.
SQL> insert into t42 (year, type) values (2016, 'A');
1 row created.
SQL> insert into t42 (year, type) values (2016, 'B');
1 row created.
SQL> insert into t42 (year, type) values (2016, 'A');
1 row created.
SQL> insert into t42 (year, type) values (2017, 'A');
1 row created.
SQL> select * from t42;
YEAR T ID
---------- - ----------
2016 A 1
2016 A 2
2016 A 3
2016 A 4
2016 B 1
2017 A 1
6 rows selected.
SQL> select * from code_control;
YEAR T LAST_NUMBER
---------- - -----------
2016 A 4
2016 B 1
2017 A 1
SQL>
तो इस कार्यान्वयन के लिए स्पष्ट आपत्ति मापनीयता है। सम्मिलित लेनदेन code_control
. पर क्रमबद्ध हैं मेज़। यह बिल्कुल सच है। हालांकि लॉक को कम से कम समय के लिए रखा जाता है, इसलिए यह कोई समस्या नहीं होनी चाहिए, भले ही t42
तालिका एक सेकंड में कई बार भर जाती है।
हालाँकि, यदि तालिका बड़ी संख्या में समवर्ती आवेषण के अधीन है, तो लॉकिंग एक मुद्दा बन सकता है। यह महत्वपूर्ण है कि समवर्ती मांगों को पूरा करने के लिए तालिका में पर्याप्त इच्छुक लेनदेन स्लॉट (INITRANS, MAXTRANS) हैं। लेकिन बहुत व्यस्त प्रणालियों को एक बेहतर कार्यान्वयन की आवश्यकता हो सकती है (शायद बैचों में आईडी उत्पन्न करना); अन्यथा एक अनुक्रम के पक्ष में यौगिक कुंजी को छोड़ दें (क्योंकि अनुक्रम बहु-उपयोगकर्ता वातावरण में बड़े पैमाने पर होते हैं)।