【问题标题】:oracle trigger errororacle触发错误
【发布时间】:2011-08-07 13:20:59
【问题描述】:

我有两个表,tableA 和 tableB。我想设置触发器。一旦在tableA中发生插入,它可能会触发tableB中的一些事件。

两个表如下,例如,

  • tableA 列:(product_id、product_name、manufacturer)
  • tableB 列:(buyer, product_id)

我要做的是:在表A中插入一个新行后,如果它的product_name为空,则在表B上触发更新。如果 tableB 中的行与新插入的制造商具有相同的制造商,则将 tableB'product_id 更新为此新插入的 product_id。

CREATE TRIGGER t1     

AFTER INSERT ON tableA    
FOR EACH ROW WHEN (NEW.product_name is NULL)

BEGIN

    UPDATE tableB 
       SET tableB.product_id = :NEW.product_id 
     WHERE tableB.product_id IN (SELECT tableA.product_id 
                                   FROM tableA 
                                  WHERE tableA.manufacture = :NEW.manufacture);

END;

SQL 开发者总是报几个错误:

Error(2,2): PL/SQL: SQL Statement ignored
Error(2,120): PL/SQL: ORA-00933: SQL command not properly ended
Error(2,36): PL/SQL: ORA-00904: "NEW"."product_id": invalid identifier
Error: PLS-00801: internal error [ph2csql_strdef_to_diana:bind]

更新:

CREATE TABLE "tableA"
  (
    "PRODUCT_ID"      NUMBER PRIMARY KEY,
    "PRODUCT_NAME"    VARCHAR2(50 BYTE) DEFAULT NULL,
    "MANUFACTURE" VARCHAR2(50 BYTE) DEFAULT NULL
)

CREATE TABLE "tableB"
(
    "BUYER_ID"      NUMBER PRIMARY KEY,
    "PRODUCT_ID"    NUMBER DEFAULT NULL
)

【问题讨论】:

  • 查看this post,其中有一个与您尝试做的类似的示例。
  • 问题是我认为语法是正确的。我不知道为什么 oracle 会抱怨。
  • 您也可以发布创建表语句吗..?这将有助于重现您的确切问题..
  • 我发布了它们。谢谢
  • 使用存储过程对A进行插入和对B进行条件更新可能会更好。如果以后遇到问题,这种工作很难追溯到触发器。您也可能难以从触发器内的 A 中进行选择 - 我认为不知道 A 上的查询是否会包含当前插入的行,因此 Oracle 不会让您避免歧义。 (但可能取决于版本 - 不确定!)

标签: sql oracle triggers ora-00904 ora-00933


【解决方案1】:

您是同时遇到所有这些错误,还是在尝试不同的事情时遇到不同的错误?如果您在NEW.product_id 之前省略了:,则会出现ORA-00904(可能还有相关的ORA-00933),而PLS-00801 可能来自
之间的空格(即: NEW.product_id。不知道如何您可以同时获得两者。

正如它现在发布的那样,它看起来很好 - 在TRIGGER T1 compiled 之后您是否仍然收到消息Errors: check compiler log - 或者您是否正在查看 SQL Developer 编译器日志窗口中的旧错误?如果您不确定,请在编译器日志窗口中右键单击并在重新运行之前选择“清除”,以查看当前代码真正产生了哪些错误(如果有)。

【讨论】:

    【解决方案2】:

    您已经创建了混合大小写名称“tableA”和“tableB”的表。这在 Oracle 中通常是一种不好的做法,并且在引用代码中的表时会导致问题,因为它们必须以正确的大小写引用,并用双引号括起来:

    CREATE TRIGGER t1     
    
    AFTER INSERT ON "tableA"    
    FOR EACH ROW WHEN (NEW.product_name is NULL)
    
    BEGIN
    
        UPDATE "tableB" 
           SET "tableB".product_id = :NEW.product_id 
         WHERE "tableB".product_id IN (SELECT "tableA".product_id 
                                       FROM "tableA" 
                                      WHERE "tableA".manufacture = :NEW.manufacture);
    
    END;
    

    【讨论】:

    • 由于触发器不会编译时出现类似的不同错误,我假设表名更改不一致以进行发布,并且真实名称必须全部大写。当然值得指出。
    • 是的,这可能不是发布的问题,但是当我尝试使用发布的代码重新创建问题时发生了这种情况。并且这些 CREATE TABLE 语句看起来像是从 SQL Developer 复制和粘贴的,尽管可能真正的表名是在之后以混合大小写的形式输入的。
    【解决方案3】:

    在 SQL*Plus 中,您需要在一行中用 / 终止 CREATE TRIGGER 语句。

    根据您的 SQL 工具,您可能需要使用一些不同的方式来设置备用分隔符。

    【讨论】:

      【解决方案4】:

      修改嵌套选择语句中的 where 子句 from WHERE "tableA".manufacture = :NEW.manufacture 到 WHERE "tableA".manufacture = NEW.manufacture

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-07
        • 2014-11-29
        • 2011-09-16
        • 2017-06-10
        • 2018-11-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多