防止插入和更新具有旧日期的记录

0yg35tkg  于 2022-09-18  发布在  Java
关注(0)|答案(2)|浏览(154)

我想要防止三件事

1.如果现有日期早于2022-01-01,则禁止更新记录
1.如果新日期早于2022-01-01,则禁止更新记录
1.如果日期早于2022-01-01,则禁止插入。

基本上,如果日期早于2022-01-01,则不应允许插入或更新记录。

我试着用带有光标的触发器。我必须使用游标,因为它应该对批处理起作用。

CREATE TRIGGER TriggerDate
ON tb
AFTER INSERT,UPDATE 
AS
BEGIN
    DECLARE @IVDate Date;

    DECLARE my_Cursor CURSOR FOR 
         SELECT InvoiceDate 
         FROM INSERTED; 

    OPEN my_Cursor; 

    FETCH NEXT FROM my_Cursor INTO @IVDate;

    WHILE @@FETCH_STATUS = 0 
    BEGIN
        FETCH NEXT FROM my_Cursor INTO @IVDate;

        IF @IVDate < '2022-01-01'
           ROLLBACK TRANSACTION
    END

    CLOSE my_Cursor; 
    DEALLOCATE my_Cursor;
END

但问题出现在INSERT语句的顺序上。

例如,以下语句运行良好

insert into tb values (1, '2022-05-02','A');
insert into tb values (2, '2021-08-06','B');

但以下方法不起作用:

insert into tb values (2, '2021-08-06','B');
insert into tb values (1, '2022-05-02','A');   -- This record is correct but still it won't insert

具有WHERE条件和OR的UPDATE语句也会发生同样的情况

为了快速理解,请参考此dbfiddle

https://dbfiddle.uk/bCrXMfUS

doinxwow

doinxwow1#

请勿在TRIGGER中使用CURSOR。触发器应该对调用语句有尽可能小的影响,而CURSOR是您可以拥有的最影响的东西之一。

这里您需要做的就是使用EXISTS来检查是否存在您不想要的行,而THROW则是错误的。不要在TRIGGER中使用ROLLBACK,因为这会给最终用户带来有意义的错误;让外部查询处理事务的回滚:

CREATE TRIGGER dbo.YourTrigger_ins ON dbo.YourTable
AFTER INSERT AS
BEGIN
    IF EXISTS (SELECT 1
               FROM inserted
               WHERE InvoiceDate < '20220101')
       THROW 50001, N'An error was thrown in the trigger ''dbo.YourTrigger_ins'' on the table ''dbo.YourTable''. A row where the invoice date is prior to 2022-01-01 cannot be inserted.', 16;
END;
GO

CREATE TRIGGER dbo.YourTrigger_upd ON dbo.YourTable
AFTER UPDATE AS
BEGIN
    IF EXISTS (SELECT 1
               FROM deleted
               WHERE InvoiceDate < '20220101')
       THROW 50002, N'An error was thrown in the trigger ''dbo.YourTrigger_upd'' on the table ''dbo.YourTable''. A row where the invoice date is prior to 2022-01-01 cannot be updated.', 16;
    IF EXISTS (SELECT 1
               FROM inserted
               WHERE InvoiceDate < '20220101')
       THROW 50003, N'An error was thrown in the trigger ''dbo.YourTrigger_upd'' on the table ''dbo.YourTable''. The value of the invoice date cannot be updated to be prior to 2022-01-01 .', 16;
END;

db<>fiddle

qf9go6mv

qf9go6mv2#

如果要从实际插入中排除插入,则可以在INSTEAD OF INSERT触发器中执行此操作

create table tb(InvoiceNo int, InvoiceDate Date, CustomerName varchar(10));
insert into tb values(3,'2021-08-06','B');
CREATE OR ALTER TRIGGER IgnoreInvoices ON dbo.tb
    INSTEAD OF INSERT
 AS
    BEGIN
    SET NOCOUNT ON;
    INSERT dbo.tb(InvoiceNo, InvoiceDate,CustomerName)
        SELECT InvoiceNo, InvoiceDate,CustomerName
        FROM inserted
        WHERE InvoiceDate >= '2022-01-01';
    END
CREATE OR ALTER TRIGGER IgnoreInvoicesupdate ON dbo.tb
    INSTEAD OF UPDATE
 AS
    BEGIN
    SET NOCOUNT ON;
  IF EXISTS 
  (
     SELECT 1 FROM inserted i
       JOIN deleted AS d ON i.InvoiceNo = d.InvoiceNo
       WHERE d.InvoiceDate >= '2022-01-01' AND i.InvoiceDate >= '2022-01-01'  
  )
  BEGIN
     UPDATE src 
       SET CustomerName = i.CustomerName, 
          InvoiceDate = i.InvoiceDate
       FROM dbo.tb AS src
       INNER JOIN inserted AS i
       ON i.InvoiceNo = src.InvoiceNo
       AND (src.InvoiceDate <> i.InvoiceDate or src.CustomerName = i.CustomerName);
  END
    END
insert into tb values(4,'2022-05-02','A');
insert into tb values(2,'2021-08-06','B');
2 rows affected
select * from tb

InvoiceNo|InvoiceDate|CustomerName
-|-|
3|2021-08-06|B
4|2022-05-02|A

UPDATE tb SET InvoiceDate = '2021-05-02' WHERE InvoiceNo = 4;;
UPDATE tb SET InvoiceDate = '2022-05-02' WHERE InvoiceNo = 3;;
2 rows affected
select * from tb

InvoiceNo|InvoiceDate|CustomerName
-|-|
3|2021-08-06|B
4|2022-05-02|A

Delete from TB
2 rows affected
insert into tb values(1,'2021-08-06','B');
insert into tb values(2,'2022-05-02','A');---This record is correct but still it won't insert
2 rows affected
select * from tb

InvoiceNo|InvoiceDate|CustomerName
-|-|
2|2022-05-02|A

fiddle

相关问题