簡體   English   中英

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

[英]UNIQUE CONSTRAINT on a column from foreign table in SQL Server 2008

我有兩個表:


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創建實體,因此代碼如下所示:


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' |

如您所見,有些行具有相同的名稱,但具有不同的符號。 不能有帶有相同符號的任何非唯一名稱。

我要強制說,只有一個名稱帶有Sign = A的名稱,只有一個名稱帶有Sign C的名稱,但有許多帶有Sign = B的名稱

是的,您可以使用索引視圖並在過濾后的結果集的(符號,名稱)上創建唯一約束(索引),從而實施此類約束。

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

要回答您的問題,沒有辦法在檢查約束(或與此相關的任何其他類型的約束)中引用外部表中的列。 但是,根據您的情況,您要確保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通過其主鍵約束來唯一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM