Sql约束方法返回假值

发布于 2024-12-18 03:37:31 字数 2702 浏览 2 评论 0原文

我在 sql 中的约束方法上遇到问题。

这是我的表格

CREATE TABLE [relations].[CompoundKey_Contacts](
    [compoundId] [varchar](32) NOT NULL,
    [companyId] [varchar](32) NULL,
    [personId] [varchar](32) NULL,
    [contactInfoId] [varchar](32) NOT NULL)

当您向该表格添加一行时,它应该检查该个人和公司的组合是否已存在于该表格中。为此,我使用约束函数

Constraint

ALTER TABLE [relations].[CompoundKey_Contacts]  WITH NOCHECK ADD  CONSTRAINT [CK_CompoundKey_Contacts] CHECK  (([relations].[doesThisCompoundKeyExist]([personId],[companyId])='NO'))
GO

ALTER TABLE [relations].[CompoundKey_Contacts] CHECK CONSTRAINT [CK_CompoundKey_Contacts]
GO

Function

CREATE function [relations].[doesThisCompoundKeyExist](
    @personId varchar(32),
    @companyId varchar(32)
)
returns varchar(3)
as
begin
    declare @exists varchar(32)

    if(@companyId is null and @personId is null)
      set @exists = 'YES'
    else if(@personId is null)
        if exists(select compoundId from relations.CompoundKey_Contacts where personId is null AND companyId = @companyId)
            set @exists = 'YES' 'This is where to code enters, but it should come to the else and return 'NO'
        else
            set @exists = 'NO'
    else if(@companyId is null)
        if exists(select compoundId from relations.CompoundKey_Contacts where personId = @personId AND companyId is null)
            set @exists = 'YES'
        else
            set @exists = 'NO'
    else if exists(
        select compoundId from relations.CompoundKey_Contacts where personId = @personId AND companyId = @companyId
        )
        set @exists = 'YES'
    else
        set @exists = 'NO'
    return @exists
end;

我的插入语句失败

insert into relations.CompoundKey_Contacts (companyId, contactInfoId, personId, compoundId) values ('COM-000015945', 'INF-000144406', null, 'CPK-000000067');

问题是这样的。当我在具有唯一插入的表上运行插入时,它仍然失败。我当然已经通过 select 语句检查了它依赖的唯一性。有趣的部分来了。当我调试它并检查它失败的位置并分解该代码部分并在不处于函数中的情况下自由运行它时,它的行为应该如此,因此如果它不在函数中运行,则以下代码可以工作

if exists(select compoundId from relations.CompoundKey_Contacts where personId is null AND companyId = 'COM-000015945')
                print 'YES'
            else
                print 'NO' 'Returns NO as it should.

这是错误消息我明白

The INSERT statement conflicted with the CHECK constraint "CK_CompoundKey_Contacts". The conflict occurred in database "domas", table "relations.CompoundKey_Contacts".
The statement has been terminated.

我在 Sql Server 2012 和 Sql Server 'DENALI' CTP3 上运行它

I have a problem with a constraint method in sql.

This is my table

CREATE TABLE [relations].[CompoundKey_Contacts](
    [compoundId] [varchar](32) NOT NULL,
    [companyId] [varchar](32) NULL,
    [personId] [varchar](32) NULL,
    [contactInfoId] [varchar](32) NOT NULL)

When you add a row to this table it should check that this combination of person and company does not already exist in the table. For this I use a constraint function

Constraint

ALTER TABLE [relations].[CompoundKey_Contacts]  WITH NOCHECK ADD  CONSTRAINT [CK_CompoundKey_Contacts] CHECK  (([relations].[doesThisCompoundKeyExist]([personId],[companyId])='NO'))
GO

ALTER TABLE [relations].[CompoundKey_Contacts] CHECK CONSTRAINT [CK_CompoundKey_Contacts]
GO

Function

CREATE function [relations].[doesThisCompoundKeyExist](
    @personId varchar(32),
    @companyId varchar(32)
)
returns varchar(3)
as
begin
    declare @exists varchar(32)

    if(@companyId is null and @personId is null)
      set @exists = 'YES'
    else if(@personId is null)
        if exists(select compoundId from relations.CompoundKey_Contacts where personId is null AND companyId = @companyId)
            set @exists = 'YES' 'This is where to code enters, but it should come to the else and return 'NO'
        else
            set @exists = 'NO'
    else if(@companyId is null)
        if exists(select compoundId from relations.CompoundKey_Contacts where personId = @personId AND companyId is null)
            set @exists = 'YES'
        else
            set @exists = 'NO'
    else if exists(
        select compoundId from relations.CompoundKey_Contacts where personId = @personId AND companyId = @companyId
        )
        set @exists = 'YES'
    else
        set @exists = 'NO'
    return @exists
end;

My insert statement that fails

insert into relations.CompoundKey_Contacts (companyId, contactInfoId, personId, compoundId) values ('COM-000015945', 'INF-000144406', null, 'CPK-000000067');

The problem is this. When I run an insert on the table with a unique insert it still fails. I have of course checked that it rely is unique with a select statement. And here comes the funny part. When I do debug it and check where it fails and break out that code part and run it free without being in a function it behaves as it should so the following code works if its not run in a function

if exists(select compoundId from relations.CompoundKey_Contacts where personId is null AND companyId = 'COM-000015945')
                print 'YES'
            else
                print 'NO' 'Returns NO as it should.

This is the error msg I get

The INSERT statement conflicted with the CHECK constraint "CK_CompoundKey_Contacts". The conflict occurred in database "domas", table "relations.CompoundKey_Contacts".
The statement has been terminated.

I run this on both a Sql Server 2012 and Sql Server 'DENALI' CTP3

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

2024-12-25 03:37:31

在检查约束中使用 UDF 不会可靠地工作,如您所见,

如果需要额外的逻辑,请在计算列上使用唯一约束

ALTER TABLE CompoundKey_Contacts
    ADD CompoundKey AS ISNULL(personID, 'NOPERSONID') + ISNULL(companyId, 'NOCOMPANYID');
ALTER TABLE CompoundKey_Contacts WITH CHECK
    ADD CONSTRAINT UQ_CompoundKey_Contacts_CompoundKey UNIQUE (CompoundKey);

或简单的唯一约束

ALTER TABLE CompoundKey_Contacts WITH CHECK
    ADD CONSTRAINT UQ_CompoundKey_OtherUnique UNIQUE (personID, companyId);

Using a UDF in a check constraint won't work reliably as you can see

Use a unique constraint on a computed column if you require extra logic

ALTER TABLE CompoundKey_Contacts
    ADD CompoundKey AS ISNULL(personID, 'NOPERSONID') + ISNULL(companyId, 'NOCOMPANYID');
ALTER TABLE CompoundKey_Contacts WITH CHECK
    ADD CONSTRAINT UQ_CompoundKey_Contacts_CompoundKey UNIQUE (CompoundKey);

Or a simple unique constraint

ALTER TABLE CompoundKey_Contacts WITH CHECK
    ADD CONSTRAINT UQ_CompoundKey_OtherUnique UNIQUE (personID, companyId);
遮云壑 2024-12-25 03:37:31

personId,companyId 上创建唯一约束或唯一索引。

不要尝试为此使用带有 UDF 的检查约束,因为它效率低下并且无论如何都难以获得正确结果。

Create a unique constraint or unique index on personId,companyId.

Don't try using a check constraint with a UDF for this as it is inefficient and difficult to get correct anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文