函数在sql server上的CHECK Constraint中不起作用

时间:2015-01-13 18:44:48

标签: sql sql-server database function

我的数据库有问题,我尝试简化我的数据库.. 经过多次尝试,该功能使用' X'表,然后使用' X' table.you不能使用函数使用相同的表...

- 创建表后:

create table Items(
ID int,
Price money
);

- 插入一些值

insert into Items Values(1,4);
insert into Items Values(2,5);

- 在表格上创建一个函数

CREATE FUNCTION GetMaxPrice
(
    -- Add the parameters for the function here

)
RETURNS Money
AS
BEGIN
    -- Declare the return variable here
    DECLARE @result money = 5;

    select @result = max(Price)
    from Items;


    -- Return the result of the function
    RETURN @result;

END

- 然后改变表以添加约束 - 接受表中任何价格低于或等于的价格

alter table Items add check(Price <= dbo.GetMaxPrice())

- 之后,我尝试插入项目

insert into Items Values(3,4);
insert into Items Values(4,15); -- <-- here, I have problem. it inserted in Database..
--why inserted when max value is 5 ??

我使用的是sql server 2012 Express,Win7

3 个答案:

答案 0 :(得分:3)

你遇到的问题是当检查约束触发时,表中存在新值(隐式事务内),所以当你插入15时,max(Price) 15,所以满足约束,INSERT成功。我有一个彻底的谷歌尝试找到记录的位置,但没有发现任何确定的。

实现后续效果的另一种方法是使用INSTEAD OF触发器,例如下面的例子。

虽然提出了一个建议 - 这种验证让我觉得容易出错。我尝试将限制值与数据分开 - 可能在另一个表中。

希望这有帮助,

里斯

create table dbo.Items(
ID int,
Price money
);

insert into dbo.Items Values(1,4);
insert into dbo.Items Values(2,5);
go

create trigger trgItemsInsert on dbo.Items instead of insert as
begin
    -- Lookup current max price
    declare @MaxPrice money = (select max(Price) from dbo.Items)
    if exists (select 1 from inserted where Price > @MaxPrice)
        begin
            -- If there is a price greater than the current max then reject the insert
            declare @msg varchar(255) = 'Maximum allowed price is ' + cast(@MaxPrice as varchar(32)) + '.'
            rollback
            raiserror('%s', 16, 1, @msg)
        end
    else
        begin
            -- Otherwise perform the insert
            insert into dbo.Items 
                select ID,Price from inserted
        end
end
go

insert into dbo.Items Values(3,4);
insert into dbo.Items Values(4,15);
go
select * from dbo.Items
go

答案 1 :(得分:2)

尝试使用此代码。它对我来说很好。

CREATE TABLE item
  (
     ID    INT,
     Price MONEY
  );

--Insert some values
INSERT INTO item
VALUES      (1,
             4);

INSERT INTO item
VALUES      (2,
             5);

--create a function use above table
CREATE FUNCTION GetMax (@price MONEY)
RETURNS MONEY
AS
  BEGIN
      -- Declare the return variable here
      DECLARE @result MONEY = 5;

      SELECT @result = max(Price)
      FROM   item;

      IF @price < @result
        RETURN 1

      RETURN 0
  -- Return the result of the function
  END

--then alter table to add constraint --accept any price less or equal price on table
ALTER TABLE item
  WITH NOCHECK ADD CONSTRAINT ck1 CHECK(dbo.GetMax(Price)=(1))

--ALTER TABLE item
--  DROP CONSTRAINT ck1
--after that, i try to insert item
INSERT INTO item
VALUES      (3,
             4);

INSERT INTO item
VALUES      (4,
             15); 

答案 2 :(得分:1)

看起来检查约束直到初始插入后才会执行。所以数据库引擎

  1. 插入数据
  2. 检查约束
  3. 如果插入违反约束,则回滚插入
  4. 如果插入正常,则提交数据
  5. 您可以在查询执行计划中看到这种情况发生的顺序: enter image description here

    图片中突出显示的Assert属性说明“用于验证是否存在指定的条件。”

    我无法从Microsoft找到相关文档,如果有人知道在哪里找到它,请告诉我。