【问题标题】:Trigger Issue : ORA-00905: missing keyword触发问题:ORA-00905:缺少关键字
【发布时间】:2016-09-23 15:29:38
【问题描述】:

我试图在插入某个表(tablea)后满足某个条件后将一条记录插入另一个表(tableb) 所以我创建了一个触发器来检查上述情况, 条件:插入tablea后,检查tablea中price的总和是否大于某个值,如果是,则将tino插入tableb中。

下面的脚本将重现我当前面临的问题.. 需要另一个关注这个问题。

-- 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'

应该运行没有问题

任何指针??

【问题讨论】:

  • 你可能做不到。 A 上的触发器通常不能在没有变异触发器错误的情况下查询 A(这听起来像是您在 cmets 中得到下面的答案)。除非您碰巧有一个手动分区的表,否则您永远不应明确指定分区名称。只需使用谓词,让 Oracle 找出分区。这消除了执行动态 SQL 的需要。如果你想要一个声明性的解决方案,一个带有约束的快速刷新的物化视图会比使用触发器更好,而且它可以在多用户系统中工作。

标签: oracle plsql triggers


【解决方案1】:

INTO v_price 应该是 execute immediate 语句的一部分,而不是动态 SQL 的一部分。

我认为

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

可以简化为

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

甚至更好,

WHERE tino = :tino';

v_tino 作为绑定变量传递,类似于

execute immediate xyz into v_price using v_tino;

【讨论】:

  • EXECUTE IMMEDIATE sql_smt INTO v_price; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); DBMS_OUTPUT.PUT_LINE('QUERY =' || sql_smt); DBMS_OUTPUT.PUT_LINE('PRICE =' ||v_price); 谢谢 Will,但它现在返回 ORA-04091:表 TABLEA 正在变异,触发器/函数可能看不到它。没有看到从那里执行,因为 PRICE 为空
  • 我在查看您的语法问题时错过了那部分。行级触发器不能查询自己的表。
  • 那么我还有什么其他选择
猜你喜欢
  • 2012-07-26
  • 1970-01-01
  • 1970-01-01
  • 2023-01-02
  • 2019-01-18
  • 1970-01-01
  • 2018-06-18
  • 2016-03-12
相关资源
最近更新 更多