SQL Server 2008 中外表的列上的唯一约束

发布于 2024-09-05 14:57:29 字数 1522 浏览 1 评论 0原文

我有两个表:


create table [dbo].[Main]
(
    [ID] [int] identity(1,1) primary key not null,
    [No] [int] not null,
    [Sign] [char](1) not null
)

create table [dbo].[Names]
(
    [ID_Main][int] primary key not null,
    [Name][nvarchar](128) not null,
    constraint [FK_Main_Users] foreign key ([ID_Main]) references [dbo].[Main]([ID]),
    constraint [CK_Name] unique ([Name], [Sign])
)

问题在于第二个约束 CK_Name

有没有办法从外部表创建约束目标列?



编辑:



解释。 我在使用 EntityFramework 的 Silverlight 应用程序中使用这些表。 这些实体是由 Table per type 继承创建的,因此代码如下所示:


public abstract class Main
{
    // main properties
}

public class Names : Main
{
    // names properties
}

这迫使我不要使用 sql 视图。

示例数据。

---------------------------------------------
|  Main                |  Names             |
---------------------------------------------
|  ID  |  Sign  |  No  |  ID_Main  |  Name  |
---------------------------------------------
|   1  |     A  |   1  |    1      |  'qwe' |
|   2  |     B  |   1  |    2      |  'qwe' |
|   3  |     B  |   1  |    3      |  'qwe' |
|   4  |     C  |   1  |    4      |  'qwe' |
|   5  |     A  |   2  |    5      |  'asd' |
|   6  |     B  |   2  |    6      |  'asd' |
|   7  |     B  |   2  |    7      |  'asd' |
|   8  |     C  |   2  |    8      |  'asd' |

正如您所看到的,有一些行具有相同的名称但具有不同的符号。 不能有任何非唯一名称具有相同的符号。

我想强制执行只有一个名称带有符号 = A 且只有一个名称带有符号 C 但许多名字带有符号 = B

I have two tables:


create table [dbo].[Main]
(
    [ID] [int] identity(1,1) primary key not null,
    [No] [int] not null,
    [Sign] [char](1) not null
)

create table [dbo].[Names]
(
    [ID_Main][int] primary key not null,
    [Name][nvarchar](128) not null,
    constraint [FK_Main_Users] foreign key ([ID_Main]) references [dbo].[Main]([ID]),
    constraint [CK_Name] unique ([Name], [Sign])
)

The problem is with the second constraint CK_Name

Is there a way to make a constraint target column from a foreign table?

EDIT:

Explanation.
I'm using these tables in a Silverlight application using EntityFramework.
The entities are created by Table per type inheritance so the code is something like this:


public abstract class Main
{
    // main properties
}

public class Names : Main
{
    // names properties
}

This forces me not to use sql views.

Sample data.

---------------------------------------------
|  Main                |  Names             |
---------------------------------------------
|  ID  |  Sign  |  No  |  ID_Main  |  Name  |
---------------------------------------------
|   1  |     A  |   1  |    1      |  'qwe' |
|   2  |     B  |   1  |    2      |  'qwe' |
|   3  |     B  |   1  |    3      |  'qwe' |
|   4  |     C  |   1  |    4      |  'qwe' |
|   5  |     A  |   2  |    5      |  'asd' |
|   6  |     B  |   2  |    6      |  'asd' |
|   7  |     B  |   2  |    7      |  'asd' |
|   8  |     C  |   2  |    8      |  'asd' |

As you can see there are some rows with the same Name but with different Sign.
There can't be any non unique Name with the same Sign.

I'd like to enforce that there is only one Name with Sign = A and only one Name with Sign C
but many Names with Sign = B

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

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

发布评论

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

评论(2

莫言歌 2024-09-12 14:57:30

是的,您可以使用索引视图强制执行此类约束,并为筛选结果集的(签名、名称)创建唯一约束(索引)。

CREATE VIEW dbo.vwSelectiveUniqueSignName WITH SCHEMABINDING
AS
SELECT  [Sign], Name
FROM    
    dbo.Main INNER JOIN dbo.Names on ID = ID_Main
WHERE
    dbo.Main.Sign IN ('A', 'C')
GO

CREATE UNIQUE CLUSTERED INDEX IDX_vwSelectiveUniqueSignName_Unique_Sign_Name
    ON dbo.vwSelectiveUniqueSignName ( [Sign] ASC, Name ASC )
GO

测试:

-- using your sample data:
/* Case 1 Sign = 'A', Name = 'qwe': this will throw error 'cannot insert duplicate key row in object ... with unique index ... */
BEGIN TRAN NotAllowedMoreThan_1
insert dbo.Main ([Sign]) OUTPUT inserted.* values ('A') /* same for 'C' */
insert dbo.Names (ID_Main, Name) OUTPUT inserted.* SELECT SCOPE_IDENTITY(),'qwe'
COMMIT TRAN NotAllowedMoreThan_1
GO

/* Case 2 Sign = 'B', Name = 'qwe': this will pass > 1 times (note GO loop) */
BEGIN TRAN AllowedMoreThan_1
insert dbo.Main ([Sign]) OUTPUT inserted.* values ('B') /* any other than A, C */
insert dbo.Names (ID_Main, Name) OUTPUT inserted.* SELECT SCOPE_IDENTITY(),'qwe'
COMMIT TRAN AllowedMoreThan_1
GO 2

Yes you can enforce such constraint using indexed view and creating a unique constraint (index) on (Sign, Name) for the filtered resultset.

CREATE VIEW dbo.vwSelectiveUniqueSignName WITH SCHEMABINDING
AS
SELECT  [Sign], Name
FROM    
    dbo.Main INNER JOIN dbo.Names on ID = ID_Main
WHERE
    dbo.Main.Sign IN ('A', 'C')
GO

CREATE UNIQUE CLUSTERED INDEX IDX_vwSelectiveUniqueSignName_Unique_Sign_Name
    ON dbo.vwSelectiveUniqueSignName ( [Sign] ASC, Name ASC )
GO

Test:

-- using your sample data:
/* Case 1 Sign = 'A', Name = 'qwe': this will throw error 'cannot insert duplicate key row in object ... with unique index ... */
BEGIN TRAN NotAllowedMoreThan_1
insert dbo.Main ([Sign]) OUTPUT inserted.* values ('A') /* same for 'C' */
insert dbo.Names (ID_Main, Name) OUTPUT inserted.* SELECT SCOPE_IDENTITY(),'qwe'
COMMIT TRAN NotAllowedMoreThan_1
GO

/* Case 2 Sign = 'B', Name = 'qwe': this will pass > 1 times (note GO loop) */
BEGIN TRAN AllowedMoreThan_1
insert dbo.Main ([Sign]) OUTPUT inserted.* values ('B') /* any other than A, C */
insert dbo.Names (ID_Main, Name) OUTPUT inserted.* SELECT SCOPE_IDENTITY(),'qwe'
COMMIT TRAN AllowedMoreThan_1
GO 2
木槿暧夏七纪年 2024-09-12 14:57:30

为了回答您的问题,没有办法在检查约束(或任何其他类型的约束)中引用外部表中的列。但是,在您的情况下,您希望确保 Names.NameMain.Sign 的任何组合都是唯一的。为此,您可以简单地在两列中的每一列上添加唯一约束:

Alter Table dbo.Main Add Constraint UC_Main Unique Nonclustered ( Sign )
GO
Alter Table dbo.Names Add Constraint UC_Names Unique Nonclustered ( Name )

无需同时在 ID_Main 和 Name 上创建唯一约束,因为 ID_Main 已要求通过其主键约束保持唯一。

To answer your question, there is no means to reference a column in a foreign table in a check constraint (or any other kind of constraint for that matter). However, in your situation, you want to ensure that any combination of Names.Name and Main.Sign will be unique. To do that you can simply add a unique constraint on each of the two columns:

Alter Table dbo.Main Add Constraint UC_Main Unique Nonclustered ( Sign )
GO
Alter Table dbo.Names Add Constraint UC_Names Unique Nonclustered ( Name )

There is no need to create a unique constraint on ID_Main and Name together since ID_Main is already required to be unique via its primary key constraint.

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