创建的触发器在唯一值上存在编译错误

Trigger created with compiling errors on unique value

我正在尝试创建一个触发器,每当我对 table 进行插入或更新时检查列的值,columnX 的值必须是唯一的:

tableX(ID, ..., columnX)




CREATE or replace TRIGGER tableX_uk
BEFORE INSERT OR UPDATE ON tableX
FOR EACH ROW
BEGIN
if(:new.columnX in (select T.columnX from tableX T)) then
Raise_Application_Error(-20001, 'Already existing');
end if;
End;

说明触发器创建时编译出错。 我在这里找不到任何错误,有人可以帮我吗?谢谢!

It shows that the trigger is created with compiling errors. I couldn't find any error here

存储的 PL/SQL 的错误可以在 user/all/dba_errors 中找到。 SQL Developer、Toad、PL/SQL Developer 等桌面工具会自动显示它们,但这是它们从中获取详细信息的地方。

DBFiddle

在这种情况下,第一个错误来自

if(:new.columnX in (select t.columnX from tableX t))

这给出了

PLS-00405: subquery not allowed in this context

因为 if x in (select...) 是无效的 PL/SQL 语法。您必须将 select 作为一个单独的步骤执行。修复它会给你至少编译的代码,但仍然不理想:

create or replace trigger tablex_uk_trg
    before insert or update on tablex
    for each row
declare
    l_columnx_check number := 0;
begin
    select count(*) into l_columnx_check
    from   tablex t
    where  t.columnx = :new.columnx
    and    rownum = 1;

    if l_columnx_check > 0 then
        raise_application_error(-20001, 'Value '||:new.columnx||' already exists');
    end if;
end;

这并不理想,因为首先,唯一约束是强制唯一性的更有效和自我记录的方式。

create table tablex (columnx number unique);

或更好

create table tablex (columnx number constraint tablex_uk unique);

或者如果它是主键

create table tablex (columnx number constraint tablex_pk primary key);

现在,任何检查 table 定义的人都会看到唯一约束,优化器将在查询中使用它,它有一个标准错误代码 ORA-00001: unique constraint (WILLIAM.TABLEX_UK) violated 等等。

其次,触发器的 update 部分无论如何都不起作用。 Oracle 不会让行级更新触发查询它自己的 table:

insert into tablex (columnx) values (1);

update tablex set columnx = 1;

ORA-04091: table WILLIAM.TABLEX is mutating, trigger/function may not see it
ORA-06512: at "WILLIAM.TABLEX_UK_TRG", line 4
ORA-04088: error during execution of trigger 'WILLIAM.TABLEX_UK'

DBFiddle

并且在任何情况下,逻辑都缺少一些检查,因为我示例中的更新应该是有效的。但我不会深入探讨如何解决这个问题,因为唯一约束就是您所需要的。