【问题标题】:SQL Server- SQL Replace on all columns in all tables across an entire DBSQL Server-SQL 替换整个数据库中所有表中的所有列
【发布时间】:2019-03-08 17:38:15
【问题描述】:

这是一个长镜头,我猜这没有简单的答案,但是...... 我继承了一个数据库,其中填充了一些可怕的数据。许多包含描述的行都有回车字符,这意味着当我们 BCP 输出数据时,它会带回车。

我的问题: 有没有办法在 MS SQL Server 中对整个数据库进行全局替换?该数据库包含数百个表,因此逐个表执行此表可能会非常耗时。

任何提示或提示将不胜感激。

提前致谢。 皮特。

【问题讨论】:

  • 您不能在 BCP 期间删除不需要的字符吗?
  • 谢谢托马斯。这很可能,但我希望有一种方法可以从源头清理数据。如果我找不到方法,那么我一定会沿着那条路往下看。感谢您的启发。
  • 您可以编写一个查询元表/视图并生成动态 SQL 更新的解决方案。
  • 如果您有任何基于时间戳/CDC 的应用程序并且您的数据库很大,请小心,因为您将更新整个数据库

标签: sql sql-server


【解决方案1】:

我假设您想在整个数据库中进行查找和替换。如果是这样,try this script from MSSQLTIPS。它正是这样做的。

这是完整的脚本:

SET NOCOUNT ON

DECLARE @stringToFind VARCHAR(100)
DECLARE @stringToReplace VARCHAR(100)
DECLARE @schema sysname
DECLARE @table sysname
DECLARE @count INT
DECLARE @sqlCommand VARCHAR(8000)
DECLARE @where VARCHAR(8000)
DECLARE @columnName sysname
DECLARE @object_id INT

SET @stringToFind = 'Smith'
SET @stringToReplace = 'Jones'

DECLARE TAB_CURSOR CURSOR  FOR
SELECT   B.NAME      AS SCHEMANAME,
         A.NAME      AS TABLENAME,
         A.OBJECT_ID
FROM     sys.objects A
         INNER JOIN sys.schemas B
           ON A.SCHEMA_ID = B.SCHEMA_ID
WHERE    TYPE = 'U'
ORDER BY 1

OPEN TAB_CURSOR

FETCH NEXT FROM TAB_CURSOR
INTO @schema,
     @table,
     @object_id

WHILE @@FETCH_STATUS = 0
  BEGIN
    DECLARE COL_CURSOR CURSOR FOR
    SELECT A.NAME
    FROM   sys.columns A
           INNER JOIN sys.types B
             ON A.SYSTEM_TYPE_ID = B.SYSTEM_TYPE_ID
    WHERE  OBJECT_ID = @object_id
           AND IS_COMPUTED = 0
           AND B.NAME IN ('char','nchar','nvarchar','varchar','text','ntext')

    OPEN COL_CURSOR

    FETCH NEXT FROM COL_CURSOR
    INTO @columnName

    WHILE @@FETCH_STATUS = 0
      BEGIN
        SET @sqlCommand = 'UPDATE ' + @schema + '.[' + @table + '] SET [' + @columnName
                           + '] = REPLACE(convert(nvarchar(max),[' + @columnName + ']),'''
                           + @stringToFind + ''',''' + @stringToReplace + ''')'

        SET @where = ' WHERE [' + @columnName + '] LIKE ''%' + @stringToFind + '%'''

        EXEC( @sqlCommand + @where)

        SET @count = @@ROWCOUNT

        IF @count > 0
          BEGIN
            PRINT @sqlCommand + @where
            PRINT 'Updated: ' + CONVERT(VARCHAR(10),@count)
            PRINT '----------------------------------------------------'
          END

        FETCH NEXT FROM COL_CURSOR
        INTO @columnName
      END

    CLOSE COL_CURSOR
    DEALLOCATE COL_CURSOR

    FETCH NEXT FROM TAB_CURSOR
    INTO @schema,
         @table,
         @object_id
  END

CLOSE TAB_CURSOR 

【讨论】:

  • 完美!这是金色的。我已经对其进行了一些调整以满足我的需求,但效果很好!感谢您的意见。
  • @PeteFoulkes 没问题。如果这回答了您的问题,您可以将其标记为解决方案。 :)
【解决方案2】:

你可以试试这个:

declare @charToReplace varchar(10) = 'char(13)' -- Carriage Return, CHAR(10) for line feed. Needs to be enclosed on quotes

select ROW_NUMBER() OVER (ORDER BY name) as ID
    , name as TableName
into #tables
from sys.tables

declare @Counter int = 0
declare @TotalTables int = (select COUNT(1) from #tables)

while @Counter < @TotalTables
begin

    declare @CurrTableName varchar(128) = (select TableName from #tables where ID = (@Counter + 1))
    declare @Columns nvarchar(4000) = ''
    declare @SQLQuery nvarchar(4000) = ''

    SELECT @Columns = COALESCE(@Columns + ',' , '') + c.name + ' = REPLACE(' + c.name + ', ' + @charToReplace + ', '''')'
    FROM SYS.tables t 
        INNER JOIN sys.columns c 
            ON C.object_id = t.object_id 
    where t.name = @CurrTableName 
        and c.user_type_id in (167, 231, 239)

    set @SQLQuery = 'UPDATE ' + @CurrTableName + ' SET ' + SUBSTRING(@Columns, 2, LEN(@Columns))

    print @SQLQuery -- You can change this to EXEC SP_EXECutesql @SQLQuery

    set @Counter += 1;

end

drop table #tables

我没有对此进行测试,但我希望它可以引导您找到您正在寻找的解决方案。

注意:print @SQLQuery 应替换为EXEC SP_EXECutesql @SQLQuery,以便它可以对数据库进行更改。

【讨论】:

    猜你喜欢
    • 2012-06-24
    • 2018-02-07
    • 2011-02-13
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    相关资源
    最近更新 更多