我有一个数据库,其中拼写错误的字符串出现在不同表的不同位置。是否有一个 SQL 查询可以用来在数据库中每个可能的 varchar/text 列中搜索该字符串?
我正在考虑尝试以某种方式使用 information_schema 视图来创建动态查询,但我不确定这是否可行,或者是否有更好的方法。
如果有帮助的话,我正在使用 MS SQL Server。
使用here找到的技术,以下脚本为给定数据库中的所有 ((n)var)char 列生成 SELECT。复制/粘贴输出,删除最后一个“union”并执行。您需要将 MISSPELLING HERE 替换为您要查找的字符串。
select
'select distinct ''' + schem.name + '.' + tab.name + '.' + col.name
+ ''' from [' + schem.name + '].[' + tab.name
+ '] where [' + col.name + '] like ''%MISSPELLING HERE%'' union '
from [sys].tables tab
join [sys].schemas schem ON (tab.schema_id = schem.schema_id)
join [sys].columns col on (tab.object_id = col.object_id)
join [sys].types types on (col.system_type_id = types.system_type_id)
where tab.type_desc = 'USER_TABLE'
and types.name IN ('CHAR', 'NCHAR', 'VARCHAR', 'NVARCHAR');
为此使用查询将使事情变得比实际需要的更复杂。为什么不考虑一些现有的免费 SQL 搜索工具。 ApexSQL 有 ApexSQL Search,还有 Red-Gate 的 SQL Search。这两个都可以轻松完成工作。
您可以使用游标和 sys.tables/sys.columns 视图来浏览它们。请稍等一下,我会给你代码。
更新:在这里:
declare @col_name nvarchar(50)
declare @sql nvarchar(max)
declare @tbl_name nvarchar(50)
declare @old_str nvarchar(50)
declare @new_str nvarchar(50)
set @old_str = 'stakoverflow'
set @new_str = 'StackOverflow'
declare fetch_name cursor for
select
c.name,
t.name
from
sys.columns c
inner join sys.tables t on c.object_id = t.object_id
inner join sys.types y on c.system_type_id = y.system_type_id
where
y.name like '%varchar'
or y.name like '%text'
open fetch_name
fetch next from fetch_name into @col_name, @tbl_name
while @@fetch_status = 0
begin
set @sql = 'UPDATE ' + @tbl_name + ' SET ' +
@col_name + ' = replace(' +
@col_name + ',''' +
@old_str + ''',''' +
@new_str + ''')'
exec sp_executesql @sql
fetch next from fetch_name into @col_name
end
close fetch_name
deallocate fetch_name
这将为您提供所需的一切。它从数据库中获取 varchar、nvarchar、text 和 ntext 列,循环浏览这些列并更新每一列。
当然,您也可以这样做来创建一个串联的 SQL 语句并在最后进行一次大更新,但是,嘿,这是您的偏好。
郑重声明,我不喜欢游标,但由于我们处理的是几列而不是数百万行,所以我对此感到满意。
上面脚本的 SQL Server 2000 版本(来自 edosoft):
select
'select distinct ''[' + tab.name + ']'' as TableName, ''[' + col.name + ']'' as ColumnName'
+ ' from [' + users.name + '].[' + tab.name
+ '] where UPPER([' + col.name + ']) like ''%MISSPELLING HERE%'' union '
from sysobjects tab
join syscolumns col on (tab.id = col.id)
join systypes types on (col.xtype = types.xtype)
join sysusers users on (tab.uid = users.uid)
where tab.xtype ='U'
and types.name IN ('char', 'nchar', 'varchar', 'nvarchar');
如果有人需要 Sybase 的类似功能,以下内容可能会有所帮助。
我创建了以下脚本,其中代码打印出包含搜索字符串的所有 TableNames、ColumnNames。
未进行性能优化,使用游标循环遍历数据库列,因此在大数据库上运行它可能需要一段时间(取决于大小、表/列的数量等)
但是,我认为在数据库中搜索字符串是一个很好的实用程序。
-----------------------------------------------------------------------------------------------------
-- SYBASE - SCRIPT TO FIND STRING IN ANY COLUMN IN TABLE AND PRINT TableName/ColumnName TO RESULTS --
-----------------------------------------------------------------------------------------------------
-- tested on Sybase ASE 15.7
set nocount off
-- CREATE OBJECTS REQUIRED FOR SCRIPT
create table #SearchString (SearchString varchar(100))
go
-- SET SEARCH STRING
declare @search_string varchar(100)
set @search_string = 'SEARCH_STRING'
-- WRITE SEARCH STRING TO TEMP TABLE TO STORE IT AWAY AND BE ABLE TO READ IT IN NEXT BATCH
insert into #SearchString (SearchString)
values (@search_string)
-- GET ALL RELEVANT TABLES AND COLUMNS
insert #TabCol
select object_name(o.id) as TableName, c.name as ColumnName
from sysobjects o, syscolumns c
where o.type = 'U' -- ONLY USER TABLES
and c.usertype in (1,2,18,19,24,25,42) -- ONLY LOOK FOR CHAR, VARCHAR, ETC.
and c.id = o.id
and c.name is not null
and c.length >= datalength(@search_string)
go
-- GET TOTAL NUMBER OF RELEVANT COLUMNS
select count(*) as RelevantColumns from #TabCol
go
-- CREATE CURSOR TO LOOP THROUGH TABLES AND COLUMNS TO FIND COLUMNS CONTAINING THE SEARCH STRING
declare cur cursor for
select TableName, ColumnName from #TabCol order by TableName, ColumnName
for read only
go
-- VARIABLE DEFINITION
declare
@table_name SYSNAME,
@table_id int,
@column_name SYSNAME,
@sql_string varchar(2000),
@search_string varchar(100)
-- GET SEARCH STRING FROM TABLE
select @search_string = SearchString from #SearchString
-- CURSOR INIT
open cur
fetch cur into @table_name, @column_name
-- LOOP THROUGH TABLES AND COLUMNS SEARCHING FOR SEARCH STRING AND PRINT IF FOUND
while (@@sqlstatus != 2)
begin
set @sql_string = 'if exists (select * from ' + @table_name + ' where [' + @column_name + '] like ''%' + @search_string + '%'') print ''' + @table_name + ', ' + @column_name + ''''
execute(@sql_string)
fetch cur into @table_name, @column_name
end
go
-- CLEAN-UP
close cur
deallocate cur
drop table #SearchString
drop table #TabCol
go
干杯
我将架构包含到 edosoft 的版本中。
select
'select distinct ''[' + SCHEMA_NAME(tab.schema_id) + '].[' + tab.name + '].[' + col.name + ']'
+ ''' from [' + SCHEMA_NAME(tab.schema_id) + '].[' + tab.name
+ '] where [' + col.name + '] like ''%hsapp%'' union '
from sys.tables tab
join sys.columns col on (tab.object_id = col.object_id)
join sys.types types on (col.system_type_id = types.system_type_id)
where tab.type_desc ='USER_TABLE'
and types.name IN ('CHAR', 'NCHAR', 'VARCHAR', 'NVARCHAR');
select column_name from information_schema.columns
where table_name ='magazines' and DATA_TYPE IN ('CHAR', 'NCHAR', 'VARCHAR', 'NVARCHAR');
希望有帮助