【问题标题】:Sql or linq to sql Unique Constraint based on two columns value基于两列值的sql或linq to sql唯一约束
【发布时间】:2016-11-19 11:22:17
【问题描述】:

我不知道这是否可能。 我有一张表,用于保存图书问题返回的记录。其中有两列是 [status] 和其他 [bookid]。我想在 sql 中添加一个约束,限制用户插入重复记录 status="问题”具有相同的 bookid。

例如,如果已经有一条 status='issue' 和 bookid=1 的记录,那么它一定不允许插入 status="issue" 和 bookid=1 的其他记录,但是我可以有多个其他状态的记录,例如staus='return' 和 bookid=1 可能会出现多次。

或者可能有在c#中使用linq to sql的解决方案

【问题讨论】:

  • 请用您正在使用的数据库标记您的问题。

标签: c# sql linq-to-sql


【解决方案1】:

一般来说,您不需要用户定义的函数。在 SQL Server(和许多其他数据库)中,您可以只使用过滤索引:

create unique index unq_bookissue
    where status = 'issued' ;

在 SQL Server 的早期版本中,您可以使用计算列执行此操作,假设您有一个包含以下列的表:

  • BookId,跨行重复。
  • Status,当值为issue时应该是唯一的。
  • BookIssueId,唯一标识每一行。

然后,添加一个计算列来跟踪status = 'issue'

alter table t add computed_bookissueid as (case when status = 'issue' then -1 else BookIssueId end);

现在在此列和BookId上添加一个唯一索引:

create unique index unq_bookid_issue on (BookId, computed_bookissueid);

【讨论】:

  • 感谢您在语法上稍作更改创建唯一索引 unq_bookissuedReference on Books(book_id) where [status] = 'issued'
【解决方案2】:

你的情况很复杂,所以UNIQUEconstraint 对你没有帮助。您将需要一个CHECKconstraint。

您首先需要一个函数来进行检查:

CREATE FUNCTION dbo.IsReturnDuplicate
(
    @id INT,
    @bookid INT,
    @status VARCHAR(MAX)
)
RETURNS BIT
AS
BEGIN
    RETURN (SELECT TOP 1 COUNT (*) FROM bookreturns WHERE (id <> @id) AND (status = @status) AND (bookid = @bookid) AND (status = 'issue')
END

如果表中已经存在状态为“问题”且具有不同 id 的行,这将返回 1

然后您可以使用此函数创建CHECK 约束

CREATE TABLE bookreturns (
    --...
    CONSTRAINT CK_bookreturns_status CHECK (dbo.IsReturnDuplicate(id, bookid, status) == 0)
)

【讨论】:

    【解决方案3】:

    使用Gordon answer

    create unique index unq_bookissuedReference
    on Books(Book_id) where [status] = 'issued' 
    

    为我工作

    【讨论】:

    • 任何有效的东西。如果您的唯一索引变得太大,您仍然可以切换到检查约束,这不会增加数据库大小。
    • @safe 我也试过你的解决方案,效果也很好
    猜你喜欢
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多