Sql server 查找并替换SQL Server数据库中的所有字符串数据

Sql server 查找并替换SQL Server数据库中的所有字符串数据,sql-server,database,replace,find,Sql Server,Database,Replace,Find,我正在寻找一个脚本,它可以找到并用指定的文本替换数据库中字符串类型的所有字段 例如,脚本将采用以下参数: 搜索:null 替换为:空字符串 SQL Server中的主要字符串数据类型:Varchar,NVarchar,Text 然后,该脚本将梳理所有基于字符串的表数据,在本例中查找null,并将其替换为空字符串 好的,我同时整理了以下代码 -- Specify 'dbo' for all tables DECLARE @schemaName VARCHAR(5) = 'dbo' BEGIN

我正在寻找一个脚本,它可以找到并用指定的文本替换数据库中字符串类型的所有字段

例如,脚本将采用以下参数:

  • 搜索:
    null
  • 替换为:
    空字符串
SQL Server中的主要字符串数据类型:
Varchar
NVarchar
Text

然后,该脚本将梳理所有基于字符串的表数据,在本例中查找
null
,并将其替换为空字符串

好的,我同时整理了以下代码

-- Specify 'dbo' for all tables
DECLARE @schemaName VARCHAR(5) = 'dbo'

BEGIN   
    DECLARE @tableName VARCHAR(255) -- table name   
    DECLARE @tableID INT -- table id (aka syst.table.object_id)   
    DECLARE table_cursor CURSOR FOR 
        SELECT T.object_id AS TableID, T.name AS TableName FROM sys.tables T
        INNER JOIN sys.schemas S ON S.schema_id = T.schema_id
        WHERE S.name = @schemaName
    OPEN table_cursor   
    FETCH NEXT FROM table_cursor INTO @tableID, @tableName  

    WHILE @@FETCH_STATUS = 0   
    BEGIN              
       -- construct each tables queries                 
        DECLARE @totalColumnsFound INT = (SELECT COUNT(*) FROM sys.columns C WHERE OBJECT_ID = @tableID 
        -- text and nvarchar column data types chosen for me (if you need more like ntext, varcahr see sys.types for their ids) 
        AND (C.system_type_id = 35 OR c.system_type_id = 231))
        IF (@totalColumnsFound > 0) 
        BEGIN
            DECLARE @tableUpdateQuery VARCHAR(MAX) = 'update ' + @schemaName + '.' + @tableName + ' set ';
            DECLARE @columnName VARCHAR(255) -- column name   
            DECLARE column_cursor CURSOR FOR 
                SELECT C.name AS ColumnName FROM sys.columns C WHERE OBJECT_ID = @tableID 
                -- text and nvarchar column data types chosen for me (if you need more like ntext, varcahr see sys.types for their ids) 
                AND (C.system_type_id = 35 OR c.system_type_id = 231) 
                OPEN column_cursor   
                FETCH NEXT FROM column_cursor INTO @columnName  

            WHILE @@FETCH_STATUS = 0   
            BEGIN      
               -- construct the columns for the update query, piece by piece.  
               -- This is also where you can apply your logic for how to handle the string update. 
               -- I am trimming string and updating nulls to empty strings here.
               SET @tableUpdateQuery = @tableUpdateQuery + ' ' + @columnName + ' = ltrim(rtrim(isnull(' + @columnName + ',''''))),'                
               FETCH NEXT FROM column_cursor INTO @columnName 
            END  

            CLOSE column_cursor   
            DEALLOCATE column_cursor

            -- trim last comma from string
            SET @tableUpdateQuery = LEFT(@tableUpdateQuery, LEN(@tableUpdateQuery) - 1)

            /** debuging purposes **
            print 'Updating table --> ' + @tableName
            print @tableUpdateQuery
            print ' '
            */

            -- execute dynamic sql
            EXEC(@tableUpdateQuery)                                 
        END    

       FETCH NEXT FROM table_cursor INTO @tableID, @tableName 
    END  

    CLOSE table_cursor   
    DEALLOCATE table_cursor 

END
--GO
这将有助于您:

/*
Author: sqiller
Description: Searches for a value to replace in all columns from all tables
USE: EXEC dbo.usp_Update_AllTAbles 'work', 'sqiller', 1
@search = Value to look for Replace
@newvalue = the value that will replace @search
@Test = If set to 1, it will only PRINT the UPDATE statement instead of EXEC, useful to see
        what is going to update before.
*/
CREATE PROCEDURE dbo.usp_Update_AllTAbles(
@search varchar(100),
@newvalue varchar(100),
@Test bit)
AS
BEGIN

            IF NOT EXISTS (select 1 from INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Tables_to_Update')
            BEGIN
                    CREATE TABLE dbo.Tables_to_Update(
                    Table_name varchar(100),
                    Column_name varchar(100),
                    recordsToUpdate int
                    )
            END
            DECLARE @table varchar(100)
            DECLARE @column varchar(100)
            DECLARE @SQL varchar(max)

            SELECT TABLE_SCHEMA+'.'+TABLE_NAME as Table_Name, 0 as Processed INTO #tables from information_schema.tables WHERE TABLE_TYPE != 'VIEW'

            WHILE EXISTS (select * from #tables where processed = 0)
            BEGIN
                SELECT top 1 @table = table_name from #tables where processed = 0

                SELECT column_name, 0 as Processed INTO #columns from information_schema.columns where TABLE_SCHEMA+'.'+TABLE_NAME = @table


                WHILE EXISTS (SELECT * from #columns where processed = 0)
                BEGIN
                    SELECT top 1 @column = COLUMN_NAME from #columns where processed = 0

                    SET @SQL = 'INSERT INTO Tables_to_Update
                                select '''+ @table +''', '''+ @column +''', count(*) from '+@table+ ' where '+ @column +' like ''%'+ @search +'%'''
                    EXEC(@SQL)

                    IF EXISTS (SELECT * FROM Tables_to_Update WHERE Table_name = @table)
                    BEGIN
                        SET @SQL = 'UPDATE '+ @table + ' SET '+ @column + ' = REPLACE('''+@column+''','''+@search+''','''+ @newvalue +''')  WHERE '+ @column + ' like ''%'+@search+'%'''
                        --UPDATE HERE
                        IF (@Test = 1)
                        BEGIN   
                            PRINT @SQL
                        END
                        ELSE
                        BEGIN
                            EXEC(@SQL)
                        END
                    END

                    UPDATE #columns SET Processed = 1 where COLUMN_NAME = @column
                END

                DROP TABLE #columns

                UPDATE #tables SET Processed = 1 where table_name = @table
            END

            SELECT * FROM Tables_to_Update where recordsToUpdate > 0

END
以下内容将在您连接到的实例的每个表上的每个数据库(不包括系统数据库)中查找并替换字符串: 只需将
'Search String'
更改为您要搜索的内容,并将
'Replace String'
更改为您要替换的内容

--Getting all the databases and making a cursor
DECLARE db_cursor CURSOR FOR  
SELECT name 
FROM master.dbo.sysdatabases 
WHERE name NOT IN ('master','model','msdb','tempdb')  -- exclude these databases

DECLARE @databaseName nvarchar(1000)
--opening the cursor to move over the databases in this instance
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @databaseName   

WHILE @@FETCH_STATUS = 0   
BEGIN
    PRINT @databaseName
    --Setting up temp table for the results of our search
    DECLARE @Results TABLE(TableName nvarchar(370), RealColumnName nvarchar(370), ColumnName nvarchar(370), ColumnValue nvarchar(3630))

    SET NOCOUNT ON

    DECLARE @SearchStr nvarchar(100), @ReplaceStr nvarchar(100), @SearchStr2 nvarchar(110)
    SET @SearchStr = 'Search String'
    SET @ReplaceStr = 'Replace String'
    SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')

    DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128)
    SET  @TableName = ''

    --Looping over all the tables in the database
    WHILE @TableName IS NOT NULL
    BEGIN
        DECLARE @SQL nvarchar(2000)
        SET @ColumnName = ''
        DECLARE @result NVARCHAR(256)
        SET @SQL = 'USE ' + @databaseName + '
            SELECT @result = MIN(QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME))
            FROM    [' + @databaseName + '].INFORMATION_SCHEMA.TABLES
            WHERE       TABLE_TYPE = ''BASE TABLE'' AND TABLE_CATALOG = ''' + @databaseName + '''
                AND QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME) > ''' + @TableName + '''
                AND OBJECTPROPERTY(
                        OBJECT_ID(
                            QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME)
                                ), ''IsMSShipped''
                                ) = 0'
        EXEC master..sp_executesql @SQL, N'@result nvarchar(256) out', @result out

        SET @TableName = @result
        PRINT @TableName

        WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
        BEGIN
            DECLARE @ColumnResult NVARCHAR(256)
            SET @SQL = '
                SELECT @ColumnResult = MIN(QUOTENAME(COLUMN_NAME))
                FROM    [' + @databaseName + '].INFORMATION_SCHEMA.COLUMNS
                WHERE       TABLE_SCHEMA    = PARSENAME(''[' + @databaseName + '].' + @TableName + ''', 2)
                    AND TABLE_NAME  = PARSENAME(''[' + @databaseName + '].' + @TableName + ''', 1)
                    AND DATA_TYPE IN (''char'', ''varchar'', ''nchar'', ''nvarchar'')
                    AND TABLE_CATALOG = ''' + @databaseName + '''
                    AND QUOTENAME(COLUMN_NAME) > ''' + @ColumnName + ''''
            PRINT @SQL
            EXEC master..sp_executesql @SQL, N'@ColumnResult nvarchar(256) out', @ColumnResult out
            SET @ColumnName = @ColumnResult 

            PRINT @ColumnName

            IF @ColumnName IS NOT NULL
            BEGIN
                INSERT INTO @Results
                EXEC
                (
                    'USE ' + @databaseName + '
                    SELECT ''' + @TableName + ''',''' + @ColumnName + ''',''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
                    FROM ' + @TableName + ' (NOLOCK) ' +
                    ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
                )
            END
        END
    END

    --Declaring another temporary table
    DECLARE @time_to_update TABLE(TableName nvarchar(370), RealColumnName nvarchar(370))

    INSERT INTO @time_to_update
    SELECT TableName, RealColumnName FROM @Results GROUP BY TableName, RealColumnName

    DECLARE @MyCursor CURSOR;
    BEGIN
        DECLARE @t nvarchar(370)
        DECLARE @c nvarchar(370)
        --Looping over the search results   
        SET @MyCursor = CURSOR FOR
        SELECT TableName, RealColumnName FROM @time_to_update GROUP BY TableName, RealColumnName

        --Getting my variables from the first item
        OPEN @MyCursor 
        FETCH NEXT FROM @MyCursor 
        INTO @t, @c

        WHILE @@FETCH_STATUS = 0
        BEGIN
            -- Updating the old values with the new value
            DECLARE @sqlCommand varchar(1000)
            SET @sqlCommand = '
                USE ' + @databaseName + '
                UPDATE [' + @databaseName + '].' + @t + ' SET ' + @c + ' = REPLACE(' + @c + ', ''' + @SearchStr + ''', ''' + @ReplaceStr + ''') 
                WHERE ' + @c + ' LIKE ''' + @SearchStr2 + ''''
            PRINT @sqlCommand
            BEGIN TRY
                EXEC (@sqlCommand)
            END TRY
            BEGIN CATCH
                PRINT ERROR_MESSAGE()
            END CATCH

            --Getting next row values
            FETCH NEXT FROM @MyCursor 
            INTO @t, @c 
        END;

        CLOSE @MyCursor ;
        DEALLOCATE @MyCursor;
    END;

    DELETE FROM @time_to_update
    DELETE FROM @Results

    FETCH NEXT FROM db_cursor INTO @databaseName
END   

CLOSE db_cursor   
DEALLOCATE db_cursor

注意:这并不理想,也没有经过优化

如果列是int、bit或float怎么办?空到空不起作用。这是一个很好的观点。我将更新主要帖子。出于好奇,你为什么要这样做?我们导入了大量的客户端数据进行处理。大约两周前,我们部署了一个用于导入客户机数据的更新工具,最近发现该工具已更新,现在将基于字符串的null视为null,而不是像以前那样视为空字符串。由于这一变化,我们的处理结果以最快的方式返回无效报告(在计算期间,空字符串在逻辑上不同于空字符串)(我现在也在处理它)要更正客户端数据,需要运行一个脚本,手动将所有具有空值的字符串解析为空字符串?这似乎是一次性的。通常,当我需要做类似的事情时,我会编写一个SQL查询,返回SQL语句列表作为结果。然后我只是执行脚本生成脚本,选择输出,然后执行它。例如:
select'UPDATE'+quotename(表名)+'SET'+quotename(列名)+'='',其中'+quotename(列名)+'为空;'从信息_SCHEMA.COLUMNS,其中为_NULLABLE='YES'和数据_键入('char','nchar','varchar','nvarchar')
。只需保存并重新运行输出。