2009-05-07 11 views
17

Ho un database in cui una stringa errata viene visualizzata in vari punti in tabelle diverse. Esiste una query SQL che posso utilizzare per cercare questa stringa in ogni possibile colonna varchar/text nel database?SQL: ricerca una stringa in ogni colonna varchar in un database

Stavo pensando di provare ad utilizzare le viste information_schema in qualche modo per creare query dinamiche, ma non sono sicuro che funzionerà, o se c'è un modo migliore.

Sto usando MS SQL Server se questo aiuta.

risposta

22

Utilizzando la tecnica trovata here, il seguente script genera SELECT per tutte le colonne ((n) var) nel database specificato. Copia/incolla l'output, rimuovi l'ultimo 'union' ed esegui .. Dovrai sostituire MISSPELLING QUI con la stringa che stai cercando.

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 Bella risposta breve, grazie per averci esaminato. Aspetterò e vedrò se uno dei due verrà upvotato di più prima di selezionarne uno –

+2

+1 Forse aggiungere (NOLOCK) o "impostare il livello di isolamento della transazione non eseguito" se si prevede di eseguirlo su un database di produzione – Andomar

+0

cosa aggiungerebbe NOLOCK? Penserei che sys.objects non venga aggiornato spesso. – edosoft

4

È possibile utilizzare un cursore e le viste sys.tables/sys.columns per esaminarle. Dammi un minuto, e ti darò il codice.

Aggiornamento: Qui sono:

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 

questo modo si ottiene tutto ciò che serve. Afferra le colonne che sono varchar, nvarchar, text e ntext dal tuo database, cicla le colonne e aggiorna ciascuna di esse.

Naturalmente, si potrebbe anche fare questo per creare un'istruzione SQL concatenata e fare un grande aggiornamento alla fine, ma hey, questa è la vostra preferenza.

E per la cronaca, non mi piacciono i cursori, ma dal momento che abbiamo a che fare con poche colonne e non con milioni di righe, sto bene con questo.

+0

Bella sceneggiatura. Tuttavia, mi sembra che questo aggiorni solo una singola tabella (chiamata 'MyTable')? – edosoft

+0

Giusto. Modificato per essere dinamico. – Eric

+0

+1 Cool, stavo lavorando a qualcosa che assomiglia a questo. Entrambe le buone risposte, aspetterò e vedrò se si viene svalutati più degli altri per selezionarne uno. –

1

SQL Server 2000 versione dello script precedente (da 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'); 

Speranza che aiuta

7

Uso delle interrogazioni per questo renderà questa più complessa di quanto realmente necessario. Perché non considerare alcuni degli strumenti gratuiti di ricerca SQL esistenti. ApexSQL ha ApexSQL Search, e c'è anche SQL Search da Red-Gate. Entrambe queste cose faranno il lavoro facilmente.

0

Se qualcuno dovesse richiedere qualcosa come questo per Sybase, quanto segue potrebbe aiutare.

Ho creato il seguente script, in cui il codice stampa tutti i TableNames, ColumnNames contenenti la stringa di ricerca.

Non prestazioni ottimizzate, utilizzando un cursore per scorrere le colonne DB, quindi potrebbe richiedere tempo eseguire questo su un grande DB (a seconda delle dimensioni, numero di tabelle/colli ecc)

Tuttavia, Penso che sia una buona utility per cercare una stringa in un DB.

----------------------------------------------------------------------------------------------------- 
-- 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 

Acclamazioni

0

ho incluso lo schema alla versione di 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'); 
Problemi correlati