我希望我的表根據它的TEMPLATE_ID對它的「order by」列進行排序。 我希望這發生在插入(可能通過插入觸發器)。 例如,如果我運行下面的插入,我應該得到下面的表值。在插入時初始化子序列列值。 (Oracle)
INSERT INTO TEMPLATE_ATTRIBUTES (ID, TEMPLATE_ID) VALUES (1, 1)
INSERT INTO TEMPLATE_ATTRIBUTES (ID, TEMPLATE_ID) VALUES (2, 1)
INSERT INTO TEMPLATE_ATTRIBUTES (ID, TEMPLATE_ID) VALUES (3, 1)
INSERT INTO TEMPLATE_ATTRIBUTES (ID, TEMPLATE_ID) VALUES (4, 2)
INSERT INTO TEMPLATE_ATTRIBUTES (ID, TEMPLATE_ID) VALUES (5, 2)
INSERT INTO TEMPLATE_ATTRIBUTES (ID, TEMPLATE_ID) VALUES (6, 2)
INSERT INTO TEMPLATE_ATTRIBUTES (ID, TEMPLATE_ID) VALUES (7, 2)
INSERT INTO TEMPLATE_ATTRIBUTES (ID, TEMPLATE_ID) VALUES (8, 3)
ID TEMPLATE_ID ORDER_BY
1 1 1
2 1 2
3 1 3
4 2 1
5 2 2
6 2 3
7 2 4
8 3 1
我第一次試圖創建這個觸發器,但是當我插入時它給了我一個錯誤。
create or replace
trigger TEMPLATE_ATTRIBUTES_AF_INS_TRIG
after insert on TEMPLATE_ATTRIBUTES
for each row
begin
if :NEW.ORDER_BY is null then
update TEMPLATE_ATTRIBUTES
set ORDER_BY = (select coalesce(MAX(ta.ORDER_BY), 0) + 1 from TEMPLATE_ATTRIBUTES ta where ta.TEMPLATE_ID = :NEW.TEMPLATE_ID)
where ID = :NEW.ID;
end if;
end;
它給我的錯誤是:「表TEMPLATE_ATTRIBUTES都在變異,觸發/功能可能沒看出來」
所以我需要一個不同的方式來建立這個觸發器。而且我也需要它「線程安全的」,因此,如果這兩個刀片在同一時間在不同的會話發生,那麼所產生的記錄仍然會得到不同的「ORDER_BY」值:
INSERT INTO TEMPLATE_ATTRIBUTES (ID, TEMPLATE_ID) VALUES (1, 1)
INSERT INTO TEMPLATE_ATTRIBUTES (ID, TEMPLATE_ID) VALUES (2, 1)
編輯:
我嘗試了「表變異,觸發器/函數可能看不到它」和周圍的工作「工作」,但它不是「線程安全的」共同的工作。我試圖添加鎖,但它給了我另一個錯誤上插入
create or replace package state_pkg
as
type ridArray is table of rowid index by binary_integer;
newRows ridArray;
empty ridArray;
end;
create or replace trigger TEMPLATE_ATTRIBUTES_ORDER_BY_TB4
before insert on TEMPLATE_ATTRIBUTES
begin
state_pkg.newRows := state_pkg.empty;
end;
create or replace trigger TEMPLATE_ATTRIBUTES_ORDER_BY_TAF1
after insert on TEMPLATE_ATTRIBUTES for each row
begin
if :NEW.ORDER_BY is null then
state_pkg.newRows(state_pkg.newRows.count+1) := :new.rowid;
end if;
end;
create or replace trigger TEMPLATE_ATTRIBUTES_ORDER_BY_TAF2
after insert on TEMPLATE_ATTRIBUTES
declare
v_request number;
v_lockhandle varchar2(200);
begin
dbms_lock.allocate_unique('TEMPLATE_ATTRIBUTES_ORDER_BY_lock', v_lockhandle);
while v_request <> 0 loop
v_request:= dbms_lock.request(v_lockhandle, dbms_lock.x_mode);
end loop;
begin
for i in 1 .. state_pkg.newRows.count loop
update TEMPLATE_ATTRIBUTES
set ORDER_BY = (select coalesce(MAX(q.ORDER_BY), 0) + 1 from TEMPLATE_ATTRIBUTES q where q.TEMPLATE_ID = (select q2.TEMPLATE_ID from TEMPLATE_ATTRIBUTES q2 where q2.rowid = state_pkg.newRows(i)))
where rowid = state_pkg.newRows(i);
end loop;
v_request:= dbms_lock.release(v_lockhandle);
EXCEPTION WHEN OTHERS THEN
v_request:= dbms_lock.release(v_lockhandle);
raise;
end;
end;
這給了我:
ORA-04092:在觸發ORA-06512不能承諾:在「SYS.DBMS_LOCK」,行250 ORA-06512:在 「TEMPLATE_ATTRIBUTES_ORDER_BY_TAF2」,第5行ORA-04088:觸發的執行期間錯誤 'TEMPLATE_ATTRIBUTES_ORDER_BY_TAF2' ORA-06512
編輯2: 的ORDER_BY列必須是一個可更新的塔。 ID實際上使用了一個序列,並在插入觸發器之前設置其值。當我將它包含在插入示例中時,我認爲我正在簡化我的問題,但這是不正確的。 ORDER_BY的初始值並非真正與ID相關,而是與記錄的插入順序有關。但是ID是按順序排列的,所以你可以使用它,如果它有幫助。
鏡像:https://forums.oracle.com/forums/thread.jspa?threadID=2455159 – Joel
你找到了這個問題的解決theadsafe? –
我沒有找到線程安全解決方案。 – Joel