Oracle 触发器给出未知错误
Oracle trigger gives unknown error
我有这个 SQL 触发器,工作正常:
USE [DMS_TEST]
GO
IF EXISTS (SELECT object_name(id) FROM sysobjects
WHERE xtype ='TR' AND object_name(id) = N'TR_SALESSTATUS_CHANGE')
DROP TRIGGER [TR_SALESSTATUS_CHANGE]
GO
CREATE TRIGGER [TR_SALESSTATUS_CHANGE] ON [VM_SDetail]
FOR UPDATE
AS
BEGIN
Set NoCount On
UPDATE [VM_SDetail]
SET SALESSTATUS = 1
From [VM_SDetail]
[VM_SDetail]
INNER JOIN INSERTED
ON [VM_SDetail].ID = INSERTED.ID
Where (Not Inserted.ValueVal Is NULL AND (Inserted.ValueVal <> ''))
AND Inserted.SALESSTATUS = 0;
End
GO
我将此触发器转换为 Oracle:
CREATE OR REPLACE TRIGGER TR_SALESSTATUS_CHANGE AFTER UPDATE
ON DMS_TEST.VM_SDetail
FOR EACH ROW
BEGIN
UPDATE DMS_TEST.VM_SDetail
SET SaleStatus = 1
From DMS_TEST.VM_SDetail
INNER JOIN :NEW
ON DMS_TEST.VM_SDetail.ID = :NEW.ID
Where (Not :NEW.ValueVal Is NULL AND (:NEW.ValueVal <> ''))
AND :NEW.SalesStatus = 0;
End;
我收到此警告并且触发器未按预期工作:
Warning: TRIGGER created with compilation errors.
我正在使用 TOAD。
我已经尝试了两天了。我试图消除和简化触发器,但即使使用简单的更新命令也无法正常工作。
关于错误的任何想法或任何可以给我更多错误消息或详细信息的工具?
谢谢
首先,如果您在 SQL*Plus
中键入 "show errors",您将得到实际的错误。其次,您不能加入 :new
伪记录。这不是 table。第三,您几乎肯定不想在 VM_SDetail
上的行级触发器中查询 VM_SDetail
。假设 id
是 table 的主键,我猜你只想设置 :new.SaleStatus
CREATE OR REPLACE TRIGGER TR_SALESSTATUS_CHANGE AFTER UPDATE
ON DMS_TEST.VM_SDetail
FOR EACH ROW
BEGIN
IF( (Not :NEW.ValueVal Is NULL AND (:NEW.ValueVal <> ''))
AND :NEW.SalesStatus = 0 )
THEN
:new.SalesStatus := 1;
END IF;
END;
您还可以将 IF
语句放在触发器的 WHEN
子句中,这样触发器就不会真正触发,除非满足条件。那么触发主体就是 :new.SalesStatus := 1;
行。
我还应该指出,在 Oracle 中,空字符串等同于 NULL
,因此没有必要检查 ValueVal
既是 NOT NULL
又不等于空字符串。直接说
更有意义
IF( :new.ValueVal IS NOT NULL and
:new.SalesStatus = 0 )
THEN
使用 F9 执行它(Execute/compile 插入符号处的语句)。它是编辑器工具栏上最左边的按钮,带有绿色播放按钮。您正在使用 F5 作为脚本执行它。正如 Justin Cave 指出的那样,这需要 SHOW ERRORS,但是作为脚本执行应该保留用于脚本执行(超过 1 个语句)或当您想要模拟 SQL*Plus 行为时。单语句执行、编译对象等最好使用 F9 来完成。它会自动获取许多其他内容中的错误。
我有这个 SQL 触发器,工作正常:
USE [DMS_TEST]
GO
IF EXISTS (SELECT object_name(id) FROM sysobjects
WHERE xtype ='TR' AND object_name(id) = N'TR_SALESSTATUS_CHANGE')
DROP TRIGGER [TR_SALESSTATUS_CHANGE]
GO
CREATE TRIGGER [TR_SALESSTATUS_CHANGE] ON [VM_SDetail]
FOR UPDATE
AS
BEGIN
Set NoCount On
UPDATE [VM_SDetail]
SET SALESSTATUS = 1
From [VM_SDetail]
[VM_SDetail]
INNER JOIN INSERTED
ON [VM_SDetail].ID = INSERTED.ID
Where (Not Inserted.ValueVal Is NULL AND (Inserted.ValueVal <> ''))
AND Inserted.SALESSTATUS = 0;
End
GO
我将此触发器转换为 Oracle:
CREATE OR REPLACE TRIGGER TR_SALESSTATUS_CHANGE AFTER UPDATE
ON DMS_TEST.VM_SDetail
FOR EACH ROW
BEGIN
UPDATE DMS_TEST.VM_SDetail
SET SaleStatus = 1
From DMS_TEST.VM_SDetail
INNER JOIN :NEW
ON DMS_TEST.VM_SDetail.ID = :NEW.ID
Where (Not :NEW.ValueVal Is NULL AND (:NEW.ValueVal <> ''))
AND :NEW.SalesStatus = 0;
End;
我收到此警告并且触发器未按预期工作:
Warning: TRIGGER created with compilation errors.
我正在使用 TOAD。 我已经尝试了两天了。我试图消除和简化触发器,但即使使用简单的更新命令也无法正常工作。 关于错误的任何想法或任何可以给我更多错误消息或详细信息的工具?
谢谢
首先,如果您在 SQL*Plus
中键入 "show errors",您将得到实际的错误。其次,您不能加入 :new
伪记录。这不是 table。第三,您几乎肯定不想在 VM_SDetail
上的行级触发器中查询 VM_SDetail
。假设 id
是 table 的主键,我猜你只想设置 :new.SaleStatus
CREATE OR REPLACE TRIGGER TR_SALESSTATUS_CHANGE AFTER UPDATE
ON DMS_TEST.VM_SDetail
FOR EACH ROW
BEGIN
IF( (Not :NEW.ValueVal Is NULL AND (:NEW.ValueVal <> ''))
AND :NEW.SalesStatus = 0 )
THEN
:new.SalesStatus := 1;
END IF;
END;
您还可以将 IF
语句放在触发器的 WHEN
子句中,这样触发器就不会真正触发,除非满足条件。那么触发主体就是 :new.SalesStatus := 1;
行。
我还应该指出,在 Oracle 中,空字符串等同于 NULL
,因此没有必要检查 ValueVal
既是 NOT NULL
又不等于空字符串。直接说
IF( :new.ValueVal IS NOT NULL and
:new.SalesStatus = 0 )
THEN
使用 F9 执行它(Execute/compile 插入符号处的语句)。它是编辑器工具栏上最左边的按钮,带有绿色播放按钮。您正在使用 F5 作为脚本执行它。正如 Justin Cave 指出的那样,这需要 SHOW ERRORS,但是作为脚本执行应该保留用于脚本执行(超过 1 个语句)或当您想要模拟 SQL*Plus 行为时。单语句执行、编译对象等最好使用 F9 来完成。它会自动获取许多其他内容中的错误。