oracle - SQL 数据库触发器 ORA-00904
问题描述
如果预订评估编号为 2,我正在尝试将客户名称、开始日期和船名输入审核表。当我使用的名称在预订表中时,我收到无效标识符错误。现在,我只是想在审计表中获取客户名称,因此在其他列中为空。
这是我的代码,我看不到哪里出错了:
CREATE OR REPLACE TRIGGER EVALUATION
BEFORE INSERT OR UPDATE OR DELETE ON BOOKING
FOR EACH ROW
WHEN (NEW.BOOKING_EVALUATION = 2)
DECLARE
custname VARCHAR(20);
sdate DATE;
shname VARCHAR(50);
BEGIN
SELECT CUSTOMER_NAME INTO custname FROM customer WHERE CUSTOMER_NAME = NEW.CUSTOMER_NAME;
IF INSERTING THEN
INSERT INTO EVALUATIONAUDIT (VOYAGES_ID,CUSTOMER_NAME,START_DATE,SHIP_NAME,BOOKING_EVALUATION)
VALUES(:NEW.VOYAGES_ID,custname,NULL,NULL,:NEW.BOOKING_EVALUATION);
END IF;
IF UPDATING THEN
INSERT INTO EVALUATIONAUDIT (VOYAGES_ID,CUSTOMER_NAME,START_DATE,SHIP_NAME,BOOKING_EVALUATION)
VALUES(:OLD.VOYAGES_ID,custname,NULL,NULL,:OLD.BOOKING_EVALUATION);
END IF;
IF DELETING THEN
INSERT INTO EVALUATIONAUDIT (VOYAGES_ID,CUSTOMER_NAME,START_DATE,SHIP_NAME,BOOKING_EVALUATION)
VALUES(:OLD.VOYAGES_ID,custname,NULL,NULL,:OLD.BOOKING_EVALUATION);
END IF;
END;
/
这是我得到的错误:
9/1 PL/SQL:SQL 语句被忽略
9/67 PL/SQL:ORA-00904:“新”。“客户名称”:无效标识符
解决方案
您需要使用NEW
伪记录中的字段,并且由于触发器所针对的表只有 ID,因此您需要使用它进行查找:
SELECT CUSTOMER_NAME
INTO custname
FROM customer
WHERE CUSTOMER_ID = :NEW.CUSTOMER_ID;
请注意 的:
前缀NEW
以及列/字段名称的更改。
IF DELETING
不过,这对分支不太适用,因为NEW
在这种情况下伪记录将为空 - 仅OLD
填充。因此,您需要额外的逻辑来根据触发事件OLD
或NEW
根据触发事件获取客户名称,并且根据您OLD
在UPDATING
分支中使用的情况,您可能也需要旧客户 ID。
出于同样的原因,该WHEN (NEW.BOOKING_EVALUATION = 2)
检查也不适用于删除。
所以你也许可以这样做:
CREATE OR REPLACE TRIGGER EVALUATION
BEFORE INSERT OR UPDATE OR DELETE ON BOOKING
FOR EACH ROW
DECLARE
custname VARCHAR(20);
BEGIN
IF INSERTING AND :NEW.BOOKING_EVALUATION = 2 THEN
SELECT CUSTOMER_NAME
INTO custname
FROM customer
WHERE CUSTOMER_ID = :NEW.CUSTOMER_ID;
INSERT INTO EVALUATIONAUDIT (VOYAGES_ID,CUSTOMER_NAME,START_DATE,SHIP_NAME,BOOKING_EVALUATION)
VALUES(:NEW.VOYAGES_ID,custname,NULL,NULL,:NEW.BOOKING_EVALUATION);
END IF;
IF (UPDATING OR DELETING) AND :OLD.BOOKING_EVALUATION = 2 THEN
SELECT CUSTOMER_NAME
INTO custname
FROM customer
WHERE CUSTOMER_ID = :OLD.CUSTOMER_ID;
INSERT INTO EVALUATIONAUDIT (VOYAGES_ID,CUSTOMER_NAME,START_DATE,SHIP_NAME,BOOKING_EVALUATION)
VALUES(:OLD.VOYAGES_ID,custname,NULL,NULL,:OLD.BOOKING_EVALUATION);
END IF;
END;
/
取决于您是否要记录更新,如果旧的、新的或其中一个BOOKING_EVALUATION
是 2。此版本仅查看您用于插入的其他值,但可以轻松检查其中一个,或者您可以OLD
拆分又出来了UPDATING OR DELETING
。或者您可以将第一个检查更改为:UPDATING
DELETING
...
BEGIN
IF (INSERTING OR UPDATING) AND :NEW.BOOKING_EVALUATION = 2 THEN
...
这取决于您要捕获哪些场景以及要为它们记录哪些值。
如果您收到编译错误,则运行show errors
或查询user_errors
视图以查看实际故障。如果你得到 ORA-04098,那么错误所指的触发器是无效的——它要么是在它被编译的时候,要么是(我认为不太可能)表结构自上次成功编译以来发生了变化。
您可能已经创建了多个触发器。看看输出
select trigger_name, status from user_triggers where table_name = 'BOOKING';
查看该表有多少触发器(尽管它可能在其他地方)以及它们的名称 - 如果有多个触发器,请查看您是否有一个需要删除的不同名称的较早尝试。
看看
select object_name, status from user_objects where object_type = 'TRIGGER';
查看您定义的所有触发器并查找任何无效的触发器。user_triggers
然后,如果从它们的名称中不明显,您可以返回视图以查看它们所针对的表。
但是,无论是无效的,原因都将在user_errors
.
推荐阅读
- asp.net-core - 无法从控制器操作刷新页面(ASP.NET MVC 核心)
- reactjs - 子组件中的useSelector重新渲染父组件
- excel - 从单元格中选择和激活超链接的宏
- json - JSON API 调用:分页循环 - 无法增加偏移值
- angular - 使用数据集和编码 API 更改特定 echarts 条的颜色
- python - Imgur API 返回 HTTP 500 响应
- angular - TypeError:这在 AsyncValidator 中未定义
- swift - 如何创建 twitter 标签栏推送动画
- java - 通配符和泛型方法的区别?[爪哇]
- r - R impute last 按组和按条件结转