sql – 一组记录中的唯一约束,其中某些值相同

前端之家收集整理的这篇文章主要介绍了sql – 一组记录中的唯一约束,其中某些值相同前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
DBMS:MS sql Server 2005,标准版

我想创建一个表约束,只有一个记录在表的一个子集中具有特定值(其中行共享特定列中的值).这可能吗?

例:
我在myTable中有一个非唯一外键(fk1)的记录,还有一个名为isPrimary的位列,用于标记我们的应用程序应该使用这个特殊逻辑.

摘要中,它看起来像这样:

myTable
-------------
pk1       (int,not null)
name      (varchar(50),null)
fk1       (int,not null)
isPrimary (bit,not null)

对于fk1的每个唯一值,我想确保将isPrimary标志设置为1的唯一一条记录.

数据示例:
这应该是合法的:

pk1     name     fk1    isPrimary
----    -----    -----  ----------
1       Bill     111    1
2       Tom      111    0
3       Dick     222    1
4       Harry    222    0

但这不应该是(超过一个fk = 111):

pk1     name     fk1    isPrimary
----    -----    -----  ----------
1       Bill     111    1
2       Tom      111    1
3       Dick     222    1
4       Harry    222    0

这也不应该(没有fk = 222):

pk1     name     fk1    isPrimary
----    -----    -----  ----------
1       Bill     111    1
2       Tom      111    0
3       Dick     222    0
4       Harry    222    0

有没有办法用表约束来做到这一点?

UPDATE
我现在已经接受了Martin Smith的回答,尽管我将在即将发布的版本中推动JohnFx的重构,因为它是最好的长期解决方案.但是我想根据Raze2dust的答案发布我更新的UDF,以防未来读者认为更适合他们的需求.

CREATE FUNCTION [dbo].[OneIsPrimaryPerFK1](@fk1 INT,@dummyIsPrimary BIT)
RETURNS INT
AS 
BEGIN
    DECLARE @retval INT;
    DECLARE @primarySum INT;
    SET @retval = 0;
    DECLARE @TempTable TABLE (
    fk1 INT,PrimarySum INT)

INSERT INTO @TempTable
    SELECT fk1,SUM(CAST(isPrimary AS INT)) AS PrimarySum
    FROM FacAdmin
    WHERE fk1 = @fk1
    GROUP BY fk1;

    SELECT @primarySum = PrimarySum FROM @TempTable;
    IF(@primarySum=1)
        BEGIN
            SET @retval = 1
        END
    RETURN @retval
END;

变化:

>使用@tempTable而不是

根据udf的要求,tempTable(在内存中,写入磁盘)
>传递@ fk1作为参数,这样我就可以在一个中选择唯一性
一组fk1值.
>棘手也必须通过isPrimary,即使它不是
必要的逻辑
功能,否则sql2005
优化器不会运行检查
isPrimary时的约束
更新.

解决方法

在检查约束中使用UDF可能会在 snapshot isolationmultirow updates下失败.

假设您的所有fk1和pk1值当前(并且将始终为)为正,您可以使用以下定义创建计算列

CASE WHEN isPrimary = 1 THEN fk1 ELSE -pk1 END

然后添加一个唯一的约束.或者,如果不能做出那个假设那么可能

CASE WHEN isPrimary = 0 THEN 1.0/pk1 ELSE fk1 END

猜你在找的MsSQL相关文章