INSERT

时间:2018-04-17 11:08:14

标签: sql oracle plsql database-trigger oracle8i

我试图在Oracle 8i中创建一个包含3个表的小型数据库,并在它们上面创建两个触发器。 这是数据库模式: db_schema

我创建了表格:

CREATE TABLE SYSTEM.Invoices(
   invoice_id   NUMBER              NOT NULL,
   invoice_body_xml CLOB     NOT NULL,
   insertTS  DATE              NOT NULL,
   modifyTS DATE,   
   PRIMARY KEY (invoice_id))
    TABLESPACE SYSTEM;


CREATE TABLE SYSTEM.Invoice_Statuses(
   invoice_id           NUMBER              NOT NULL,
   status               NVARCHAR2(15)       NOT NULL,
   status_details       CLOB,
   transaction_id       NVARCHAR2(50),
   transaction_index    NUMBER,
   request_id           NVARCHAR2(50),
   insertTS             DATE                NOT NULL,
   CONSTRAINT from_statuses_to_invoices
        FOREIGN KEY(invoice_id)
        REFERENCES SYSTEM.INVOICES(invoice_id))
    TABLESPACE SYSTEM;

CREATE TABLE SYSTEM.Open_Invoices(
    invoice_id          NUMBER              NOT NULL,
    invoice_body_xml    CLOB                NOT NULL,
    status              NVARCHAR2(15)       NOT NULL,
    transaction_id      NVARCHAR2(50),
    transaction_index   NUMBER,
    insertTS            DATE                NOT NULL,
   CONSTRAINT from_open_to_invoices
        FOREIGN KEY(invoice_id)
        REFERENCES SYSTEM.INVOICES(invoice_id))
    TABLESPACE SYSTEM;

我需要的TRIGGERS:

CREATE OR REPLACE TRIGGER after_invoice_insert
AFTER INSERT
   ON SYSTEM.INVOICES
   FOR EACH ROW

BEGIN
   INSERT INTO SYSTEM.INVOICE_STATUSES
   (INVOICE_ID,
   STATUS,
   INSERTTS)
   VALUES
   ( 
    :NEW.invoice_id,
    n'NEW',
    SYSDATE);
END;

另一个:

CREATE OR REPLACE TRIGGER after_invoice_statuses_insert
AFTER INSERT
   ON SYSTEM.INVOICE_STATUSES
   FOR EACH ROW
DECLARE
    body_xml CLOB;

BEGIN
   SELECT SYSTEM.INVOICES.invoice_body_xml INTO body_xml FROM SYSTEM.INVOICES WHERE SYSTEM.INVOICES.invoice_id = :NEW.invoice_id;
   INSERT INTO SYSTEM.OPEN_INVOICES
   (INVOICE_ID,
   INVOICE_BODY_XML,
   STATUS,
   TRANSACTION_ID,
   TRANSACTION_INDEX,
   INSERTTS)
   VALUES
   ( 
    :NEW.invoice_id,
    body_xml,
    :NEW.status,
    :NEW.transaction_id,
    :NEW.transaction_index,
    SYSDATE);
END;

如您所见,在OPEN_INVOICES表中,我需要来自INVOICES表的body_xml,这就是我想用select创建body_xml的原因。

在此之后,当我尝试插入发票时,我收到此错误: sqlerror

3 个答案:

答案 0 :(得分:3)

你有一个触发器,它会在插入INVOICES后触发。这会触发插入INVOICE_STATUSES

你还有一个触发器,它会在INVOICE_STATUSES后插入,但是在这个触发器中你试图从表INVOICES中选择 - 你得到错误。

在任何触发器中将您的声明和所有 DML视为一个命令。在其中插入任何数据时,无法选择表。

您应该将所有逻辑放入存储过程并执行该过程。

答案 1 :(得分:0)

如果您需要通过触发器完成此操作,那么最好的方法是将with存储在invoice_body_xml中,并在INVOICE_STATUSES的触发器中填充它:

INVOICES

答案 2 :(得分:0)

我建议你不要试图折叠,转动和毁坏一堆触发器来完成所需的INSERT,SELECT等,我建议您编写一个程序来创建类似于以下的发票:

CREATE OR REPLACE PROCEDURE CREATE_INVOICE
  (pinInvoice_id       IN NUMBER,
   pinInvoice_body_xml IN CLOB)
IS
BEGIN
  INSERT INTO INVOICES
    (INVOICE_ID,
     INVOICE_BODY,
     INSERTTS)
  VALUES
    (pinInvoice_id,
     pinInvoice_body_xml,
     SYSDATE);

  INSERT INTO INVOICE_STATUSES
    (INVOICE_ID,
     STATUS,
     INSERTTS)
  VALUES
    (pinInvoice_id,
     n'NEW',
     SYSDATE);

  INSERT INTO OPEN_INVOICES
    (INVOICE_ID,
     INVOICE_BODY_XML,
     STATUS,
     TRANSACTION_ID,
     TRANSACTION_INDEX,
     INSERTTS)
  VALUES
   (pinInvoice_id,
    pinInvoice_body_xml,
    n'NEW',
    ???,  -- don't know where this comes from
    ???,  -- don't know where this comes from
    SYSDATE);
END CREATE_INVOICE;

您可能仍希望使用触发器来设置INSERTTS和MODIFYTS等字段。

在执行此操作时,我发现需要设置OPEN_INVOICES中的几个字段,但是在初始化时没有(据我所知)。这可能是您想要研究的内容。

祝你好运。