如何在语句之前运行检查约束

时间:2017-04-18 20:02:10

标签: sql-server tsql

我遇到了一个问题,我的检查约束正在阻止命令执行,但我的Identity列值增加了。我想这是因为检查发生在语句运行之后,由于检查失败导致事务回滚。这使身份值增加1。

有没有办法在执行SQL语句之前运行约束检查?

CREATE TABLE TestTable
(
    Id INT IDENTITY(1,1) PRIMARY KEY(Id),
    Name VARCHAR(100)
)

INSERT INTO TestTable VALUES ('Type-1'),('Type-2'),('Type-55'),('Type-009')

--Add a check constraint so nobody can edit this without doing serious work
ALTER TABLE TestTable WITH NOCHECK ADD CONSTRAINT [CHECK_TestTable_READONLY] CHECK(1=0)


--This fails with the constraint as expected
INSERT INTO TestTable VALUES('This will Fail')
INSERT INTO TestTable VALUES('This will again....')


--Check the Id, it was incremented...
SELECT (IDENT_CURRENT( 'TestTable' )  ) As CurrentIdentity

2 个答案:

答案 0 :(得分:2)

当我不得不在过去做同样的事情时,我创建了一个触发器,只是在插入和删除时引发了异常。这有几个优点,最重要的是它可以防止更新和删除,你可以给出一个自定义异常消息,解释你在那里做了什么以及为什么,这是一个非常糟糕的习惯,只是放置不合逻辑的约束,并希望从现在开始3个月后人们会理解什么去那里,知道他们应该问你这件事。如果重要的话,它还可以防止Id计数器递增。如果它很重要,我也不会使用自动增量,只需手动设置ID号,因为即使您使用这些触发器,在禁用它们并尝试添加值后,您可能总是出现意外语法错误或任何其他错误

create trigger PreventChanges
on TestTable
FOR INSERT, UPDATE, DELETE
as
begin
  throw 51000, 'DO NOT change anything in that table unless you really have to! in order to do so pleasae talk to GER (or just disable and reenable this trigger)',1
and

答案 1 :(得分:0)

听起来您打算将标识列用于不适合的内容。但要回答您的问题,您是否可以手动编写一些SQL Server IF语句来在插入发生之前测试数据(可能在存储过程中)?我不知道如何使这个动态“适应任何表的所有约束”,但是该过程可以做你想要的 - 防止INSERT被触发。但是,如果您的约束发生变化,那么您也必须更改过程。

如,

IF 1 = 0 -- or use any of your constraints here...
    BEGIN
        -- nest more IFs if you have multiple check-constraints...
        INSERT INTO TestTable 
        VALUES ('This will not increase your identity number since 1 does not equal 0')
    END