前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mssql全库查找且替换字段

mssql全库查找且替换字段

作者头像
cultureSun
发布2023-11-24 09:25:11
1280
发布2023-11-24 09:25:11
举报
文章被收录于专栏:cultureSun学安全cultureSun学安全

业务场景

两个业务实体合并。假设业务实体为人员A人员B,需要将两个人员的相关数据合并,且保留人员B,删掉人员A

通过分析实际的场景,在库中存的相关业务数据都是通过人员ID关联人员的,而人员ID在库中是唯一的值。所以只需要全库所有表中查找人员A的 ID,替换成人员B,即可完成两个人员的合并需求(注意排除存储人员的数据表)。

具体实现

分两种:

  1. 一种是某表某字段只存储一位人员ID
  2. 一种是此字段存储多位人员ID(中间有分隔符)

第一种:

代码语言:javascript
复制
DECLARE @OldValue NVARCHAR(MAX) = '人员A-ID'
DECLARE @NewValue NVARCHAR(MAX) = '人员B-ID'

DECLARE @TableName NVARCHAR(MAX)
DECLARE @ColumnName NVARCHAR(MAX)
DECLARE @UpdateStmt NVARCHAR(MAX)
DECLARE @SqlQuery NVARCHAR(MAX)
DECLARE @aExists INT
DECLARE @SQLString NVARCHAR(1000)

--创建游标,获取库中所有(表名,列名)
DECLARE tableCursor CURSOR FOR
SELECT t.name AS TableName, c.name AS ColumnName
FROM sys.tables t
INNER JOIN sys.columns c ON t.object_id = c.object_id
WHERE c.system_type_id IN (167, 175, 231, 239) -- 数据类型为char、varchar、nchar、nvarchar的列

--  CREATE TABLE #TempTable (
--     ID NVARCHAR(MAX),
--      CNAME NVARCHAR(MAX)
-- )
-- 
--获取游标中的行
OPEN tableCursor
FETCH NEXT FROM tableCursor INTO @TableName, @ColumnName

--循环游标
WHILE @@FETCH_STATUS = 0
BEGIN
        --用来排除某些表或者列
        IF @TableName='TABLE-A' OR @ColumnName='COLUMN-A'
        BEGIN
            FETCH NEXT FROM tableCursor INTO @TableName, @ColumnName
            CONTINUE
        END
        
        --判断此表此列是否存在 值 等于 人员A-ID ,如果有替换值
        SET @SqlQuery = 'SELECT @aExists=1 FROM ' + QUOTENAME(@TableName) + ' WHERE ' + QUOTENAME(@ColumnName) + ' = @OldValue'
        EXEC sp_executesql @SqlQuery, N'@OldValue NVARCHAR(MAX), @aExists INT OUTPUT', @OldValue, @aExists OUTPUT

        IF @aExists=1
        BEGIN
            --将相关的合并数据进行备份,备份表(bak_tran),此表结构应根据具体情况设计,以下只供参考。原本打算存在临时表(TempTable)
             SET @SQLString = 'SELECT ID,'''+@TableName+''','''+@ColumnName+''','''+@NewValue+''','''+@OldValue+''' FROM '+QUOTENAME(@TableName)+' WHERE ' +QUOTENAME(@ColumnName)+' = @OldValue'
            INSERT INTO [bak_tran](id,tname,cname,new,old) EXEC sp_executesql @SQLString,N'@OldValue NVARCHAR(MAX)',@OldValue
            
            --将 人员A-ID 替换为 人以员B-ID
      SET @UpdateStmt = 'UPDATE ' + QUOTENAME(@TableName) + ' SET ' + QUOTENAME(@ColumnName) + ' = CASE WHEN '+QUOTENAME(@ColumnName)+' =@OldValue THEN @NewValue ELSE '+QUOTENAME(@ColumnName)+' END'        
      EXEC sp_executesql @UpdateStmt, N'@OldValue NVARCHAR(MAX), @NewValue NVARCHAR(MAX)', @OldValue, @NewValue
        END
        
        SET @aExists = 0
    FETCH NEXT FROM tableCursor INTO @TableName, @ColumnName
END
-- SELECT * FROM #TempTable
--关闭且删除游标
CLOSE tableCursor
DEALLOCATE tableCursor

第二种:

代码语言:javascript
复制
DECLARE @OldValue NVARCHAR(MAX) = '人员A-ID'
DECLARE @NewValue NVARCHAR(MAX) = '人员B-ID'

DECLARE @TableName NVARCHAR(MAX)
DECLARE @ColumnName NVARCHAR(MAX)
DECLARE @UpdateStmt NVARCHAR(MAX)
DECLARE @SqlQuery NVARCHAR(MAX)
DECLARE @aExists INT
DECLARE @SQLString NVARCHAR(1000)

--创建游标,获取库中所有(表名,列名)
DECLARE tableCursor CURSOR FOR
SELECT t.name AS TableName, c.name AS ColumnName
FROM sys.tables t
INNER JOIN sys.columns c ON t.object_id = c.object_id
WHERE c.system_type_id IN (167, 175, 231, 239) -- 数据类型为char、varchar、nchar、nvarchar的列

--  CREATE TABLE #TempTable (
--     ID NVARCHAR(MAX),
--      CNAME NVARCHAR(MAX)
-- )
-- 
--获取游标中的行
OPEN tableCursor
FETCH NEXT FROM tableCursor INTO @TableName, @ColumnName

--循环游标
WHILE @@FETCH_STATUS = 0
BEGIN
        --用来排除某些表或者列
        IF @TableName='TABLE-A' OR @ColumnName='COLUMN-A'
        BEGIN
            FETCH NEXT FROM tableCursor INTO @TableName, @ColumnName
            CONTINUE
        END
        
        --判断此表此列是否存在 值 等于 人员A-ID ,如果有替换值
        SET @SqlQuery = 'SELECT @aExists=1 FROM ' + QUOTENAME(@TableName) + ' WHERE ' + QUOTENAME(@ColumnName) + ' = @OldValue'
        EXEC sp_executesql @SqlQuery, N'@OldValue NVARCHAR(MAX), @aExists INT OUTPUT', @OldValue, @aExists OUTPUT

        IF @aExists=1
        BEGIN
            --将相关的合并数据进行备份,备份表(bak_tran),此表结构应根据具体情况设计,以下只供参考。原本打算存在临时表(TempTable)
             SET @SQLString = 'SELECT ID,'''+@TableName+''','''+@ColumnName+''','''+@NewValue+''','''+@OldValue+''' FROM '+QUOTENAME(@TableName)+' WHERE ' +QUOTENAME(@ColumnName)+' = @OldValue'
            INSERT INTO [bak_tran](id,tname,cname,new,old) EXEC sp_executesql @SQLString,N'@OldValue NVARCHAR(MAX)',@OldValue
            
            --将 人员A-ID 替换为 人以员B-ID
      SET @UpdateStmt = 'UPDATE ' + QUOTENAME(@TableName) + ' SET ' + QUOTENAME(@ColumnName) + ' = replace( '+QUOTENAME(@ColumnName)+',@OldValue,@NewValue) '
      EXEC sp_executesql @UpdateStmt, N'@OldValue NVARCHAR(MAX), @NewValue NVARCHAR(MAX)', @OldValue, @NewValue
        END
        
        SET @aExists = 0
    FETCH NEXT FROM tableCursor INTO @TableName, @ColumnName
END
-- SELECT * FROM #TempTable
--关闭且删除游标
CLOSE tableCursor
DEALLOCATE tableCursor

代码讲解

第一种和第二种的唯一差别是 48 行的 SQL 语句不同,一个是用 case 判断替换全值,一个是用 replace 函数部分替换。

首先,从sys.tables表查找全库的表和列,且赋值给游标。 然后,循环游标。 之后,判断某些表名和列名,用来排除一些特殊表或者列。 下一步,判断是否存在被替换值,若有则进行数据备份(为了安全起见) 最后,替换值,结尾删除游标

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-11-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com