[英]PL/SQL Trigger BEFORE INSERT based on values in the changing table
所以我有这个问题。
如果客户在插入每一行之前已经使用触发器至少有一个未付款的购物车(以防插入多个新购物车),我想防止添加新的购物车。
表的 model 截图
我设法在修改表的paidTime 列中包含 NULL 的 T-SQL 计数记录中很容易地解决了这个问题。
CREATE TRIGGER one_unpaid_cart_per_client ON Cart
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE newCart_cursor CURSOR FOR SELECT IdClient, IdCart, isPaid FROM inserted;
DECLARE @IdClient int;
DECLARE @IdCart int;
DECLARE @isPaid datetime;
OPEN newCart_cursor;
FETCH NEXT FROM newCart_cursor INTO @IdClient, @IdCart, @isPaid;
WHILE @@FETCH_STATUS = 0
BEGIN
IF @isPaid is null
BEGIN
if 1 < (SELECT COUNT(1) FROM Cart WHERE IdClient = @IdClient AND isPaid is Null)
BEGIN
PRINT 'Unpaid cart already exists for client id: ' + Cast(@IdClient as Varchar);
DELETE FROM Cart WHERE IdCart = @IdCart;
Raiserror('New cart has not been added', 1, 1);
END;
END;
FETCH NEXT FROM newCart_cursor INTO @IdClient, @IdCart, @isPaid;
END;
CLOSE newCart_cursor;
DEALLOCATE newCart_cursor;
SET NOCOUNT OFF;
END;
在 PL/SQL 中,据我所知,您无法查询更改表,因此我无法检查那里有多少未付费的购物车。
我可以做些什么来使用 PL/SQL 中的触发器来完成这项工作吗?
谢谢你的帮助!
正如 OldProgrammer 建议的那样,您可以使用 Oracle 中的复合触发器来完成您想做的事情。 在这种方法中,您将有一个 BEFORE INSERT...FOR EACH ROW 触发器来记录 memory(PL/SQL 数组或其他东西)中的客户端 ID,然后是一个 BEFORE INSERT 语句级别触发器来检查多个未付费购物车中的任何一个记录的客户端 ID(如果找到,则抛出异常)。
但是,使用触发器来强制执行参照完整性是很难做到的。 这主要是因为触发器在事务提交之前触发。 因此,例如:
...而您的触发器未能实现其目的。
一个更好的方法是创建一个唯一约束,依赖于唯一约束不拒绝在约束的所有列中具有NULL
值的行这一事实。
像下面的例子应该避免上面描述的竞争条件并且 100% 的时间工作。
--drop table cart;
CREATE TABLE cart
( cart_id NUMBER NOT NULL,
client_id NUMBER NOT NULL,
payment_time TIMESTAMP,
unpaid_client_id NUMBER
INVISIBLE GENERATED ALWAYS AS (DECODE(payment_time,NULL,client_id, NULL)) VIRTUAL,
is_unpaid VARCHAR2(1)
INVISIBLE GENERATED ALWAYS AS (DECODE(payment_time,NULL,'Y',NULL)) VIRTUAL,
CONSTRAINT cart_pk PRIMARY KEY ( cart_id ),
CONSTRAINT max_one_unpaid UNIQUE ( unpaid_client_id, is_unpaid)
);
delete from cart;
-- This should be allowed: the first unpaid cart for a client
insert into cart ( cart_id, client_id, payment_time ) values ( 100, 1, null );
--1 row(s) inserted.
-- This should be rejected: a second unpaid cart for a client
insert into cart ( cart_id, client_id, payment_time ) values ( 101, 1, null );
--ORA-00001: unique constraint (SQL_PRUOVRWCMSHZECACDIWPGIBED.MAX_ONE_UNPAID) violated ORA-06512: at "SYS.DBMS_SQL", line 1721
-- This should be allowed, a paid cart for a client having an unpaid one
insert into cart ( cart_id, client_id, payment_time ) values ( 102, 1, SYSTIMESTAMP );
--1 row(s) inserted.
-- This should be allowed, a second paid cart for a client having an unpaid one
insert into cart ( cart_id, client_id, payment_time ) values ( 103, 1, SYSTIMESTAMP );
--1 row(s) inserted.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.