2016-09-23 7 views
0

私は特定の条件が特定のテーブルに挿入した後に満たされた後、別のテーブル(TableBの)にレコードを挿入しようとしています(TABLEA) は、だから私は持っています上記のチェックを行うトリガーを作成しました。 条件:tableaに挿入した後、tableaの価格の合計がある値よりも大きいかどうかを確認し、そうであればtablebにtinoを挿入します。トリガー問題: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は、動的SQLの一部ではなく、execute immediateステートメントの一部である必要があります。

ところで、私は

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

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

あるいはさらに良い、

01のようなものでバインド変数として渡された v_tino

WHERE tino = :tino'; 

に単純化することができると思います

+0

これは? 'EXECUTE IMMEDIATE sql_smt INTO v_price; – Wasky

+0

はい - ちょうど私の答えを広げました。 –

+0

'EXECUTE IMMEDIATE sql_smt INTO v_price; 例外 その他の場合 DBMS_OUTPUT.PUT_LINE(SQLERRM); DBMS_OUTPUT.PUT_LINE( 'QUERY =' || sql_smt); DBMS_OUTPUT.PUT_LINE( 'PRICE =' || v_price); 'ありがとうございますが、ORA-04091が返されます:table TABLEAが突然変異していますが、trigger/functionはそれを見ないかもしれません。 PRICEがヌルであるのでそこから実行されないことがわかりました – Wasky

関連する問題