2012-10-10 48 views
13

Tengo un gran esquema, con varios cientos de tablas y varios miles de columnas. Sé que una dirección IP específica está almacenada en esta base de datos en varios lugares, pero no estoy seguro de qué tabla (s) o columna (s) está almacenada. Básicamente, estoy tratando de encontrar en todas partes que esto La dirección IP se almacena en la base de datos para que pueda actualizarla a un nuevo valor en todos esos lugares.Cómo buscar todos los campos de texto en una base de datos para alguna subcadena con T-SQL

Aquí está mi primera grieta en una declaración de T-SQL para imprimir el nombre de la tabla y columna, y el valor, para cada columna de texto en la base de datos que tiene la subcadena 10.15.13.

Ahora, esto funciona, más o menos. El problema es que cuando lo ejecuto en Management Studio, la llamada a sp_executesql realmente devolverá todos los resultados vacíos de cada consulta que no devuelve nada (es decir, la columna no tiene ningún registro con esa subcadena), y llena la ventana de resultados al máximo, y luego realmente no veo si se imprimió algo.

¿Existe una forma mejor de escribir esta consulta? ¿O puedo ejecutarlo de otra manera para que solo me muestre las Tablas y Columnas donde esta subcadena existe?

DECLARE 
    @SchemaName VARCHAR(50), 
    @TableName VARCHAR(50), 
    @ColumnName VARCHAR(50); 
BEGIN 
    DECLARE textColumns CURSOR FOR 
    SELECT s.Name, tab.Name, c.Name 
    FROM Sys.Columns c, Sys.Types t, Sys.Tables tab, Sys.Schemas s 
    WHERE s.schema_id = tab.schema_id AND tab.object_id = c.object_id AND c.user_type_id = t.user_type_id 
    AND t.Name in ('TEXT','NTEXT','VARCHAR','CHAR','NVARCHAR','NCHAR'); 

    OPEN textColumns 

    FETCH NEXT FROM textColumns 
    INTO @SchemaName, @TableName, @ColumnName 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     DECLARE @sql NVARCHAR(MAX), 
       @ParamDef NVARCHAR(MAX), 
       @result NVARCHAR(MAX);    
     SET @sql = N'SELECT ' + @ColumnName + ' FROM ' + @SchemaName + '.' + @TableName + ' WHERE ' + @ColumnName + ' LIKE ''%10.15.13%'''; 
     SET @ParamDef = N'@resultOut NVARCHAR(MAX) OUTPUT'; 

     EXEC sp_executesql @sql, @ParamDef, @resultOut = @result OUTPUT; 

     PRINT 'Column = ' + @TableName + '.' + @ColumnName + ', Value = ' + @result; 
     FETCH NEXT FROM textColumns 
     INTO @SchemaName, @TableName, @ColumnName  
    END 
    CLOSE textColumns; 
    DEALLOCATE textColumns; 
END 

me gustaría ver resultados algo como esto donde se muestra la tabla/columna que la subcadena se encuentra en, y el valor total de esa columna ...

Column = SomeTable.SomeTextColumn, Value = 'https://10.15.13.210/foo' 
Column = SomeTable.SomeOtherColumn, Value = '10.15.13.210' 

etc.

+0

Su cierre. Compare el suyo con este ejemplo: [Búsqueda y búsqueda de un valor de cadena en todas las columnas en una tabla de SQL Server] (http://www.mssqltips.com/sqlservertip/1522/searching-and-finding-a-string-value-in -all-columns-in-a-sql-server-table /) – Jeremy

+0

¡Gracias increíbles! De hecho, no utilicé esa solución del enlace porque es para buscar una sola tabla a la vez, pero tenía otro enlace a una solución completa para buscar todas las tablas en una base de datos; exactamente lo que necesitaba http://vyaskn.tripod.com/search_all_columns_in_all_tables.htm ¡Publique esto como respuesta y lo marcaré como correcto! – Jim

+0

He incluido la respuesta y el enlace al que se refería para la posteridad. ¡Gracias! – Jeremy

Respuesta

24

You'r close. Comparar la suya con este ejemplo: Searching and finding a string value in all columns in a SQL Server table

El enlace anterior es para buscar en una sola tabla, sin embargo aquí es otro enlace que incluye todas las tablas: How to search all columns of all tables in a database for a keyword?

EDIT: Por si acaso el enlace nunca va mal, aquí está la solución a partir de ese enlace ...

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 


EXEC SearchAllTables '<yourSubstringHere>' 

Nota: Como el comentario sugiere en el fragmento de código, que se puso a prueba utilizando versiones anteriores de SQL Server. Esto puede no funcionar en SQL Server 2012.

+0

-1 Recibo el siguiente error en SQL Server 2012 "Msg 217, nivel 16, estado 1, procedimiento SearchAllTables, línea 54 Máximo procedimiento almacenado, función, desencadenante o nivel de anidación de la vista excedido (límite 32)". – codemonkeh

+0

codemonkeh, asegúrese de agregar las instrucciones dropedprocessure y temp table después de cada ejecución O antes de la ejecución. – Munawar

+0

obtenga el siguiente error en SQL Server 2012 "Msg 217, nivel 16, estado 1, procedimiento SearchAllTables, línea 54 Procedimiento almacenado máximo, función, desencadenante o vista nivel de anidación excedido (límite 32). Mismo error – Jahangeer

0

probar esto no le dará el error de límite exceda 32

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



    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 

creo que sirve

3

La respuesta elegida es brillante, pero me encontré cuando utilizándolo repetidamente, los resultados fueron erróneos, así que añadí algo de limpieza para que sea re-ejecutable con resultados precisos:

IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'SearchAllTables') 
    DROP PROC SearchAllTables 
GO 

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 
    -- Slightly modified by: Natalie Ford, 6/10/15 
    -- 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 

    TRUNCATE Table #Results 

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 

    DROP TABLE #Results 
END 
Cuestiones relacionadas