SQL Server中的约束,其中Col1中的值只能有有限的Col2中的值选择

SQL Server中的约束,其中Col1中的值只能有有限的Col2中的值选择,sql,sql-server,tsql,constraints,Sql,Sql Server,Tsql,Constraints,根据C1的值,我希望能够插入Col2的字符串的选择数量有限。以下代码用于澄清 CREATE TABLE [dbo].[tester] ( [C1] [varchar](50) NULL, [C2] [varchar](50) NULL ) ON [PRIMARY] INSERT INTO [dbo].[tester] ([C1], [C2]) VALUES ('ADDRESS', 'Primary') GO 对于字符串'address',我只想给column2一个字符串'pr

根据C1的值,我希望能够插入Col2的字符串的选择数量有限。以下代码用于澄清

CREATE TABLE [dbo].[tester]
(
    [C1] [varchar](50) NULL,
    [C2] [varchar](50) NULL
) ON [PRIMARY]

INSERT INTO [dbo].[tester] ([C1], [C2])
VALUES ('ADDRESS', 'Primary')
GO
对于字符串'address',我只想给column2一个字符串'primary','secondary','home'的选择

INSERT INTO [dbo].[tester] ([C1], [C2])
VALUES ('phone', 'home')
GO

使用字符串“phone”,我想让第2列只能选择“休闲”、“工作”、“商务”。

您可以使用
CASE
语句,并将其放入
TRY CATCH

如您所见,我将表中的列设置为不接受
NULL

DECLARE @tester TABLE
(
    [C1] [varchar](50) NOT NULL,
    [C2] [varchar](50) NOT NULL
)

DECLARE @col1 VARCHAR(20) = 'ADDRESS' , @col2 VARCHAR(20) = 'work'

BEGIN TRY
    INSERT @tester
    SELECT  CASE  WHEN @col1 = 'address' AND @col2 IN ('primary', 'secondary', 'home') THEN @col1
                  WHEN @col1 = 'phone' AND @col2 IN ('leisure', 'work', 'business') THEN @col1 ELSE NULL END
            ,CASE WHEN @col1 = 'address' AND @col2 IN ('primary', 'secondary', 'home') THEN @col2
                  WHEN @col1 = 'phone' AND @col2 IN ('leisure', 'work', 'business') THEN @col2 ELSE NULL END
END TRY

BEGIN CATCH

END CATCH

SELECT * FROM @tester

通常,您会有两个单独的表
AddressTypes
PhoneTypes
,但如果您坚持,您可以使用constraint并在其中写入允许的选项:

CREATE TABLE [dbo].[tester](
    [C1] [varchar](50) NULL,
    [C2] [varchar](50) NULL
) ON [PRIMARY]
GO

SET ANSI_PADDING ON
GO

ALTER TABLE [dbo].[tester] WITH CHECK ADD CONSTRAINT [CK_Rules] CHECK 
(
([C1]='address' AND [C2] IN ('home', 'secondary', 'primary')) OR
([C1]='phone' AND [C2] IN ('leisure', 'work', 'business'))
)
GO

ALTER TABLE [dbo].[tester] CHECK CONSTRAINT [CK_Rules]
GO
测试

INSERT INTO [dbo].[tester] ([C1],[C2]) VALUES 
('address', 'home'),
('address', 'primary'),
('phone', 'business');
返回:

(3 row(s) affected)
The INSERT statement conflicted with the CHECK constraint "CK_Rules". 
The conflict occurred in database "AdventureWorks2014", table "dbo.tester".
The statement has been terminated.
但是

返回:

(3 row(s) affected)
The INSERT statement conflicted with the CHECK constraint "CK_Rules". 
The conflict occurred in database "AdventureWorks2014", table "dbo.tester".
The statement has been terminated.

如果不想更改表结构,请参阅其他两个答案

不过,更好的处理方法是创建一个包含可能的组合的表。示例(可以更好地选择名称):

用cat+sub填充表格,然后允许使用
联系人样式的组合

INSERT INTO contact_cat(id,desc)VALUES(1,'Address');
INSERT INTO contact_cat(id,desc)VALUES(2,'Phone');
INSERT INTO contact_sub(id,desc)VALUES(1,'Primary');
INSERT INTO contact_sub(id,desc)VALUES(2,'Leisure');
INSERT INTO contact_style(cat_id,sub_id)VALUES(1,1); -- Address + Primary
INSERT INTO contact_style(cat_id,sub_id)VALUES(2,2); -- Phone + Leisure
向检测仪添加信息:

INSERT INTO tester(cat_id,sub_id,information)VALUES(1,1,'NY, 120 Boulevard Av'); -- succeeds
INSERT INTO tester(cat_id,sub_id,information)VALUES(2,2,'555 77 88 99'); -- succeeds
INSERT INTO tester(cat_id,sub_id,information)VALUES(1,2,'Blablabla'); -- fails
INSERT INTO tester(cat_id,sub_id,information)VALUES(2,1,'More blah'); -- fails
前两条语句成功,因为外键存在于
contact\u style
中允许的联系人样式中。最后两个失败是因为外键不存在于
contact\u style

这种工作方式的好处:

  • 无需每次重复联系人类别+子类别描述
  • 将这些表缓存在内存中时,可以节省磁盘空间和内存;表尽可能缓存在SQL Server中,以加快查询响应
  • 当需要新类别或子类别时,不必重写任何约束(参见其他答案)。只需在适当的表中为新的cat/SUBACT添加行,将行添加到
    contact_style
    以反映新的组合和presto

您所说的“给column2一个选择”是什么意思?你是说当有人试图在C1中插入“电话”,在C2中插入“外星人”时,你希望返回一个错误吗?你不能这样做。使用trigger而不是teadw3ave,C1将包含字符串'Address',如果有人将字符串'alien'而不是'primary',secondary',home'选项放入,我希望出现一个错误。PS:最好还是将地址和电话号码分开存储。TT.,你应该看到程序员对你的答案感到不安。:)由于你的建议,我们正在考虑增加一些表格。约束:约束FK_tester_contact_样式外键(cat_id,sub_id)引用contact_样式(cat_id,sub_id)让每个人都很高兴。还有更多…@user2241789=)好听,让他们蠕动;-)。我已经添加了一个比使用约束更好的优点。我们可以按照您在开始时的建议使用两个单独的表。我们仍在与这个答案作斗争。