我想用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数据类型 我是桌子和功能的所有者。
谁能告诉我我做错了什么?
答案 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
因为这样只允许一个用户一次检出一本书。