2009-04-02 2 views
84

C'è un modo per cercare un valore (nel mio caso si tratta di un UID del tipo char (64)) all'interno di qualsiasi colonna di qualsiasi tabella all'interno di un database MS-SQL?Come cercare un valore in qualsiasi colonna di qualsiasi tabella all'interno di un database MS-SQL?

Sono seduto di fronte a un enorme database senza alcuna idea di come i tavoli debbano essere collegati insieme. Per scoprirlo vorrei elencare tutte le tabelle e le colonne che contengono un determinato valore in qualsiasi riga. È possibile?

Un modo potrebbe essere quello di scaricare l'intero database in un file di testo e di utilizzare qualsiasi editor di testo per cercare il valore, ma questo sarebbe puro dolore se il database fosse troppo grande.

+1

possibile duplicato di [Come trovare un valore in qualsiasi punto di un database SQL Server?] (Http://stackoverflow.com/questions/436351/how-do-i-find-a-value-anywhere-in-a -sql-server-database) – LittleBobbyTables

+0

Possibile duplicato di [Come trovare un valore in un database SQL Server?] (http://stackoverflow.com/questions/436351/how-do-i-find-a-value -questo-in-a-sql-server-database) – Omar

risposta

102

Grazie per la domanda in quanto questo è un argomento molto utile. Lo userò anche io ora per motivi che includono quello che hai proposto. :-)

Come cercare tutte le colonne di tutte le tabelle in un database per una parola chiave?

http://vyaskn.tripod.com/search_all_columns_in_all_tables.htm

Andrew

-Edit, ecco l'attuale T-SQL, in caso di collegamento rot:

CREATE PROC SearchAllTables 
(
@SearchStr nvarchar(100) 
) 
AS 
BEGIN 

-- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved. 
-- Purpose: To search all columns of all tables for a given search string 
-- Written by: Narayana Vyas Kondreddi 
-- Site: http://vyaskn.tripod.com 
-- Tested on: SQL Server 7.0 and SQL Server 2000 
-- Date modified: 28th July 2002 22:50 GMT 


CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630)) 

SET NOCOUNT ON 

DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110) 
SET @TableName = '' 
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''') 

WHILE @TableName IS NOT NULL 
BEGIN 
    SET @ColumnName = '' 
    SET @TableName = 
    (
     SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)) 
     FROM INFORMATION_SCHEMA.TABLES 
     WHERE  TABLE_TYPE = 'BASE TABLE' 
      AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName 
      AND OBJECTPROPERTY(
        OBJECT_ID(
         QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) 
         ), 'IsMSShipped' 
          ) = 0 
    ) 

    WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL) 
    BEGIN 
     SET @ColumnName = 
     (
      SELECT MIN(QUOTENAME(COLUMN_NAME)) 
      FROM INFORMATION_SCHEMA.COLUMNS 
      WHERE  TABLE_SCHEMA = PARSENAME(@TableName, 2) 
       AND TABLE_NAME = PARSENAME(@TableName, 1) 
       AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar') 
       AND QUOTENAME(COLUMN_NAME) > @ColumnName 
     ) 

     IF @ColumnName IS NOT NULL 
     BEGIN 
      INSERT INTO #Results 
      EXEC 
      (
       'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
       FROM ' + @TableName + ' (NOLOCK) ' + 
       ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2 
      ) 
     END 
    END 
END 

SELECT ColumnName, ColumnValue FROM #Results 
END 
+3

Non funziona durante la ricerca di uniqueidentifier (passato in '') – Pol

+1

Simpatico script! L'ho usato per trovare tutte le colonne che avevano un indirizzo e-mail in modo da poterlo aggiornare. Un altro buon esempio di script è http://gallery.technet.microsoft.com/scriptcenter/c0c57332-8624-48c0-b4c3-5b31fe641c58. – NateJ

+0

Potresti forse aggiungere un'indicazione di quanto tempo ci vuole per eseguire questa procedura? (un secondo, ore?) –

9

ho ampliato il codice, perché non mi ha detto il 'record number', e devo a ritrovare esso.

CREATE PROC SearchAllTables 
(
@SearchStr nvarchar(100) 
) 
AS 
BEGIN 

-- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved. 
-- Purpose: To search all columns of all tables for a given search string 
-- Written by: Narayana Vyas Kondreddi 
-- Site: http://vyaskn.tripod.com 
-- Tested on: SQL Server 7.0 and SQL Server 2000 
-- Date modified: 28th July 2002 22:50 GMT 

-- Copyright @ 2012 Gyula Kulifai. All rights reserved. 
-- Extended By: Gyula Kulifai 
-- Purpose: To put key values, to exactly determine the position of search 
-- Resources: Anatoly Lubarsky 
-- Date extension: 19th October 2012 12:24 GMT 
-- Tested on: SQL Server 10.0.5500 (SQL Server 2008 SP3) 

CREATE TABLE #Results (TableName nvarchar(370), KeyValues nvarchar(3630), ColumnName nvarchar(370), ColumnValue nvarchar(3630)) 

SET NOCOUNT ON 

DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110) 
    ,@TableShortName nvarchar(256) 
    ,@TableKeys nvarchar(512) 
    ,@SQL nvarchar(3830) 

SET @TableName = '' 
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''') 

WHILE @TableName IS NOT NULL 
BEGIN 
    SET @ColumnName = '' 

    -- Scan Tables 
    SET @TableName = 
    (
     SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)) 
     FROM INFORMATION_SCHEMA.TABLES 
     WHERE  TABLE_TYPE = 'BASE TABLE' 
      AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName 
      AND OBJECTPROPERTY(
        OBJECT_ID(
         QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) 
         ), 'IsMSShipped' 
          ) = 0 
    ) 
    Set @TableShortName=PARSENAME(@TableName, 1) 
    -- print @TableName + ';' + @TableShortName +'!' -- *** DEBUG LINE *** 

     -- LOOK Key Fields, Set Key Columns 
     SET @TableKeys='' 
     SELECT @TableKeys = @TableKeys + '''' + QUOTENAME([name]) + ': '' + CONVERT(nvarchar(250),' + [name] + ') + ''' + ',' + ''' + ' 
     FROM syscolumns 
     WHERE [id] IN (
      SELECT [id] 
      FROM sysobjects 
      WHERE [name] = @TableShortName) 
      AND colid IN (
      SELECT SIK.colid 
      FROM sysindexkeys SIK 
      JOIN sysobjects SO ON 
       SIK.[id] = SO.[id] 
      WHERE 
       SIK.indid = 1 
       AND SO.[name] = @TableShortName) 
     If @TableKeys<>'' 
      SET @TableKeys=SUBSTRING(@TableKeys,1,Len(@TableKeys)-8) 
     -- Print @TableName + ';' + @TableKeys + '!' -- *** DEBUG LINE *** 

    -- Search in Columns 
    WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL) 
    BEGIN 
     SET @ColumnName = 
     (
      SELECT MIN(QUOTENAME(COLUMN_NAME)) 
      FROM INFORMATION_SCHEMA.COLUMNS 
      WHERE  TABLE_SCHEMA = PARSENAME(@TableName, 2) 
       AND TABLE_NAME = PARSENAME(@TableName, 1) 
       AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar') 
       AND QUOTENAME(COLUMN_NAME) > @ColumnName 
     ) -- Set ColumnName 

     IF @ColumnName IS NOT NULL 
     BEGIN 
      SET @SQL=' 
       SELECT 
        ''' + @TableName + ''' 
        ,'[email protected]+' 
        ,''' + @ColumnName + ''' 
       ,LEFT(' + @ColumnName + ', 3630) 
       FROM ' + @TableName + ' (NOLOCK) ' + 
       ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2 
      --Print @SQL -- *** DEBUG LINE *** 
      INSERT INTO #Results 
       Exec (@SQL) 
     END -- IF ColumnName 
    END -- While Table and Column 
END --While Table 

SELECT TableName, KeyValues, ColumnName, ColumnValue FROM #Results 
END 
15

un ritardo, ma si spera utile ...

Ho avuto lo stesso problema qualche mese fa, ma sono riuscito a risolvere questo utilizzando strumenti di terze parti.

Tutti gli strumenti indicati di seguito sono al 100% gratuiti.

Ho utilizzato ApexSQL Search con esito positivo per la ricerca di oggetti e dati nelle tabelle. Viene fornito con diverse altre caratteristiche come diagrammi di relazione e come ...

ero un po 'lento su grandi dimensioni (40 GB TFS Database) banche dati anche se ...

enter image description here

Oltre a questo c'è anche SSMS Tools pack che le offerte molte altre funzionalità che sono abbastanza utili anche se queste non sono direttamente correlate alla ricerca di testo.

+0

Il database cercato con lo strumento Apex aveva al suo interno 580 tabelle. Quando ho eseguito la ricerca su tutti i tavoli, lo strumento direbbe che ha terminato la ricerca con successo ma non ha trovato risultati. Quando ho capito a quale tavolo si trovavano i miei dati e mi sono imbattuto solo in quel tavolo, l'avrei trovato. Anche se avessi selezionato alcuni tavoli, avrebbe funzionato, ma non con tutti i tavoli 580+. Forse ha un timeout? – skinneejoe

5

Fonte: http://fullparam.wordpress.com/2012/09/07/fck-it-i-am-going-to-search-all-tables-all-collumns/

ho una soluzione da qualche tempo fa che ho continuato a migliorare. Cerca anche all'interno di colonne XML se gli viene richiesto di farlo, o cerca valori interi se fornisce una stringa intera solo.

/* Reto Egeter, fullparam.wordpress.com */ 

DECLARE @SearchStrTableName nvarchar(255), @SearchStrColumnName nvarchar(255), @SearchStrColumnValue nvarchar(255), @SearchStrInXML bit, @FullRowResult bit, @FullRowResultRows int 
SET @SearchStrColumnValue = '%searchthis%' /* use LIKE syntax */ 
SET @FullRowResult = 1 
SET @FullRowResultRows = 3 
SET @SearchStrTableName = NULL /* NULL for all tables, uses LIKE syntax */ 
SET @SearchStrColumnName = NULL /* NULL for all columns, uses LIKE syntax */ 
SET @SearchStrInXML = 0 /* Searching XML data may be slow */ 

IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results 
CREATE TABLE #Results (TableName nvarchar(128), ColumnName nvarchar(128), ColumnValue nvarchar(max),ColumnType nvarchar(20)) 

SET NOCOUNT ON 

DECLARE @TableName nvarchar(256) = '',@ColumnName nvarchar(128),@ColumnType nvarchar(20), @QuotedSearchStrColumnValue nvarchar(110), @QuotedSearchStrColumnName nvarchar(110) 
SET @QuotedSearchStrColumnValue = QUOTENAME(@SearchStrColumnValue,'''') 
DECLARE @ColumnNameTable TABLE (COLUMN_NAME nvarchar(128),DATA_TYPE nvarchar(20)) 

WHILE @TableName IS NOT NULL 
BEGIN 
SET @TableName = 
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)) 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_TYPE = 'BASE TABLE' 
AND TABLE_NAME LIKE COALESCE(@SearchStrTableName,TABLE_NAME) 
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName 
AND OBJECTPROPERTY(OBJECT_ID(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)), 'IsMSShipped') = 0 
) 
IF @TableName IS NOT NULL 
BEGIN 
DECLARE @sql VARCHAR(MAX) 
SET @sql = 'SELECT QUOTENAME(COLUMN_NAME),DATA_TYPE 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_SCHEMA = PARSENAME(''' + @TableName + ''', 2) 
AND TABLE_NAME = PARSENAME(''' + @TableName + ''', 1) 
AND DATA_TYPE IN (' + CASE WHEN ISNUMERIC(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@SearchStrColumnValue,'%',''),'_',''),'[',''),']',''),'-','')) = 1 THEN '''tinyint'',''int'',''smallint'',''bigint'',''numeric'',''decimal'',''smallmoney'',''money'',' ELSE '' END + '''char'',''varchar'',''nchar'',''nvarchar'',''timestamp'',''uniqueidentifier''' + CASE @SearchStrInXML WHEN 1 THEN ',''xml''' ELSE '' END + ') 
AND COLUMN_NAME LIKE COALESCE(' + CASE WHEN @SearchStrColumnName IS NULL THEN 'NULL' ELSE '''' + @SearchStrColumnName + '''' END + ',COLUMN_NAME)' 
INSERT INTO @ColumnNameTable 
EXEC (@sql) 
WHILE EXISTS (SELECT TOP 1 COLUMN_NAME FROM @ColumnNameTable) 
BEGIN 
PRINT @ColumnName 
SELECT TOP 1 @ColumnName = COLUMN_NAME,@ColumnType = DATA_TYPE FROM @ColumnNameTable 
SET @sql = 'SELECT ''' + @TableName + ''',''' + @ColumnName + ''',' + CASE @ColumnType WHEN 'xml' THEN 'LEFT(CAST(' + @ColumnName + ' AS nvarchar(MAX)), 4096),''' 
WHEN 'timestamp' THEN 'master.dbo.fn_varbintohexstr('+ @ColumnName + '),''' 
ELSE 'LEFT(' + @ColumnName + ', 4096),''' END + @ColumnType + ''' 
FROM ' + @TableName + ' (NOLOCK) ' + 
' WHERE ' + CASE @ColumnType WHEN 'xml' THEN 'CAST(' + @ColumnName + ' AS nvarchar(MAX))' 
WHEN 'timestamp' THEN 'master.dbo.fn_varbintohexstr('+ @ColumnName + ')' 
ELSE @ColumnName END + ' LIKE ' + @QuotedSearchStrColumnValue 
INSERT INTO #Results 
EXEC(@sql) 
IF @@ROWCOUNT > 0 IF @FullRowResult = 1 
BEGIN 
SET @sql = 'SELECT TOP ' + CAST(@FullRowResultRows AS VARCHAR(3)) + ' ''' + @TableName + ''' AS [TableFound],''' + @ColumnName + ''' AS [ColumnFound],''FullRow>'' AS [FullRow>],*' + 
' FROM ' + @TableName + ' (NOLOCK) ' + 
' WHERE ' + CASE @ColumnType WHEN 'xml' THEN 'CAST(' + @ColumnName + ' AS nvarchar(MAX))' 
WHEN 'timestamp' THEN 'master.dbo.fn_varbintohexstr('+ @ColumnName + ')' 
ELSE @ColumnName END + ' LIKE ' + @QuotedSearchStrColumnValue 
EXEC(@sql) 
END 
DELETE FROM @ColumnNameTable WHERE COLUMN_NAME = @ColumnName 
END 
END 
END 
SET NOCOUNT OFF 

SELECT TableName, ColumnName, ColumnValue, ColumnType, COUNT(*) AS Count FROM #Results 
GROUP BY TableName, ColumnName, ColumnValue, ColumnType 
0

Dopo aver provato la soluzione di @ regeter e aver visto che non risolveva il mio problema quando stavo cercando una chiave primaria/esterna per vedere tutte le tabelle/colonne dove esiste, non ha funzionato. Dopo aver letto come ha fallito un altro che ha provato ad usare un identificatore univoco, ho apportato le modifiche ed ecco il risultato aggiornato: (funziona sia con int che con guids ... vedrai come estenderlo facilmente)

CREATE PROC [dbo].[SearchAllTables_Like] 
(
     @SearchStr nvarchar(100) 
) 
AS 
BEGIN 

-- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved. 
-- Purpose: To search all columns of all tables for a given search string 
-- Written by: Narayana Vyas Kondreddi 
-- Site: http://vyaskn.tripod.com 
-- Tested on: SQL Server 7.0 and SQL Server 2000 
-- Date modified: 28th July 2002 22:50 GMT 


CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630)) 

SET NOCOUNT ON 

DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110) 
SET @TableName = '' 
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''') 

WHILE @TableName IS NOT NULL 
BEGIN 
    SET @ColumnName = '' 
    SET @TableName = 
    (
     SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)) 
     FROM INFORMATION_SCHEMA.TABLES 
     WHERE  TABLE_TYPE = 'BASE TABLE' 
      AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName 
      AND OBJECTPROPERTY(
        OBJECT_ID(
         QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) 
         ), 'IsMSShipped' 
          ) = 0 
    ) 

    WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL) 
    BEGIN 

     SET @ColumnName = 
     (
      SELECT MIN(QUOTENAME(COLUMN_NAME)) 
      FROM INFORMATION_SCHEMA.COLUMNS 
      WHERE  TABLE_SCHEMA = PARSENAME(@TableName, 2) 
       AND TABLE_NAME = PARSENAME(@TableName, 1) 
       AND DATA_TYPE IN ('guid', 'int', 'char', 'varchar', 'nchar', 'nvarchar') 
       AND QUOTENAME(COLUMN_NAME) > @ColumnName 
     ) 

     IF @ColumnName IS NOT NULL 
     BEGIN 
      INSERT INTO #Results 
      EXEC 
      (
       'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
       FROM ' + @TableName + ' (NOLOCK) ' + 
       ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2 
      ) 
     END 
    END 
END 

SELECT ColumnName, ColumnValue FROM #Results 
END