我有两张桌子。
第一个表是具有架构的路由(Train_Number,Route_Status,Time_Status,Route_TM,Departure,Destination),第二个表是带有架构的记录(Train_Number,Time_Status,Route_TM,Departure,Destination)。
我需要一个触发器,以便当路线状态从' En-Route'到达'到达时,它会将路径中的(Train_Number,Time_Status,Date,Departure,Destination)记录到记录中。
同样在游戏中是另一个带有架构的配置表(名称,值)。特别是,在该表中,我有(' Enable_Logging',' T')
以下是我对此触发器的尝试:
CREATE OR REPLACE TRIGGER Train_Logging
AFTER UPDATE OF Route_Status ON Routes
FOR EACH ROW
WHEN (new.route_status = 'Arrived' AND old.route_status = 'En-Route')
DECLARE
logging_flag Configuration.value%type;
BEGIN
SELECT Configuration.value INTO logging_flag FROM Configuration WHERE Configuration = 'Enable_Logging';
IF (logging_flag = 'T') THEN INSERT INTO Records (Train_Number, Time_Status, Date, Departure, Destination) VALUES (SELECT Train_Number, Time_Status, Date, Departure, Destination FROM Routes);
END IF;
END Train_Logging;
我的错误是 " PL / SQL语句被忽略" (在logging_flag Configuration.value%type;) 并且" ORA-00936缺少表达" (在BEGIN)
我的声明声明有什么问题?
答案 0 :(得分:1)
如上所述忽略您的架构问题 - 您似乎有一个名为date
的字段是不允许的,除非它被引用,并且您正在检查status
字段您所显示的表格描述不存在,并且您在configuration.configuration
而不是select
中引用了configuration.name
- 稍微调整一下就会出现错误堆栈如:
8/122 PL/SQL: ORA-00936: missing expression
8/30 PL/SQL: SQL Statement ignored
第8行似乎是logging_flag
声明;但实际上错误中的行号是指PL / SQL块,而不是之前的触发器定义,因此第8行实际上是语句中的第14行。如果您将该行拆分,以便insert
转到新行,并且values
也转到新行,则堆栈变为:
10/9 PL/SQL: ORA-00936: missing expression
9/1 PL/SQL: SQL Statement ignored
所以insert
被忽略了,因为values
子句出了问题。如果您确实要从选择中插入,则根本不会使用values
关键字;你做了:
INSERT INTO Records (Train_Number, Time_Status, Train_Date,
Departure, Destination)
SELECT Train_Number, Time_Status, Train_Date, Departure, Destination
FROM Routes;
(您可以在select
子句中使用values
,但只能获得单个值,然后它会在另一组括号中使用,而这不是您想要的此处。)
但是您不希望或需要从您插入的表格中进行选择。您的select
没有where
子句,因此您每次更新任何行时都会将整个routes
表复制到records
表中,这肯定不是;你想要什么。您只想复制受更新影响的特定行。但是,您不需要select
,您拥有new
和old
伪行中的所有值:
INSERT INTO Records (Train_Number, Time_Status, Train_Date,
Departure, Destination)
VALUES (:NEW.Train_Number, :NEW.Time_Status, :NEW.Train_Date,
:NEW.Departure, :NEW.Destination);
假设您的date
列真的被称为train_date
,并且您想要检查route_status
是否已更改,则它将如下所示:
CREATE OR REPLACE TRIGGER Train_Logging
AFTER UPDATE OF Route_Status ON Routes
FOR EACH ROW
WHEN (new.route_status = 'Arrived' AND old.route_status = 'En-Route')
DECLARE
logging_flag Configuration.value%type;
BEGIN
SELECT Configuration.value
INTO logging_flag
FROM Configuration
WHERE Name = 'Enable_Logging';
IF (logging_flag = 'T') THEN
INSERT INTO Records (Train_Number, Time_Status, Train_Date,
Departure, Destination)
VALUES (:NEW.Train_Number, :NEW.Time_Status, :NEW.Train_Date,
:NEW.Departure, :NEW.Destination);
END IF;
END Train_Logging;
/
使用一些补充数据并猜测一些数据类型:
insert into configuration values ('Enable_Logging', 'T');
insert into routes values (1, 'En-Route', 'On-time', trunc(sysdate),
trunc(sysdate) + 10/24, 'New York');
update routes set route_status = 'Arrived' where train_number = 1;
select * from records;
TRAIN_NUMBER TIME_STATUS TRAIN_DATE DEPARTURE DESTINATION
------------ ----------- ---------- --------- -----------
1 On-time 29-APR-14 29-APR-14 New York
顺便说一句,将状态值保持为字符串会使它们更难管理,因为您必须始终以完全正确的情况输入所有内容。通常,最好使用带有数字主键的状态代码查找表,并使这些表具有该主状态表的外键。然后您插入键值而不是文本,因此您不必担心案例等,如果措辞发生变化,您只需要在一个地方更新它。当然,你必须加入该表来检索文本值,但这不是一个很大的困难。