sqlserver批量修改null及空字符串
在做数据迁移的过程中总会出现各种始料不及的问题,原始库中的数据总会多出不少的冗余数据或无效数据,最近工作需要需要将sqlserver数据库中的所有表存在的空字符串以及null替换为"NaN",今天来研究一下sqlserver中的空字符串以及null
null 和空字符串"的区别
null不指向任何对象,没有任何值,而空字符串"代表一个长度为0的字符串
假如有个字段是money,null可以理解为 “我有没有钱关你啥事儿 ”,而 空字符"表示“我真的没有钱,我就是个穷B”,那么数据存储中空值到底用NULL还是空字符,这个争议比较多,根据个人需要吧,区别不大。个人习惯用null值,毕竟sqlserver中有isnull()函数是可以方便的检索null值,这个对于业务上的一些处理比较方便,另外是isnull()函数是不能识别空字符的,这也与我们为什么要写下面的sql脚本。
如何来解决整个数据库的替换
整个替换逻辑大致就是循环数据库表,然后循环表中所有字段,将所有的字段检索替换一遍。逻辑简单,主要是语法上的书写。
需要用到的SQL语句
-- 查询表中所有字段名
select name from syscolumns where id=object_id('TEST01')
-- 查询数据库所有表名
select table_name from information_schema.tables
单表修改
declare @colname varchar(100),
@sql varchar(8000),
@count int,
@num int
SET @sql=''
SET @num=1
select @count=count(*) from syscolumns where id=object_id('TEST01')
while @num <= @count
BEGIN
select @colname=name from syscolumns s where id=object_id('TEST01') and colid = @num
set @sql='update TEST01 set '+@colname+'=''NaN'''+'where '+@colname+'='''' or '+@colname+' is NULL'
exec (@sql)
set @num=@num +1
end ;
这个比较简单 ,查询出表中字段数量,然后查询表中所有字段名,根据数量来循环更新语句。需要注意的是拼接sql语句不要漏掉引号。稍微修改一下,做个存储过程,如下:
单表存储过程
create procedure test_table_update
@tablename varchar(100)
as
declare @colname varchar(100),
@sql varchar(8000),
@count int,
@num int
SET @sql=''
SET @num=1
select @count=count(*) from syscolumns where id=object_id(@tablename)
while @num <= @count
BEGIN
select @colname=name from syscolumns s where id=object_id(@tablename) and colid = @num
set @sql='update '+@tablename+' set '+@colname+'=''NaN'''+'where '+@colname+'='''' or '+@colname+' is NULL'
exec (@sql)
set @num=@num +1
end ;
数据库修改
use 数据库名;
declare @tableName varchar(100), -- 表名
@tableCount varchar(100), -- 表数量
@colname varchar(100), -- 字段名
@sql varchar(8000), -- 执行sql
@count int, -- 字段数量
@num int, -- 字段数量初始
@tableNum int -- 表数量初始
SET @tableNum=1
select @tableCount=count(*) from information_schema.tables -- 将@tableCount赋值为表数量
while @tableNum <= @tableCount -- 循环表
BEGIN
select @tableName=table_name from (select row_number() over ( order by table_name) as row ,* from information_schema.tables) t where t.row =@tableNum -- 给查询到的表名赋予序号并按序号查询
select @count=count(*) from syscolumns where id=object_id(@tableName)
SET @num=1
while @num <= @count -- 循环字段
BEGIN
select @colname=name from syscolumns s where id=object_id(@tableName) and colid = @num -- 查询字段名
set @sql='update '+@tableName+' set '+@colname+'=''NaN'''+'where '+@colname+'='''' or '+@colname+' is NULL' --更新
exec (@sql) --执行
set @num=@num +1 -- 下一个字段
end ;
set @tableNum=@tableNum +1 -- 下一张表
end ;
尝试用存储过程来实现数据库下所有表修改,但不同数据库不能相互操作走了弯路, 所以只能用上述的 use database;
虽然无效,但是存储过程中拼接赋值sql带参数的写法是可以保留以供学习,有兴趣可以看看。
ALTER procedure test_schema_update02
@schemaName varchar(100) -- 数据库名
as
declare @tableName varchar(100), -- 表名
@tableCount varchar(100), -- 表数量
@colname varchar(100), -- 字段名
@sql varchar(8000), -- 执行sql
@count int, -- 字段数量
@num int, -- 字段数量初始
@tableNum int, -- 表数量初始
@schemaSql nvarchar(1000), -- 数据库拼接sql
@schemaSql02 nvarchar(1000)
SET @tableNum=1
set @schemaSql= 'select @cnt=count(*) from '+@schemaName+'.information_schema.tables'
EXECUTE sp_executesql @schemaSql, N'@schemaName varchar(100),@cnt int OUTPUT', @schemaName = @schemaName, @cnt=@tableCount OUTPUT
while @tableNum <= @tableCount -- 循环表
BEGIN
set @schemaSql02 = 'select @cnt=table_name from (select row_number() over ( order by table_name) as row ,* from '+@schemaName+'.information_schema.tables) t where t.row =@tableNum'
EXECUTE sp_executesql @schemaSql02, N'@schemaName varchar(100) ,@tableNum varchar(100) ,@cnt varchar(100) OUTPUT', @schemaName = @schemaName,@tableNum=@tableNum,@cnt=@tableName OUTPUT
-- select @tableName=table_name from (select row_number() over ( order by table_name) as row ,* from information_schema.tables) t where t.row =@tableNum -- 给查询到的表名赋予序号并按序号查询
select @count=count(*) from syscolumns where id=object_id(@tableName)
SET @num=1
while @num <= @count -- 循环字段
BEGIN
select @colname=name from syscolumns s where id=object_id(@tableName) and colid = @num -- 查询字段名
set @sql='update '+@tableName+' set '+@colname+'=''NN'''+'where '+@colname+'='''' or '+@colname+' is NULL' --更新
exec (@sql) --执行
set @num=@num +1 -- 下一个字段
end ;
set @tableNum=@tableNum +1 -- 下一张表
end ;