处理SQL 2008/08 中的OUTPUT与CHECK约束冲突的问题
2009-04-22 05:06
357 查看
在SQL Server 2005中,新增的OUTPUT子句极大地提高了数据转移的方便性,不过很遗憾的是, OUTPUT子句的输出表不能包含启用状态的CHECK约束。这未免让人觉得很不爽。不过,在实际使用过程中,却发现了一个很奇怪的问题,某些具有启用状态的CHECK约束的表确实无法用于OUTPUT子句,而某些表却是可以的,经过对比,发现了这个很奇怪现象的原因,使得可以把有启用状态的CHECK约束的表用于OUTPUT子句。
下面是演示。
USE tempdb;
GO
-- 建立测试表
CREATE TABLE dbo.tb_source(
id int
);
CREATE TABLE dbo.tb_target(
id int,
CONSTRAINT CHK__tb_target__id
CHECK(
id > 0)
);
GO
-- OUTPUT 测试1
DELETE dbo.tb_source
OUTPUT deleted.*
INTO dbo.tb_target;
/*-- 会收到错误
消息333,级别16,状态1,第3 行
OUTPUT INTO 子句的目标表'dbo.tb_target' 不能具有任何启用的检查约束或任何启用的规则。找到检查约束或规则'CHK__tb_target__id'。
--*/
GO
-- 禁用和启用约束
ALTER TABLE dbo.tb_target
NOCHECK CONSTRAINT ALL;
ALTER TABLE dbo.tb_target
CHECK CONSTRAINT ALL;
GO
-- OUTPUT 测试2
DELETE dbo.tb_source
OUTPUT deleted.*
INTO dbo.tb_target;
/*-- 测试成功
(0 行受影响)
--*/
GO
-- 验证CHECK 约束是否正常工作
INSERT dbo.tb_target
VALUES(
-1);
/*-- 结果(违反约束)
消息547,级别16,状态0,第3 行
INSERT 语句与CHECK 约束"CHK__tb_target__id"冲突。该冲突发生于数据库"tempdb",表"dbo.tb_target", column 'id'。
语句已终止。
--*/
GO
-- 验证OUTPUT 时, CHECK 约束是否正常工作
INSERT dbo.tb_source
VALUES(
-1);
DELETE dbo.tb_source
OUTPUT deleted.*
INTO dbo.tb_target;
/*-- 结果(违反约束)
(1 行受影响)
消息547,级别16,状态0,第6 行
DELETE 语句与CHECK 约束"CHK__tb_target__id"冲突。该冲突发生于数据库"tempdb",表"dbo.tb_target", column 'id'。
语句已终止。
--*/
GO
-- 删除测试
DROP TABLE dbo.tb_source, dbo.tb_target;
从测试可以看出,只要CHECK约束是使用WITH NOCHECK启用的,则可以作为OUTPUT子句的输出表(与微软给的错误提示信息显示不一样)。
而且这种情况,同样适用于使用WITH NOCHECK创建的约束,参考下面的脚本。
USE tempdb;
GO
-- 建立测试表
CREATE TABLE dbo.tb_source(
id int
);
CREATE TABLE dbo.tb_target(
id int
);
ALTER TABLE dbo.tb_target
WITH NOCHECK
ADD CONSTRAINT CHK__tb_target__id
CHECK(
id > 0);
GO
-- OUTPUT 测试
DELETE dbo.tb_source
OUTPUT deleted.*
INTO dbo.tb_target;
/*-- 测试成功
(0 行受影响)
--*/
GO
-- 删除测试
DROP TABLE dbo.tb_source, dbo.tb_target;
注:
1. 默认情况下,建立约束使用的是WITH CHECK,而启用约束使用的是WITH NOCHECK;
2. WITH NOCHECK只是确定在建立(启用)约束时,是否检查表中的现有数据,对新进的数据没有影响;
3. WITH NOCHECK会导致分区视图失败。
下面是演示。
USE tempdb;
GO
-- 建立测试表
CREATE TABLE dbo.tb_source(
id int
);
CREATE TABLE dbo.tb_target(
id int,
CONSTRAINT CHK__tb_target__id
CHECK(
id > 0)
);
GO
-- OUTPUT 测试1
DELETE dbo.tb_source
OUTPUT deleted.*
INTO dbo.tb_target;
/*-- 会收到错误
消息333,级别16,状态1,第3 行
OUTPUT INTO 子句的目标表'dbo.tb_target' 不能具有任何启用的检查约束或任何启用的规则。找到检查约束或规则'CHK__tb_target__id'。
--*/
GO
-- 禁用和启用约束
ALTER TABLE dbo.tb_target
NOCHECK CONSTRAINT ALL;
ALTER TABLE dbo.tb_target
CHECK CONSTRAINT ALL;
GO
-- OUTPUT 测试2
DELETE dbo.tb_source
OUTPUT deleted.*
INTO dbo.tb_target;
/*-- 测试成功
(0 行受影响)
--*/
GO
-- 验证CHECK 约束是否正常工作
INSERT dbo.tb_target
VALUES(
-1);
/*-- 结果(违反约束)
消息547,级别16,状态0,第3 行
INSERT 语句与CHECK 约束"CHK__tb_target__id"冲突。该冲突发生于数据库"tempdb",表"dbo.tb_target", column 'id'。
语句已终止。
--*/
GO
-- 验证OUTPUT 时, CHECK 约束是否正常工作
INSERT dbo.tb_source
VALUES(
-1);
DELETE dbo.tb_source
OUTPUT deleted.*
INTO dbo.tb_target;
/*-- 结果(违反约束)
(1 行受影响)
消息547,级别16,状态0,第6 行
DELETE 语句与CHECK 约束"CHK__tb_target__id"冲突。该冲突发生于数据库"tempdb",表"dbo.tb_target", column 'id'。
语句已终止。
--*/
GO
-- 删除测试
DROP TABLE dbo.tb_source, dbo.tb_target;
从测试可以看出,只要CHECK约束是使用WITH NOCHECK启用的,则可以作为OUTPUT子句的输出表(与微软给的错误提示信息显示不一样)。
而且这种情况,同样适用于使用WITH NOCHECK创建的约束,参考下面的脚本。
USE tempdb;
GO
-- 建立测试表
CREATE TABLE dbo.tb_source(
id int
);
CREATE TABLE dbo.tb_target(
id int
);
ALTER TABLE dbo.tb_target
WITH NOCHECK
ADD CONSTRAINT CHK__tb_target__id
CHECK(
id > 0);
GO
-- OUTPUT 测试
DELETE dbo.tb_source
OUTPUT deleted.*
INTO dbo.tb_target;
/*-- 测试成功
(0 行受影响)
--*/
GO
-- 删除测试
DROP TABLE dbo.tb_source, dbo.tb_target;
注:
1. 默认情况下,建立约束使用的是WITH CHECK,而启用约束使用的是WITH NOCHECK;
2. WITH NOCHECK只是确定在建立(启用)约束时,是否检查表中的现有数据,对新进的数据没有影响;
3. WITH NOCHECK会导致分区视图失败。
相关文章推荐
- SQL Server 2008 中SQL查询语句中字段值不区分大小写问题处理
- Sql 08 安装【win7下SQLServer 2008 R2安装详细图文教程】 + Sql Server服务 远程过程调用失败问题的解决方案
- 解决SqlTransaction用尽的问题(SQL处理超时)
- 处理Sever 2008 连接 Openfiler的iSCSI存储chap认证失败的问题
- 11g dg 从库sql性能问题处理吐槽
- sql server 2008 之找不到SQL Server Management Studio的处理方法
- Access转成Sql 2008步骤,同时解决自动编号问题,主键,id数值不重置
- SQL Server 2008 Analysis Services 多维数据库一步一步从入门到精通(二)---定义和部署多维数据集及问题处理
- 安装Windows 2008 R2 + SQL Server 2005 64Bit问题处理
- SQL 重复记录问题的处理方法小结
- ArcSDE for SQL Server 2008 安装问题汇总
- C#对于字符串的处理类(剪裁、过滤危险字符、替换sql中有问题符号等)
- SQL 2008 RAISERROR语法在SQL 2012/2014不兼容问题
- 记一次处理oracle分区表索引"乱用"引起的SQL性能问题
- 关于如何处理JSONObject.fromObject(Object obj)无法转换特殊日期(java.sql.Date,java.sql.Timestamp)格式的问题。
- SQL Server R2 2008中的SQL Server Management Studio 阻止保存要求重新创建表的更改问题的设置方法
- 【问题处理】arcgis运行在android studio上jar包冲突解决
- powerpoint、excel 2007与visual studio 2008 起冲突,打开时显示安装的问题解决方法
- 有关SQL排序规则---------即"无法解决 equal to 操作的排序规则冲突"等等的菜问题.
- MS SQL Server2014链接到MS SQL Server 2000的解决方案及问题处理