我正致力于将数据验证集成到SQL Server 2014中的表架构中。
smoke
可以包含0(非吸烟者),1(吸烟者)或9(缺失)。cigarette
可以是等于或低于887,888(不适用)或999(缺失)的值。如果cigarette
包含0(非吸烟者),我希望SQL Server在smoking
中插入其他不适用(888)或丢失(999)的值时抛出错误。我该怎么做?
这是我现在拥有的一个例子:
CREATE TABLE [dbo].[CHECK_table]
(
[study_id] [smallint] NOT NULL,
[smoke] [smallint] NOT NULL,
[cigarettes] [smallint] NOT NULL,
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[CHECK_table] WITH CHECK
ADD CHECK (([smoke] = (0) OR ([smoke] = (1) OR [smoke] = (8)) OR [smoke] = (9)))
GO
ALTER TABLE [dbo].[CHECK_table] WITH CHECK
ADD CHECK (([cigarettes] <= (90) OR [cigarette] = (888) OR [cigarette] = (999)))
GO
答案 0 :(得分:1)
您可以使用CASE
并将多个OR
替换为IN
:
CREATE TABLE #CHECK_table(
[study_id] [smallint] NOT NULL,
[smoke] [smallint] NOT NULL,
[cigarettes] [smallint] NOT NULL
);
ALTER TABLE #CHECK_table
WITH CHECK ADD CHECK ([smoke] IN (0,1,9));
ALTER TABLE #CHECK_table
WITH CHECK ADD CHECK (((CASE WHEN [smoke] = 0 AND [cigarettes] IN(999,888) THEN 1
WHEN [smoke] <> 0 AND ([cigarettes] <= 888
OR [cigarettes] = 999) THEN 1
ELSE 0 END) = 1)
);
的 LiveDemo
强>
答案 1 :(得分:1)
正如其中一条评论所表达的那样,为什么不让它们NULL
用于未知数据呢?如果您使用可空的位字段,您可以获得与您的方案相同的详细信息量,具有更好的存储和性能,并且无需强制执行任何约束。
我的建议:
CREATE TABLE #CHECK_table(
[study_id] [smallint] NOT NULL,
[smoke] [bit] NULL,
[cigarettes] [smallint] NULL ,
check (( case when [smoke] = 0 then 0 else 1 end ) = 1)
)
insert into #check_table ( study_id, smoke, cigarettes ) select 1, 1, 12
insert into #check_table ( study_id, smoke, cigarettes ) select 1, 0, 12
insert into #check_table ( study_id, smoke, cigarettes ) select 1, 1, null
第二个插入将失败,并且插入与检查约束冲突的错误。
(除此之外:还有,你为什么要使用 smallint
- 你不期望看到很多记录吗?)
添加:
对于导出,当您从表中进行最终选择时(如上所述),您可以执行以下操作:
select [study_id],
cast(case when [smoke] is null then 9 else [smoke] end as smallint) as [smoke],
[cigarettes]
from #CHECK_table
这样,您的表格中就会有干净的数据,而无需任何编码。从数据的角度来看,当你看到一个列时,你看到的东西要清楚得多 - 它是“是”,“是”还是“未回答”。这也意味着,在查看代码时,很明显 你已经编写了数据以及 你已经编纂了它。