目前,我有一个表格,如下所示:
Year | Branch_Code | Registration_Number | ...
______________________________________________
2018 | BRANCH1 | 1 | ...
2018 | BRANCH1 | 2 | ...
2018 | BRANCH2 | 1 | ...
因此,每当我将数据插入表中时,我都希望注册编号自动增加,并依赖于Year和Branch_Code。我尝试先获取最大值,然后再插入,但是如果我的客户同时插入,有时会插入重复的数字。
有人有什么解决办法吗?
P.S。我正在使用Laravel Framework和Oracle Database。
答案 0 :(得分:1)
我建议您使用序列,不要再担心了。
或者,您可以尝试使用以下方法:
regnum
),该表包含[year,branch_code]组合的最后一个registration_number
COMMIT
不会影响主交易)yourt
)方法如下:
表格优先:
SQL> create table yourt (year number, branch_code varchar2(20), registration_number number, datum date);
Table created.
SQL> create table regnum (year number, branch_code varchar2(20), registration_number number);
Table created.
功能
:SQL> create or replace function f_regnum (par_year in number, par_branch_code in varchar2)
2 return number
3 is
4 pragma autonomous_transaction;
5 l_nextval number;
6 begin
7 select registration_number + 1
8 into l_nextval
9 from regnum
10 where year = par_year
11 and branch_code = par_branch_code
12 for update of registration_number;
13
14 update regnum set
15 registration_number = l_nextval
16 where year = par_year
17 and branch_code = par_branch_code;
18
19 commit;
20 return (l_nextval);
21
22 exception
23 when no_data_found then
24 lock table regnum in exclusive mode;
25
26 insert into regnum (year, branch_code, registration_number)
27 values (par_year, par_branch_code, 1);
28
29 commit;
30 return(1);
31 end;
32 /
Function created.
触发器:
SQL> create or replace trigger trg_bi_yourt
2 before insert on yourt
3 for each row
4 begin
5 :new.registration_number := f_regnum(:new.year, :new.branch_code);
6 end;
7 /
Trigger created.
测试:
SQL> insert into yourt (year, branch_code, datum) values (2017, 'branch 1', date '2017-01-01');
1 row created.
SQL> insert into yourt (year, branch_code, datum) values (2017, 'branch 1', date '2017-01-25');
1 row created.
SQL> insert into yourt (year, branch_code, datum) values (2017, 'branch 2', date '2017-04-14');
1 row created.
SQL> insert into yourt (year, branch_code, datum) values (2018, 'branch 3', date '2018-07-11');
1 row created.
SQL> insert into yourt (year, branch_code, datum) values (2018, 'branch 1', date '2018-05-21');
1 row created.
SQL> insert into yourt (year, branch_code, datum) values (2018, 'branch 3', date '2018-03-14');
1 row created.
SQL> insert into yourt (year, branch_code, datum) values (2018, 'branch 3', date '2018-05-17');
1 row created.
结果:
SQL> select * from yourt order by branch_code, year;
YEAR BRANCH_CODE REGISTRATION_NUMBER DATUM
---------- -------------------- ------------------- ----------
2017 branch 1 2 2017-01-25
2017 branch 1 1 2017-01-01
2018 branch 1 1 2018-05-21
2017 branch 2 1 2017-04-14
2018 branch 3 2 2018-03-14
2018 branch 3 3 2018-05-17
2018 branch 3 1 2018-07-11
7 rows selected.
SQL> select * from regnum order by branch_code, year;
YEAR BRANCH_CODE REGISTRATION_NUMBER
---------- -------------------- -------------------
2017 branch 1 2
2018 branch 1 1
2017 branch 2 1
2018 branch 3 3
SQL>
该解决方案将在多用户环境中运行,不会引发变异表错误,但是如果您加载大量的代码,性能可能会受到影响行一次(例如,使用SQL * Loader)。再次使用序列。
答案 1 :(得分:0)
我认为,使用自动增量触发器或其他过程来维持Registration_Number
列的完整性是毫无价值的,我的意思是可能会存在类似delete/ update
之类的操作,而这些操作很难使用这样的设置进行跟踪。我宁愿使用更简单的方法并创建视图
CREATE OR replace VIEW view_t
AS
SELECT year,
branch_code,
row_number()
over (
PARTITION BY year, branch_code
ORDER BY NULL) AS REGISTRATION_NUMBER
FROM t;
这样,当您查询视图时,registration_number将“自动”包含所需的编号,您可能希望将其用于显示或从外部应用程序使用。
答案 2 :(得分:0)
感谢一个告诉我创建before insert
触发器的人(由于他删除了答案,我不记得他的名字)。我尝试创建一个,它就像一个吊饰。
CREATE OR REPLACE TRIGGER TRIGGER_NAME
BEFORE INSERT ON TABLE_NAME
FOR EACH ROW
BEGIN
SELECT NVL(MAX(REGISTRATION_NUMBER), 0) + 1
INTO :NEW.REGISTRATION_NUMBER
FROM TABLE_NAME
WHERE TABLE_NAME.YEAR = :NEW.YEAR
AND TABLE_NAME.BRANCH_CODE = :NEW.BRANCH_CODE;
END;