检查约束中的MSSQL函数

时间:2017-02-23 18:48:38

标签: sql sql-server

我想用CHECK约束创建表,其中CHECK调用用户定义的标量函数。我已经在多个网站上阅读过它可能,但它的性能也不好。即使我愿意这样做。

我有这张桌子

CREATE TABLE [book_history] (
    id int NOT NULL IDENTITY PRIMARY KEY,
    user_id int NOT NULL,
    library_id int NOT NULL,
    book_id int NOT NULL,
    borrow_time datetime DEFAULT GETDATE(),
    return_policy datetime DEFAULT DATEADD(DAY, 30, GETDATE()),
    return_time datetime,
    CHECK (dbo.fn_check_duplicate(user_id, library_id, book_id) = 0)
);

和功能

DROP FUNCTION IF EXISTS fn_check_duplicate
GO
CREATE FUNCTION fn_check_duplicate (@user_id int, @library_id int, @book_id int)
RETURNS int
BEGIN
    RETURN (SELECT COUNT(*) FROM [book_history] WHERE user_id = @user_id AND library_id = @library_id AND book_id = @book_id AND return_time IS NULL)
END
GO

当我尝试在此book_history表(空白)中插入新行时,出现错误The INSERT statement conflicted with the CHECK constraint "CK__book_history__267ABA7A". The conflict occurred in database "library", table "dbo.book_history".

COUNT应该根据MSDN文档返回int数据类型 我是桌子和功能的所有者。

谁能告诉我我做错了什么?

1 个答案:

答案 0 :(得分:4)

将其更改为check (dbo.fn_check_duplicate(user_id, library_id, book_id) = 1)

check将在插入后查看表的状态,因此您希望计数为1.

通过取消注释第二个插入来在rextester:http://rextester.com/AWDNP40594上测试它。

您还可以使用过滤的唯一索引替换此慢速检查约束,如下所示:

create unique nonclustered index uix_book_history_user_library_book
  on dbo.book_history (user_id, library_id, book_id)
    where return_time is null

如果每本book_id都是一本书,那么这可能更像是你要做的事情:

create unique nonclustered index uix_book_history_library_book
  on dbo.book_history (library_id, book_id)
    where return_time is null

因为这样只允许一个用户一次检出一本书。

相关问题