【问题标题】:ORACLE trigger instead of insert on view with a nested tableORACLE 触发器而不是使用嵌套表在视图上插入
【发布时间】:2017-05-26 06:13:47
【问题描述】:

我必须写一个触发器。它编译一切,但如果我想在我的视图中插入一些东西,我会收到一条错误消息。也许你能帮帮我。

SET DEFINE off;
CREATE OR REPLACE TRIGGER LieferantOV_trig

INSTEAD OF INSERT
ON LIEFERANT_OV
FOR EACH ROW
BEGIN 
  IF INSERTING THEN
  INSERT INTO Lieferant (LiefNr, Name, Adresse)  
  VALUES(:new.LiefNr, :new.Name, ntTAdresse());

  INSERT INTO TABLE (SELECT Adresse FROM Lieferant  ) VALUES
  (TAdresse(:new.Straße, :new.PLZ, :new.Ort));

  END IF;
  END;

INSERT INTO Lieferant_OV 
VALUES(752443, 'Laepple Teublitz', 'Maxstr. 12', '93158', 'Teublitz');

对于嵌套表

CREATE OR REPLACE TYPE TAdresse AS OBJECT(
Straße VARCHAR2(50),
PLZ VARCHAR2(5),
Ort VARCHAR2(50)
);



CREATE TABLE Lieferant(
LiefNr number(6) PRIMARY KEY,
Name varchar2(20) NOT NULL
);
1.
CREATE OR REPLACE TYPE ntTAdresse AS TABLE OF TAdresse;
2.
ALTER TABLE Lieferant ADD Adresse ntTAdresse NESTED TABLE Adresse STORE AS TAdresseNT;


CREATE OR REPLACE VIEW Lieferant_OV (LiefNr, Name, Straße, PLZ, ORT) 
AS SELECT k.LiefNr, k.Name, l.Straße, l.PLZ, l.Ort 
FROM Lieferant k, table(k.Adresse) l;

【问题讨论】:

  • 你得到什么错误?
  • 嘿,我添加了更多代码。收到此错误:SQL-ERROR: ORA-04098: Trigger 'S74040.LIEFERANT_OV_TRIG' ist ungültig und konnte nicht neu bestätigt werden 04098. 00000 - “trigger '%s.%s' is invalid and failed re-validation”
  • 要插入一行吗?
  • 是的,先生。如果我在没有触发器的情况下插入它,它可以工作。
  • 如果您已经有 752443 LeifNr 的行怎么办?你想更新行吗?

标签: oracle view triggers


【解决方案1】:

语法应该是这样的:

CREATE OR REPLACE TRIGGER LieferantOV_trig
   INSTEAD OF INSERT
   ON LIEFERANT_OV
   FOR EACH ROW
BEGIN 
   INSERT INTO Lieferant (LiefNr, Name, Adresse)  
   VALUES(:new.LiefNr, :new.Name, ntTAdresse(TAdresse(:new.Straße,:new.PLZ,:new.ORT));

END;

您可以跳过IF INSERTING THEN,因为您的触发器仅在INSERT 上触发

注意,每条记录最多只有一个地址,因此嵌套表没有多大意义。

要向现有的 Lieferant 添加地址,您可以这样做:

CREATE OR REPLACE TRIGGER LieferantOV_trig
   INSTEAD OF INSERT
   ON LIEFERANT_OV
   FOR EACH ROW

DECLARE
   lieferantCount INTEGER;
BEGIN 

   select count(*) 
   into lieferantCount 
   from Lieferant 
   where LiefNr = :new.LiefNr
       and Name = :new.Name;

   if lieferantCount = 0 then
      INSERT INTO Lieferant (LiefNr, Name, Adresse)  
      VALUES(:new.LiefNr, :new.Name, ntTAdresse(TAdresse(:new.Straße,:new.PLZ,:new.ORT)));
   else
      UPDATE Lieferant 
      SET Adresse = Adresse MULTISET UNION ntTAdresse(TAdresse(:new.Straße,:new.PLZ,:new.ORT))
      WHERE LiefNr = :new.LiefNr
         and Name = :new.Name;
   end if;

END;

【讨论】:

    【解决方案2】:

    如果您想每次插入保留一行,我想您应该这样做。

    CREATE OR REPLACE TRIGGER LieferantOV_trig
    
    INSTEAD OF INSERT
    ON LIEFERANT_OV
    FOR EACH ROW
    BEGIN
      INSERT INTO Lieferant (LiefNr, Name, Adresse)  
      VALUES(:new.LiefNr, :new.Name, ntTAdresse(TAdresse(:new.Straße, :new.PLZ, :new.Ort)));
    END;
    /
    

    如果 Adresse 列仅包含一个地址,则此方法有效。但这不是嵌套表的目的。因此,您可能想检查表中是否存在具有给定 LiefNr 的现有行。如果是,则只插入到嵌套表中。

    【讨论】:

    • 好的,谢谢。不,此触发器在此表单中也没有错误地编译。我有这个几乎一样。但是,如果我在视图中插入这样的行,也会出现错误:INSERT INTO Lieferant_OV VALUES(752443, 'Laepple Teublitz', 'Maxstr. 12', '93158', 'Teublitz');
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多