【问题标题】:How not to insert specific value into database如何不将特定值插入数据库
【发布时间】:2010-09-16 15:48:16
【问题描述】:

我有 MS SQL Server 数据库并向其中一个表插入一些值。

假设该表包含列IDint Statustext Text

如果可能,我想创建一个触发器,以防止将特定的不正确状态(例如1)写入表。相反,应该写0。但是,插入新值时应保留其他列:

如果写入的新行是(1, 4, "some text"),则按原样写入。
如果写入的新行是(1, 1, "another text"),则写为(1, 0, "another text"

是否可以创建这样的触发器?怎么样?

编辑:即使状态列无效,我也需要允许写入此类记录,因此外键对我不起作用。

【问题讨论】:

  • 绝对是。插入触发器可以做到这一点。但是,出于各种原因,主要与调试和可维护性有关,我建议您在代码中处理它,而不是为这种逻辑使用触发器。此外,如果状态是用户输入,如果输入的状态不正确,您是否需要提醒/警告用户,而不是仅仅更改用户不知道的状态?
  • 我正在使用 ORM 写入数据库,并且在某些情况下,它会插入具有中间状态的中间值。这还不错,但是,如果程序由于某些原因崩溃,数据库中会存储无效状态。所以我无法在代码中处理这个(这是第三方二进制文件),这不是用户输入。
  • 尽可能使用事务来确保 ACID...
  • 谢谢,但这是第三方 ORM,我不能。我需要这个 hack 来解决第三方问题。

标签: sql sql-server


【解决方案1】:

我认为即使您选择使用触发器,您也需要一个外键来确保数据完整性(尽管我自己更喜欢“帮助”存储过程——触发器可能导致调试地狱),例如

CREATE TABLE MyStuff 
(
 ID INTEGER NOT NULL UNIQUE,
 Status INTEGER NOT NULL 
    CHECK (Status IN (0, 1)), 
 UNIQUE (Status, ID) 
);

CREATE TABLE MyZeroStuff 
(
 ID INTEGER NOT NULL, 
 Status INTEGER NOT NULL 
    CHECK (Status = 0), 
 FOREIGN KEY (Status, ID)
    REFERENCES MyStuff (Status, ID), 
 my_text VARCHAR(20) NOT NULL
);

CREATE TRIGGER tr__MyZeroStuff
ON MyZeroStuff
INSTEAD OF INSERT, UPDATE
AS
BEGIN; 
INSERT INTO MyZeroStuff (ID, Status, my_text)
SELECT i.ID, 0, i.my_text
  FROM inserted AS i;
END; 

【讨论】:

    【解决方案2】:

    已经提到了插入触发器,但实现此目的的另一种方法是在状态列上有一个指向状态表的外键 - 这将不允许写入和更改值,而是简单地禁止如果外键无效则写入。

    查看referential integrity 了解有关此选项的更多信息。

    【讨论】:

    • 感谢您的回答,但微妙的是,由于任务特定,即使状态列无效,我也需要允许写入此类记录,因此外键对我不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 2017-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    相关资源
    最近更新 更多