0

我想创建一个触发器来防止输入高于某个值的值。

我已经阅读了一些内容,但无法将以下问题与我自己的问题联系起来。

仅当 SQL Server 中满足条件时触发

代码:

ALTER TRIGGER Tgr_IQRating
  ON  dbo.Customer
  FOR UPDATE 
AS
BEGIN
   SET NOCOUNT ON;

   DECLARE @IQ int

   Select @IQ = IQRATING from dbo.customer

   IF (@IQ) > 150 
   BEGIN
       PRINT ('Cannot enter anything higher than 100')
   END

   ROLLBACK TRANSACTION
END

我试过这样

IF (IQRating) > 150 
BEGIN
   PRINT ('Cannot enter anything higher than 100')
END

ROLLBACK TRANSACTION

但是得到一个无法找到该列的错误。此外,当我尝试更新时,以下失败。

IF (SELECT IQRating FROM dbo.customer) > 150 
BEGIN
    PRINT ('Cannot enter anything higher than 100')
END

错误:

消息 512,级别 16,状态 1,过程 Tgr_IQRating,第 16 行
子查询返回超过 1 个值。当子查询跟随 =、!=、<、<=、>、>= 或子查询用作表达式时,这是不允许的。

任何帮助都会很棒。

谢谢,

杰。

4

3 回答 3

1

你真的应该为此使用约束。它对 SQL 来说更惯用。

检查约束

于 2013-05-23T19:59:02.040 回答
0

您应该使用特殊的“表格”inserted来查看正在更新的数据,否则您正在查看的整个表格也将包含其他行。

IF EXISTS(SELECT 1 FROM inserted WHERE IQRating > 150)
BEGIN
    PRINT ('Cannot enter anything higher than 150')
END

RAISERROR更好的解决方案是在 SQL Server 2012THROW语句中使用or ,而不是PRINT将错误消息发送回启动更新的人。

于 2013-05-23T18:25:52.867 回答
0

你有多个问题。首先,您将回滚 100% 的时间,因为回滚不在 IF 块中。

下一个

Select @IQ = IQRATING from dbo.customer

是你的子查询问题。我假设客户有多个记录!无论如何,您可能应该引用插入的伪表。

第三,您似乎认为触发器一次只能在一行上操作。它将分批运行。一个线索是您正在填充一个标量变量。假设更新中永远只有一条记录是不负责任和不专业的。

您是否还需要对 INSERT 进行此项检查?还是这些数据仅在更新中填充?

如果一个记录是坏的,或者如果你想找到任何插入的坏记录并只保留那些数据库,你是否希望整个事务回滚是不清楚的。每种可能性的代码都会不同。

编辑其中一些是针对 SQL 服务器的(我没有看到 mysql 标记,但你在文中引用了 SQL 服务器,所以我做了一个假设。)虽然代码看起来像 T_SQL 代码。

于 2013-05-23T19:51:47.113 回答