2009-05-07 4 views
17

У меня есть база данных, где строка с ошибками появляется в разных местах в разных таблицах. Есть ли SQL-запрос, который я могу использовать для поиска этой строки во всех возможных столбцах varchar/text в базе данных?SQL: поиск строки в каждом столбце varchar в базе данных

Я думал о попытке использовать представления information_schema каким-то образом для создания динамических запросов, но я не уверен, что это сработает, или если есть лучший способ.

Я использую MS SQL Server, если это помогает.

ответ

22

Используя найденную технику here, следующий сценарий генерирует столбцы SELECT для всех ((n) var) в данной базе данных. Скопируйте/вставьте результат, удалите последний «союз» и выполните. Вам нужно будет заменить MISSPELLING HERE строкой, которую вы ищете.

select 
'select distinct ''' + tab.name + '.' + col.name 
+ ''' from [' + tab.name 
+ '] where [' + col.name + '] like ''%MISSPELLING HERE%'' 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'); 
+0

+1 Хороший короткий ответ, спасибо, что заглянули в него. Я подожду и посмотрю, если кто-то получит преимущество, прежде чем выбрать один –

+2

+1 Может быть, добавить (NOLOCK) или «установить уровень изоляции транзакции без чтения», если вы планируете запустить это в производственной базе данных – Andomar

+0

, что бы добавить NOLOCK? Я бы подумал, что sys.objects часто не обновляется. – edosoft

4

Вы можете использовать курсор и представления sys.tables/sys.columns, чтобы пройти через них. Дайте мне минуту, и я дам вам код.

Update: Здесь вы:

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 и сделать одно большое обновление в конце, но эй, это ваши предпочтения.

И для записи я не люблю курсоры, но поскольку мы имеем дело с несколькими столбцами, а не с миллионами строк, я в порядке с этим.

+0

Отличный сценарий. Однако мне кажется, что это обновляет только одну таблицу (называемую «MyTable»)? – edosoft

+0

Совершенно верно. Отредактировал его как динамический. – Eric

+0

+1 Круто, я работал над тем, что выглядит примерно так. И хорошие ответы, я подожду и посмотрю, если кто-то получит больше, чем другой, чтобы выбрать один. –

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'); 
-1
select column_name from information_schema.columns 
    where table_name ='magazines' and DATA_TYPE IN ('CHAR', 'NCHAR', 'VARCHAR', 'NVARCHAR'); 

надеюсь, что это помогает

7

Использование запросов для этого сделает это более сложным, чем на самом деле необходимо. Почему бы не рассмотреть некоторые из бесплатных инструментов поиска SQL, которые существуют там. ApexSQL имеет ApexSQL Search, а также есть SQL Search от Red-Gate. Оба они легко справятся с этой задачей.

0

Если кто-то потребует что-то подобное для Sybase, это может помочь следующее.

Я создал следующий скрипт, в котором код печатает все имена таблиц, имена столбцов, содержащие строку поиска.

Не производительность оптимизирована, используя курсор Переберите столбцов БД, поэтому он может занять некоторое время, чтобы запустить это на большой БД (в зависимости от размера, количества таблиц/перевалы и т.д.)

Однако, Я думаю, что это хорошая утилита для поиска строки в БД.

----------------------------------------------------------------------------------------------------- 
-- 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'); 
Смежные вопросы