SQL:在数据库中的每个 varchar 列中搜索字符串

问题描述 投票:0回答:7

我有一个数据库,其中拼写错误的字符串出现在不同表的不同位置。是否有一个 SQL 查询可以用来在数据库中每个可能的 varchar/text 列中搜索该字符串?

我正在考虑尝试以某种方式使用 information_schema 视图来创建动态查询,但我不确定这是否可行,或者是否有更好的方法。

如果有帮助的话,我正在使用 MS SQL Server。

sql sql-server string search
7个回答
27
投票

使用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');

7
投票

为此使用查询将使事情变得比实际需要的更复杂。为什么不考虑一些现有的免费 SQL 搜索工具。 ApexSQL 有 ApexSQL Search,还有 Red-Gate 的 SQL Search。这两个都可以轻松完成工作。


4
投票

您可以使用游标和 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 语句并在最后进行一次大更新,但是,嘿,这是您的偏好。

郑重声明,我不喜欢游标,但由于我们处理的是几列而不是数百万行,所以我对此感到满意。


1
投票

上面脚本的 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'); 

0
投票

如果有人需要 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

干杯


0
投票

我将架构包含到 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');

-1
投票
select column_name from information_schema.columns 
    where table_name ='magazines' and DATA_TYPE IN ('CHAR', 'NCHAR', 'VARCHAR', 'NVARCHAR');

希望有帮助

© www.soinside.com 2019 - 2024. All rights reserved.