Sql 插入时Oracle变异触发器
我正试图在Oracle8i中创建一个包含3个表的小型数据库,并在其上创建两个触发器。 以下是数据库架构: 我已经创建了表:Sql 插入时Oracle变异触发器,sql,oracle,plsql,database-trigger,oracle8i,Sql,Oracle,Plsql,Database Trigger,Oracle8i,我正试图在Oracle8i中创建一个包含3个表的小型数据库,并在其上创建两个触发器。 以下是数据库架构: 我已经创建了表: CREATE TABLE SYSTEM.Invoices( invoice_id NUMBER NOT NULL, invoice_body_xml CLOB NOT NULL, insertTS DATE NOT NULL, modifyTS DATE, PRIMARY
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;
我需要的触发器是:
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表中,我需要发票表中的body_xml,这就是为什么我要使用select创建body_xml
在此之后,当我尝试插入到发票中时,会出现以下错误:
您有一个触发器,在插入发票后触发。这将触发插入
发票\u状态
您还有一个触发器,它在插入INVOICE\u status
后触发,但是在该触发器中,您尝试从表INVOICES
中进行选择-出现错误
将您的语句和任何触发器中的allDML视为one命令。在表中插入任何数据时,不能选择该表
您应该将所有逻辑放入一个存储过程并执行该存储过程。您有一个触发器,它在插入
发票后触发。这将触发插入发票\u状态
您还有一个触发器,它在插入INVOICE\u status
后触发,但是在该触发器中,您尝试从表INVOICES
中进行选择-出现错误
将您的语句和任何触发器中的allDML视为one命令。在表中插入任何数据时,不能选择该表
您应该将所有逻辑放入一个存储过程并执行该过程。如果需要通过触发器完成此操作,那么最好的方法可能是将invoice\u body\u xml
存储在invoice\u status
中,并将其填充到INVOICES
上的触发器中:
CREATE OR REPLACE TRIGGER after_invoice_insert
AFTER INSERT
ON invoices
FOR EACH ROW
BEGIN
INSERT INTO invoice_statuses
( invoice_id, status, insertts, invoice_body_xml )
VALUES
( :new.invoice_id, n'NEW', SYSDATE, :new.invoice_body_xml );
END;
/
CREATE OR REPLACE TRIGGER after_invoice_statuses_insert
AFTER INSERT
ON invoice_statuses
FOR EACH ROW
BEGIN
INSERT INTO open_invoices
( invoice_id, invoice_body_xml, status, transaction_id, transaction_index, insertts )
VALUES
( :new.invoice_id, :new.invoice_body_xml, :new.status, :new.transaction_id, :new.transaction_index, SYSDATE );
END;
/
如果您需要通过触发器实现这一点,那么最好的方法可能是将发票_body_xml
存储在发票_status
中,并将其填充到发票
上的触发器中:
CREATE OR REPLACE TRIGGER after_invoice_insert
AFTER INSERT
ON invoices
FOR EACH ROW
BEGIN
INSERT INTO invoice_statuses
( invoice_id, status, insertts, invoice_body_xml )
VALUES
( :new.invoice_id, n'NEW', SYSDATE, :new.invoice_body_xml );
END;
/
CREATE OR REPLACE TRIGGER after_invoice_statuses_insert
AFTER INSERT
ON invoice_statuses
FOR EACH ROW
BEGIN
INSERT INTO open_invoices
( invoice_id, invoice_body_xml, status, transaction_id, transaction_index, insertts )
VALUES
( :new.invoice_id, :new.invoice_body_xml, :new.status, :new.transaction_id, :new.transaction_index, SYSDATE );
END;
/
我建议您编写一个程序来创建发票,类似于以下内容,而不是试图折叠、旋转和破坏一堆触发器来执行所需的插入、选择等操作:
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_发票中的几个字段,但没有在哪里(据我所知)初始化它们。这可能是你想调查的事情
祝您好运。我建议您编写一个创建发票的过程,类似于以下内容,而不是尝试将一堆触发器折叠、旋转和破坏在一起以执行所需的插入、选择等操作:
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_发票中的几个字段,但没有在哪里(据我所知)初始化它们。这可能是你想调查的事情
祝你好运。Oracle 8i-真的吗?它已经20岁了!您不应该在系统
架构中创建任何用户对象。@WernfriedDomscheit没有帮助。如果您发布此消息,请解释为什么不使用SYSTEM或使用注释来要求澄清。是的,但使用SYSTEM(这是一个具有提升权限的保留内部Oracle帐户,不适用于用户定义的对象)是您MCVE的一部分。永远不要使用SYS或SYSTEM用户创建您自己的表。不要触碰8i-真的吗?它已经20岁了!您不应该在系统
架构中创建任何用户对象。@WernfriedDomscheit没有帮助。如果您发布此消息,请解释为什么不使用SYSTEM或使用注释来要求澄清。是的,但使用SYSTEM(这是一个具有提升权限的保留内部Oracle帐户,不适用于用户定义的对象)是您MCVE的一部分。永远不要使用SYS或SYSTEM用户创建您自己的表。别这样