2016-09-23 46 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