发现一个SQLSERVER数据库的编绎解析问题
今天捧读SQLSERVER圣经联机帮助,设计SQL SERVER 2000复制时出现下面的问题,最后得出结论是SQL数据库引擎不能正确的解析或者说不是时候的解析。
1. 创建复制表:
--在发布服务器上创建表sales:
CREATE TABLE sales
(sale_id INT IDENTITY(1,1)
NOT FOR REPLICATION,
sales_region VARCHAR(20),
CONSTRAINT id_pk PRIMARY KEY (sale_id)
)
--在订阅服务器上创建表sales:
CREATE TABLE sales
(sale_id INT IDENTITY(100001,1)
NOT FOR REPLICATION,
sales_region VARCHAR(2),
CONSTRAINT id_pk PRIMARY KEY (sale_id)
)
CREATE TABLE sales
(sale_id INT IDENTITY(1,1)
NOT FOR REPLICATION,
sales_region VARCHAR(20),
CONSTRAINT id_pk PRIMARY KEY (sale_id)
)
--在订阅服务器上创建表sales:
CREATE TABLE sales
(sale_id INT IDENTITY(100001,1)
NOT FOR REPLICATION,
sales_region VARCHAR(2),
CONSTRAINT id_pk PRIMARY KEY (sale_id)
)
2. 建立事务复制,不可更新的订阅,其它都采用默认设置,只改发布属性“名称冲突”为“删除现有表中与行筛选语句相匹配的数据”,以防删除手工建立的表及标识列规则。在服务器插入新数据或删除旧数据时都正确,但修改数据时出错:
A.错误消息:{CALL sp_MSupd_sales (NULL,'afg2342342',2,0x02)}
上一次执行批处理的事务序列号和命令 ID 分别是 0x0000006100000082000500000000 和 1。
上一次执行批处理的事务序列号和命令 ID 分别是 0x0000006100000082000500000000 和 1。
B.上一条命:无法更新标识列 'sale_id'。
C.错误详细信息:无法更新标识列 'sale_id'。
(源: DEV1 (数据源); 错误代码: 8102)
(源: DEV1 (数据源); 错误代码: 8102)
3. 复制自动创建的订阅服务器的存储过程如下,我对错误处做了注释:
create procedure "sp_MSupd_sales"
@c1 int,@c2 varchar(20),@pkc1 int
,@bitmap binary(1)
as
if substring(@bitmap,1,1) & 1 = 1 --条件为否时,应执行ELSE语句块
begin
update "sales" set
"sale_id" = case substring(@bitmap,1,1) & 1 when 1 then @c1 else "sale_id" end --其语法完全没有问题,存储过程已创建好,标识列是不能更新的,由于@bitmap=0x02,不应该执行该语句块,但是该语句既然分析正确而且不会执行,仍然还在在执行时进行解析,???
,"sales_region" = case substring(@bitmap,1,1) & 2 when 2 then @c2 else "sales_region" end
where "sale_id" = @pkc1
if @@rowcount = 0
if @@microsoftversion>0x07320000
exec sp_MSreplraiserror 20598
end
else
begin
update "sales" set
"sales_region" = case substring(@bitmap,1,1) & 2 when 2 then @c2 else "sales_region" end
where "sale_id" = @pkc1
if @@rowcount = 0
if @@microsoftversion>0x07320000
exec sp_MSreplraiserror 20598
end
GO
@c1 int,@c2 varchar(20),@pkc1 int
,@bitmap binary(1)
as
if substring(@bitmap,1,1) & 1 = 1 --条件为否时,应执行ELSE语句块
begin
update "sales" set
"sale_id" = case substring(@bitmap,1,1) & 1 when 1 then @c1 else "sale_id" end --其语法完全没有问题,存储过程已创建好,标识列是不能更新的,由于@bitmap=0x02,不应该执行该语句块,但是该语句既然分析正确而且不会执行,仍然还在在执行时进行解析,???
,"sales_region" = case substring(@bitmap,1,1) & 2 when 2 then @c2 else "sales_region" end
where "sale_id" = @pkc1
if @@rowcount = 0
if @@microsoftversion>0x07320000
exec sp_MSreplraiserror 20598
end
else
begin
update "sales" set
"sales_region" = case substring(@bitmap,1,1) & 2 when 2 then @c2 else "sales_region" end
where "sale_id" = @pkc1
if @@rowcount = 0
if @@microsoftversion>0x07320000
exec sp_MSreplraiserror 20598
end
GO
最后得出一个结论:不是复制组件的问题,问题出在数据库引擎不能正确的解析或者说不是时候的解析,简单的试试下面的代码(先分析后执行):
CREATE TABLE Test
(
ID INT IDENTITY(1,1) NOT FOR REPLICATION,
Content VARCHAR(20),
CONSTRAINT id_pk PRIMARY KEY (ID)
)
GO
if 1=0
begin
print 'It can not be.'
update Test set ID=ID, Content=Content --where 1=0
end
else
begin
print 'Right.'
update Test set Content=Content
end
(
ID INT IDENTITY(1,1) NOT FOR REPLICATION,
Content VARCHAR(20),
CONSTRAINT id_pk PRIMARY KEY (ID)
)
GO
if 1=0
begin
print 'It can not be.'
update Test set ID=ID, Content=Content --where 1=0
end
else
begin
print 'Right.'
update Test set Content=Content
end
专注数据库技术,学以致用。