我有两张桌子:
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 inheritance创建的,所以代码是这样的:
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的非唯一Name。
我想强制执行只有一个名称带有Sign = A且只有一个带有Sign C的名称 但很多名字有Sign = B
答案 0 :(得分:4)
是的,您可以使用索引视图强制执行此类约束,并为筛选的结果集在(Sign,Name)上创建唯一约束(索引)。
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
答案 1 :(得分:1)
要回答您的问题,无法在检查约束(或任何其他类型的约束)中引用外表中的列。但是,在您的情况下,您需要确保Names.Name
和Main.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已经要求通过其主键约束是唯一的。