在SQL Server 2008中给定一个具有位类型的列,如何编写触发器以允许从0到1的更新,但不允许从1更新为0?
换句话说,一旦该位设置为1,它应始终为1.
触发器必须适用于多个更新,例如:
UPDATE Table SET BitField = 0
BitField = 1的任何行都应该失败。
编辑:为了给出一些背景知识,有问题的位/标记标记是否需要处理货币交易。如果位= 1,则事务已处理完毕。如果该位重置为0,则事务可能会重复,因此我需要在数据库级别强制执行该位不能重置为0.
我需要防止针对数据库运行的直接查询以及应用程序级错误。我无法确定是否总是会使用存储过程来更新表,因此我认为触发器是强制执行此逻辑的唯一方法。
答案 0 :(得分:4)
看起来你需要一个简单的触发后
CREATE TABLE YourTable(
PK int Primary key,
bitCol bit
)
CREATE TRIGGER YourTableTrigger
ON YourTable
AFTER UPDATE
AS
DECLARE @nrOfViolations int
select @nrOfViolations = count(*) from deleted d
join YourTable t on d.PK = t.PK
where d.bitCol = 1 and t.bitCol = 0
if @nrOfViolations > 0
BEGIN
RAISERROR('Failed', 16, 1);
ROLLBACK TRANSACTION
END
答案 1 :(得分:2)
一种方法是使用触发器来进行所有更新,除了在等于1时更改位域的任何内容。在这种情况下,除了位域更改之外,它允许所有更新通过。
CREATE TRIGGER OneWayBitChange
ON YourTable
INSTEAD OF UPDATE
AS
BEGIN
UPDATE YourTable SET /* update all fields from original update except bitfield */
Field1 = i.Field1,
Field2 = i.Field2,
Field3 = i.Field3
FROM YourTable
INNER JOIN Inserted i ON i.PrimaryKey = YourTable.PrimaryKey
UPDATE YourTable SET /* update bitfield only if it's not already a 1 */
BitField = i.BitField
FROM YourTable
INNER JOIN Inserted i ON i.PrimaryKey = YourTable.PrimaryKey
WHERE IsNull(YourTable.BitField,0) < 1
END
GO
以上将允许所有更新在从1到其他任何内容(0或null)时接受一个字段。
如果要在位字段上尝试取消该行的任何更新,可以像这样修改正文:
UPDATE YourTable SET /* update all except bitfield changes from 1 to 0 */
Field1 = i.Field1,
Field2 = i.Field2,
Field3 = i.Field3,
BitField = i.BitField
FROM YourTable
INNER JOIN Inserted i ON i.PrimaryKey = YourTable.PrimaryKey
WHERE IsNull(BitField,0) = 0 OR IsNull(i.BitField,0) = 1
答案 2 :(得分:2)
我不会把它埋在触发器中。我有你的存储过程(SP)更新表检查值。例如:
CREATE PROCEDURE dbo.proc_update_my_table
@id AS INT,
-- Whatever other params you need
@the_bit_field AS BIT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @existing_value AS BIT
SELECT @existing_value = the_bit_field FROM dbo.Table1 t WHERE t.id = @id
IF @existing_value = 1 AND @the_bit_field = 0
BEGIN
RAISERROR('Fail.', 10, 1)
RETURN -1
END
-- Update the table as normal.
END
GO
使用触发器有点像试图通过打开的前门(SP的查询)将小偷(错误)赶出家门。改为锁上前门;)