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
- 替换为:
空字符串
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')
。只需保存并重新运行输出。