当有一个名为timestamp的字段时,Oracle为啥创建触发器失败?

Posted

技术标签:

【中文标题】当有一个名为timestamp的字段时,Oracle为啥创建触发器失败?【英文标题】:Oracle why does creating trigger fail when there is a field called timestamp?当有一个名为timestamp的字段时,Oracle为什么创建触发器失败? 【发布时间】:2008-11-12 17:13:04 【问题描述】:

我刚刚浪费了过去两个小时试图创建一个基于this tutorial 的具有自动递增主键的表,本教程很棒,我遇到的问题是如果创建目标失败我在同一个表中有一个时间戳列和一个称为时间戳的表...

为什么 oracle 在我创建表时不将此标记为问题?

这是我输入的命令序列:

    创建表:

    CREATE TABLE myTable
       (id NUMBER PRIMARY KEY,
        field1 TIMESTAMP(6),
        timeStamp NUMBER,
    );
    

    创建序列:

    CREATE SEQUENCE test_sequence
    START WITH 1
    INCREMENT BY 1;
    

    创建触发器:

    CREATE OR REPLACE TRIGGER test_trigger  
    BEFORE INSERT  
    ON myTable  
    REFERENCING NEW AS NEW  
    FOR EACH ROW  
    BEGIN  
    SELECT test_sequence.nextval INTO :NEW.ID FROM dual;  
    END;  
    /
    

这是我收到的错误消息:

ORA-06552: PL/SQL: Compilation unit analysis terminated
ORA-06553: PLS-320: the declaration of the type of this expression is incomplete or malformed

任何没有包含“时间戳”字样的两行的组合都可以正常工作。我原以为语法足以区分关键字和列名。

正如我所说,我不明白为什么表创建得很好但是当我尝试创建触发器时 oracle 崩溃了......

澄清

我知道问题在于有一个名为 timestamp 的列,它可能是也可能不是关键字。我的问题是为什么它在我尝试创建触发器时而不是在我创建表时出现,我至少会收到警告。

也就是说,使用 Oracle 几个小时后,它的错误报告似乎不那么冗长了,也许只是因为我使用的是 express 版本。

如果这是 Oracle 中的一个错误,没有支持合同的人将如何报告它?我只是在玩 express 版本,因为我必须将一些代码从 mysql 迁移到 Oracle。

【问题讨论】:

如果您有一个较旧的数据库,其中包含一个名为“timestamp”的表列并且您想向其添加触发器,则此问题相对令人沮丧。我还没有找到解决它的方法,我很害怕。我已经使用了 Pablo 的答案来解决类似的时间戳命名问题。 【参考方案1】:

Metalink 上有一个关于此 (227615.1) 摘录的注释:

# symptom: Creating Trigger fails
# symptom: Compiling a procedure fails
# symptom: ORA-06552: PL/SQL: %s
# symptom: ORA-06553: PLS-%s: %s     
# symptom: PLS-320: the declaration of the type of this expression is incomplete or malformed
    # cause: One of the tables being references was created with a column name that is one of the datatypes (reserved key word). Even though the field is not referenced in the PL/SQL SQL statements, this error will still be produced.

    fix:

    Workaround:

    1. Rename the column to a non-reserved word.
    2. Create a view and alias the column to a different name.

【讨论】:

【参考方案2】:

TIMESTAMP 没有在 Oracle 文档中作为保留字列出(这令人惊讶)。

它在 V$RESERVED_WORDS 数据字典视图中列出,但其 RESERVED 标志设置为“N”。

这可能是触发器处理中的错误。我会说这是一个很好的 Oracle 支持。

【讨论】:

【参考方案3】:

你自己已经暗示了答案。您使用 timestamp 作为列名,但它也是关键字。将列名更改为其他名称(例如xtimestamp),然后触发器编译。

【讨论】:

我认为他理解这一点,他的问题是“为什么当我首先使用保留字时 Oracle 没有引发错误?”。好问题,我认为。 是的,我原以为它会在我创建表时而不是在创建触发器时出现。 如果您有一个名为 TIMESTAMP 的列,"DELETE FROM myTable" 也不起作用——您需要将该列重命名为其他名称,执行 DELETE,然后将其重命名。很烦人。【参考方案4】:

好吧,我对此并不完全确定,但我认为这是因为用于操作和访问数据库对象的 SQL 代码由某些解释器解释,与用于解释 PL/SQL 代码的解释器不同。

请记住,SQL 和 PL/SQL 是不同的东西,因此它们的处理方式不同。所以,我认为一个解释器有一些错误,只是不确定哪个是。

【讨论】:

【参考方案5】:

不要让 Oracle 维护视图,而是使用 EXECUTE IMMEDIATE(即,如果“将列重命名为非保留字”不是一个选项。

【讨论】:

【参考方案6】:

您可以通过 EXECUTE IMMEDIATE 执行。它不是更好的方法,而是工作并避免列重命名。

在我的情况下,重命名列将是一种混乱的方式

【讨论】:

以上是关于当有一个名为timestamp的字段时,Oracle为啥创建触发器失败?的主要内容,如果未能解决你的问题,请参考以下文章

mysql timestamp自动更新时间问题

你如何正确地用 NULL 更新 mysql 字段?

Android:当有一个空白的editText字段时,我的应用程序崩溃了

如何在C ++中同步静态字段

CakePHP:当有多个关联记录时如何指定返回字段

mysql中为一个字段添加default值为当前时间,怎么写