触发在记录表中插入新行

时间:2014-04-29 03:33:59

标签: oracle plsql

我有两张桌子。

第一个表是具有架构的路由(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)

我的声明声明有什么问题?

1 个答案:

答案 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,您拥有newold伪行中的所有值:

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    

顺便说一句,将状态值保持为字符串会使它们更难管理,因为您必须始终以完全正确的情况输入所有内容。通常,最好使用带有数字主键的状态代码查找表,并使这些表具有该主状态表的外键。然后您插入键值而不是文本,因此您不必担心案例等,如果措辞发生变化,您只需要在一个地方更新它。当然,你必须加入该表来检索文本值,但这不是一个很大的困难。