2016-09-23 49 views
0

我試圖插入一條記錄到另一個表(表B)一旦特定條件插入之後滿足到某個表(表A) 所以我有創建了一個觸發器,檢查上述條件: 條件:插入tablea後,檢查tablea中的價格總和是否大於某個值,如果是,則將tino插入到tableb中。觸發問題:ORA-00905:缺少關鍵字

下面的腳本將重新創建我目前面臨的問題..需要另外支付的眼睛在這個。

-- create the tables 
CREATE TABLE tablea 
(
    tino NUMBER not null, 
    price VARCHAR2(200), 
    dated date 
) 
partition by range (DATED) 
(
partition PART_201608 values less than (TO_DATE(' 2016-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
partition PART_201609 values less than (TO_DATE(' 2016-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), 
partition PART_201610 values less than (TO_DATE(' 2016-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')) 
) 

--INSERT VALUES 
INSERT INTO tablea (tino,price,dated)VALUES('1234567',10,SYSDATE); 
    COMMIT; 
    INSERT INTO tablea (tino,price,dated)VALUES('1234560',20,SYSDATE); 
    COMMIT; 
    -- create table table which once condition is met,, data is written into 
CREATE TABLE tableb(tino number); 


-- CREATE THE TRIGGER 
CREATE OR REPLACE TRIGGER trg1 
AFTER INSERT 
ON tablea 
FOR EACH ROW 

DECLARE 
v_price NUMBER; 
v_partition VARCHAR2(20) := 'PART_'||TO_CHAR(SYSDATE,'YYYYMM'); 
v_tino VARCHAR2(20) := :NEW.tino; 
sql_smt VARCHAR2(1000) := ''; 

BEGIN 
    sql_smt :=' 
     SELECT SUM(price) price INTO v_price 
     FROM tablea PARTITION('||v_partition||') 
     WHERE tino = '||''''||v_tino||''''||''; 

BEGIN 
    EXECUTE IMMEDIATE sql_smt; 
    EXCEPTION 
    WHEN OTHERS THEN 
    DBMS_OUTPUT.PUT_LINE(SQLERRM); 
    DBMS_OUTPUT.PUT_LINE('QUERY='|| sql_smt); 
END; 

--DBMS_OUTPUT.PUT_LINE('PRICE =' || v_price); 

IF v_price >= 15 THEN 
    INSERT INTO tableb (tino) VALUES (v_tino); 
    COMMIT; 
    END IF; 
END; 
    -- test the trigger 
    INSERT INTO tablea(tino,price,dated) VALUES('1234567',10,sysdate); 
    COMMIT; 

應該返回一個ORA-00905:缺少關鍵字

DBMS_OUTPUT.PUT_LINE(SQLERRM); 

返回:

SELECT SUM(price) price INTO v_price 
FROM tablea PARTITION(PART_201609) 
WHERE tino = '1234567' 

這應該沒有問題

任何指針跑了?

+2

你可能不能。 A上的觸發器通常不會查詢A而不會得到突變的觸發器錯誤(這聽起來像您正在對下面的答案進行評論)。除非您碰巧有手動分區表,否則不應該明確指定分區名稱。只需使用謂詞並讓Oracle找出分區即可。這消除了動態SQL的需要。如果你想要一個聲明式的解決方案,一個帶約束的快速刷新的物化視圖比使用觸發器更好,再加上它可以在多用戶系統中工作。 –

回答

1

INTO v_price應該是execute immediate語句的一部分,而不是動態SQL的一部分。

順便說一句,我認爲

WHERE tino = '||''''||v_tino||''''||''; 

可以簡化爲

WHERE tino = '''||v_tino||''''; 

甚至更​​好,

WHERE tino = :tino'; 

v_tino與一些綁定變量像

01年通過
+0

如此??? 'EXECUTE IMMEDIATE sql_smt INTO v_price;' – Wasky

+0

是的 - 只是擴大了我的答案。 –

+0

'EXECUTE IMMEDIATE sql_smt INTO v_price; EXCEPTION 何時其他 DBMS_OUTPUT.PUT_LINE(SQLERRM); DBMS_OUTPUT.PUT_LINE('QUERY ='|| sql_smt); DBMS_OUTPUT.PUT_LINE('PRICE ='|| v_price); '謝謝你,但它現在返回ORA-04091:表TABLEA是變異的,觸發器/函數可能看不到它。沒有看到從那裏執行,因爲PRICE爲null – Wasky