Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检查约束中的MSSQL函数_Sql_Sql Server - Fatal编程技术网

检查约束中的MSSQL函数

检查约束中的MSSQL函数,sql,sql-server,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

我想创建带有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\u history
表(该表为空)时,我得到一个错误,即
insert语句与CHECK约束“CK\uu book\u history\uuu 267ABA7A”冲突。冲突发生在数据库“library”表“dbo.book\u history”中。

COUNT应根据MSDN文档返回int数据类型。
我是表和函数的所有者

有人能告诉我我做错了什么吗?

将其更改为
检查(dbo.fn\u检查重复(用户id、图书馆id、图书id)=1)

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

在rextester上测试:取消第二个插入的注释


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

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

如果每本书都是一本单独的书,那么这可能是您试图做的更多:

create unique nonclustered index uix_book_history_library_book
  on dbo.book_history (library_id, book_id)
    where return_time is null
因为这将允许一本书一次只能由一个用户签出

将其更改为
check(dbo.fn\u check\u duplicate(用户id、图书馆id、图书id)=1)

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

在rextester上测试:取消第二个插入的注释


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

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

如果每本书都是一本单独的书,那么这可能是您试图做的更多:

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

因为这将允许一本书一次只能由一个用户签出

返回内容:
选择fn\u check\u duplicate(user\u id int,library\u id int,book\u id int)
?返回内容:
选择fn\u check\u duplicate(user\u id int,library\u id int,book\u id int)
?我绝对同意OP应该使用这里提供的过滤索引。它远没有标量函数那么笨重。我不知道CHECK是在操作后检查状态。非常感谢您提供的信息。关于您提供的备选方案:我有多个用户,可以在多个图书馆注册,每个图书馆都有自己的一套书籍。所以你可以说
(用户id、图书馆id、图书id)
的组合是唯一的。但是我想防止插入相同的
(用户id、图书馆id、图书id)
如果
返回时间
为空-这意味着用户仍然有借来的图书。仅当
return\u time
不为空时,才允许插入相同的值-这意味着用户在一段时间前就有了那本书,他想再次借阅。这就是过滤后的唯一索引所做的吗?@Lopfest您可能会发现这一点很有趣:失败的插入会消耗一个
id
。因此,如果插入失败,id为2,则下一次成功插入的id为3。@Lopfest我在索引中没有
user\u id
的最后一个选择是关于以下情况:如果
book\u id
是一个物理对象,那么可以公平地说,两个用户不可能同时签出同一个物理对象。但是如果一个
图书id
仅仅代表一本书的一个版本或一个书名等,并且有很多,那就不适用了。我绝对同意OP应该使用这里提供的过滤索引。它远没有标量函数那么笨重。我不知道CHECK是在操作后检查状态。非常感谢您提供的信息。关于您提供的备选方案:我有多个用户,可以在多个图书馆注册,每个图书馆都有自己的一套书籍。所以你可以说
(用户id、图书馆id、图书id)
的组合是唯一的。但是我想防止插入相同的
(用户id、图书馆id、图书id)
如果
返回时间
为空-这意味着用户仍然有借来的图书。仅当
return\u time
不为空时,才允许插入相同的值-这意味着用户在一段时间前就有了那本书,他想再次借阅。这就是过滤后的唯一索引所做的吗?@Lopfest您可能会发现这一点很有趣:失败的插入会消耗一个
id
。因此,如果插入失败,id为2,则下一次成功插入的id为3。@Lopfest我在索引中没有
user\u id
的最后一个选择是关于以下情况:如果
book\u id
是一个物理对象,那么可以公平地说,两个用户不可能同时签出同一个物理对象。但是如果一个
book\u id
仅仅代表一本书的一个版本或一个书名等,并且有很多,那么这就不适用了。