use master go use master go if object_id('sp_ReplaceTextCol') is not null drop procedure sp_ReplaceTextCol go alter procedure sp_ReplaceTextCol @tableName sysname,@colName sysname,@oldStr nvarchar(512),@newStr nvarchar(512),@whereStr nvarchar(200)='' /* 为一个表内的text做统一替换的存储过程 缺点:支持且仅支持主键为一个列的表 可见改进:可以写个只有一列的临时表 来支持多主键,更新的时候按照这个临时表来做 realgz 2008-05-05 */ as begin declare @exec nvarchar(4000),@keyName sysname,@keyValue sql_variant declare @rpPtr varbinary(16),@rpPostion int,@rpLen int select @keyName = sc.name from sysobjects so join sysindexes idx on so.parent_obj=idx.id join sysindexkeys idk on so.parent_obj=idk.id and idx.indid = idk.indid join syscolumns sc on so.parent_obj=sc.id and idk.colid=sc.colid where so.xtype='PK' and so.parent_obj =object_id(@tableName) if @@rowcount <> 1 begin raiserror ('表不符合要求或者没有这个表',12,1) return end select @rpLen=len(@oldStr),@oldStr='%'+@oldStr+'%' select @exec ='declare #c cursor static for select ['+@keyName+'],textptr('+@colname+'),PATINDEX ('''+replace(@oldStr,'''','''''')+''','+@colname+')-1 from ' +@tablename+' '+@whereStr --print @exec exec sp_executesql @exec open #c fetch next from #c into @keyValue,@rpPtr,@rpPostion while @@fetch_status=0 begin --select @keyValue,@rpPostion while @rpPostion>0 begin select @exec= 'updatetext '+@tablename+'.'+@colname+' @rpPtr @rpPostion @rpLen @NewStr' exec sp_executesql @exec,N' @rpPtr varbinary(16),@rpPostion int,@rpLen int,@newStr nvarchar(512)',@rpPtr,@rpPostion,@rpLen,@NewStr select @exec=' select @rpPostion = PATINDEX ('''+replace(@oldStr,'''','''''')+''','+@colname+')-1 from ' +@tablename+' where ['+@keyName+'] = @keyValue' exec sp_executesql @exec,N'@keyValue sql_variant ,@rpPostion int output',@keyValue,@rpPostion output end fetch next from #c into @keyValue,@rpPtr,@rpPostion end close #c deallocate #c end go if object_id('sp_ReplaceTextWithMultiColPk') is not null drop proc sp_ReplaceTextWithMultiColPk go create procedure sp_ReplaceTextWithMultiColPk @tableName sysname,@colName sysname,@oldStr nvarchar(512),@newStr nvarchar(512),@whereStr nvarchar(200)='' /* 为一个表内的text做统一替换的存储过程,sp_ReplaceTextCol升级版本 缺点:慢,而且事实上还没办法支持任意表,而且代码看起来难受 因为 varchar的长度有限,当然还可以扩展,不过在sql 2005 里已经没这个问题了,懒得再写。 realgz 2008-05-05 */ as begin set nocount on declare @exec nvarchar(4000),@fetch nvarchar(4000),@insert nvarchar(4000),@where nvarchar(4000) declare @rpPtr varbinary(16),@rpPostion int,@rpLen int if object_id('tempdb..#key') is not null drop table #key --获得主键列表 select sc.name keyName into #key from sysobjects so join sysindexes idx on so.parent_obj=idx.id join sysindexkeys idk on so.parent_obj=idk.id and idx.indid = idk.indid join syscolumns sc on so.parent_obj=sc.id and idk.colid=sc.colid where so.xtype='PK' and so.parent_obj =object_id(@tableName) and idx.status & 0x800>0 if @@rowcount < 1 begin raiserror ('表不符合要求或者没有这个表',12,1) return end --增加键值列 alter table #key add keyValue sql_variant alter table #key add primary key(keyName) --为游标的提取生成语句 select @fetch='',@insert='',@where='' select @fetch = @fetch +'declare @'+keyName +' sql_variant '+char(13) from #key select @fetch = @fetch +'fetch next from #c into @rpPtr,@rpPostion' select @fetch = @fetch +',@'+keyName +char(13) from #key --把游标提取出来的值放到临时表的语句 select @insert = @insert +' insert into #key(keyName,keyValue ) ' select @insert = @insert + ' select '''+replace(keyName,'''','''''')+''',@'+keyName+' union all' +char(13) from #key select @insert = left(@insert,len(@insert)-10) select @fetch=@fetch +@insert --替换的长度 select @rpLen=len(@oldStr),@oldStr='%'+@oldStr+'%' --游标声明语句 select @exec ='declare #c cursor static for select textptr('+@colname+'),PATINDEX ('''+replace(@oldStr,'''','''''')+''','+@colname+')-1' select @exec = @exec +',['+keyName+']' from #key select @exec = @exec +' from ' +@tablename+' '+@whereStr --每次获得游标行对应text指针的语句 select @where =' where 1=1' select @where =@where +' and ['+keyName+']= (select keyValue from #key where keyName = '''+replace(keyName,'''','''''')+''')' from #key --声明游标 exec sp_executesql @exec truncate table #key open #c --提取第一行 exec sp_executesql @fetch,N'@rpPtr varbinary(16) output,@rpPostion int output',@rpPtr output,@rpPostion output --print @fetch while @@fetch_status=0 begin --只要@rpPostion>0 证明还需要替换 while @rpPostion>0 begin --替换 select @exec= 'updatetext '+@tablename+'.'+@colname+' @rpPtr @rpPostion @rpLen @NewStr' exec sp_executesql @exec,N' @rpPtr varbinary(16),@rpPostion int,@rpLen int,@newStr nvarchar(512)',@rpPtr,@rpPostion,@rpLen,@NewStr --重新判断是否需要替换 select @exec=' select @rpPostion = PATINDEX ('''+replace(@oldStr,'''','''''')+''','+@colname+')-1 from ' +@tablename+@where exec sp_executesql @exec,N'@rpPostion int output',@rpPostion output end truncate table #key --提取下一行 exec sp_executesql @fetch,N'@rpPtr varbinary(16) output,@rpPostion int output',@rpPtr output,@rpPostion output end close #c deallocate #c if object_id('tempdb..#key') is not null drop table #key set nocount off end go |