2011-06-30 14 views
8

He buscado una respuesta a esto, pero todo lo que puedo encontrar es que la gente pregunte cómo buscar todas las columnas de TODAS las tablas en una base de datos para un valor. Solo quiero buscar todas las columnas para una tabla específica. El código que la gente ha ideado para la pregunta de todas las tablas es complicado y difícil para mí para descubrir exactamente dónde está buscando una tabla específica. alguien me puede ayudar? GraciasBuscar todas las columnas de una tabla para un valor?

+1

Necesitamos saber cuáles son los tipos de datos son, y por qué su estructura incluso permitiría esto? ¿Son todos sus campos 'varchar' o algo así? – JNK

+1

¿Qué versión de SQL Server por favor? –

Respuesta

0

que modificó este procedimiento almacenado para tomar un nombre de tabla como el segundo parámetro y sólo una búsqueda en esa tabla para los datos:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SearchOneTable]') AND type in (N'P', N'PC')) 
DROP PROCEDURE [dbo].[SearchOneTable] 
GO 

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE PROC [dbo].[SearchOneTable] 
(
    @SearchStr nvarchar(100) = 'A', 
    @TableName nvarchar(256) = 'dbo.Alerts' 
) 
AS 
BEGIN 

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

    --SET NOCOUNT ON 

    DECLARE @ColumnName nvarchar(128), @SearchStr2 nvarchar(110) 
    SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''') 
    --SET @SearchStr2 = QUOTENAME(@SearchStr, '''') --exact match 
    SET @ColumnName = ' ' 


     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 
    SELECT ColumnName, ColumnValue FROM #Results 
END 


GO 
+0

Esto no busca tipos de datos 'text' o' xml', y con un requisito como este, ¿quién sabe qué pueden tener en sus tablas? – JNK

+0

La operación mencionó que había encontrado procs almacenados que buscaban en toda la base de datos pero que tenían problemas para entenderlos. Si esto es solo para uso de un desarrollador, no veo el problema de modificar una de las soluciones dinámicas para una sola tabla según lo solicitado. – Decker97

+0

Yo, simplemente, simplemente señalándolo. Tenga en cuenta que no le devolví :) – JNK

2

no tengo ni idea de los tipos de columna o valores de datos que está buscando para, pero supongo que estás tratando de buscar una subcadena entre varias columnas de texto.

Este es un trabajo para Full-Text Search.

No pierda el tiempo con LIKE '%' + @SearchStr + '%'. Tienes que escribir un montón de código complicado para soportarlo, y esa solución no funcionará bien de todos modos.

+0

La configuración de la búsqueda de texto completo puede ser excesiva si solo se trata de una tarea interna o de mantenimiento y no una función primaria (o usuario final en absoluto) de la aplicación. –

+0

Aún es más fácil que codificar procedimientos almacenados largos y complejos para ejecutar SQL queris dinámico, como en la respuesta de @Decker97. –

+0

Eso depende de la versión de SQL Server y si se instaló Full-Text cuando se instaló SQL Server. No lo he intentado, pero he leído historias de horror sobre cómo calzarlo después del hecho. Aún así, ¿va a completar un índice de texto completo para cada columna de cadena en cada tabla? Incluso si esta es una tarea interna? Es un costoso costo/beneficio en mi humilde opinión. –

1

Aquí hay una solución que, al igual que el enfoque de @ Decker97, determina a partir de los metadatos qué columnas son aptas para la búsqueda de texto. Asume 2005+ para el uso de XML PATH, así como sys.columns, sys.tables, etc. Admite TEXT/NTEXT/CHAR/NCHAR/VARCHAR/NVARCHAR, e incluso coloca el N principal en la cadena de búsqueda, según corresponda. No es compatible con columnas XML. Lo que hace ligeramente diferente es que devuelve un único conjunto de resultados para cada tabla, no para cada columna, por lo que solo se obtiene una fila por cada fila de la tabla real, incluso si coinciden varias columnas. Si el objetivo es entender cómo funciona en lugar de simplemente tener una solución, probablemente tome un poco más de esto ... tal vez debería escribir sobre este problema (probablemente no sea flojo y de hecho construya las listas de columnas en lugar de solo usando SELECT *).

DECLARE @SearchTerm NVARCHAR(32) = 'foo'; 

DECLARE @TableName NVARCHAR(128) = NULL; 

SET NOCOUNT ON; 

DECLARE @s NVARCHAR(MAX) = ''; 

WITH [tables] AS 
(
    SELECT [object_id] 
     FROM sys.tables AS t 
     WHERE (name = @TableName OR @TableName IS NULL) 
     AND EXISTS 
     (
      SELECT 1 
       FROM sys.columns 
       WHERE [object_id] = t.[object_id] 
       AND system_type_id IN (35,99,167,175,231,239) 
     ) 
) 
SELECT @s = @s + 'SELECT ''' 
    + REPLACE(QUOTENAME(OBJECT_SCHEMA_NAME([object_id])),'''','''''') 
    + '.' + REPLACE(QUOTENAME(OBJECT_NAME([object_id])), '''','''''') 
    + ''',* FROM ' + QUOTENAME(OBJECT_SCHEMA_NAME([object_id])) 
    + '.' + QUOTENAME(OBJECT_NAME([object_id])) + ' WHERE ' + 
    (
     SELECT QUOTENAME(name) + ' LIKE ' + CASE 
      WHEN system_type_id IN (99,231,239) 
      THEN 'N' ELSE '' END 
      + '''%' + @SearchTerm + '%'' OR ' 
     FROM sys.columns 
     WHERE [object_id] = [tables].[object_id] 
     AND system_type_id IN (35,99,167,175,231,239) 
     ORDER BY name 
     FOR XML PATH(''), TYPE 
).value('.[1]', 'nvarchar(max)') + CHAR(13) + CHAR(10) 
FROM [tables]; 

SELECT @s = REPLACE(@s,' OR ' + CHAR(13),';' + CHAR(13)); 

/* 
    make sure you use Results to Text and adjust Tools/Options/
    Query Results/SQL Server/Results to Text/Maximum number 
    of characters if you want a chance at trusting this output 
    (the number of tables/columns will certainly have the ability 
    to exceed the output limitation) 
*/ 

SELECT @s; 
-- EXEC sp_executeSQL @s; 
2

En un similar question I mencionado SQL Workbench/J.

El comando que busca en la base de datos también se puede limitar a una sola tabla. Entonces, incluso si esa pregunta era específica de PostgreSQL, la herramienta funciona para SQL Server hasta donde yo sé.

0

Esto suena como que solo quiere saber en qué tabla y columna se almacenan algunos datos, no que desea saberlos durante la ejecución de su código, o cambiarlos. También tuve este problema y esto lo resolvió:

Descargue su base de datos en formato SQL (usando phpmyadmin, por ejemplo), ábralo con un editor de texto y busque las instancias que desee.

+0

Si el tamaño de la base de datos es GB, sería muy difícil abrir y buscar dicho archivo. –

3

Simplemente use alguna herramienta de terceros. Hay varios que son 100% gratis y no puedes equivocarte con ninguno de estos porque te ahorrarán un montón de tiempo.

ApexSQL Search (búsquedas tanto de esquema y datos), SSMS Toolpack (búsquedas esquema y los datos pero no libre para SQL Server 2012), SQL Search (búsquedas sólo datos).

Francamente, realmente no entiendo por qué incluso los DBA muy experimentados se molestan en escribir guiones para esto si pueden usar alguna herramienta gratis que hará el trabajo.

0

Cutesie poco trabajo en torno a que implica un poco más escribir o Excel que corta con tijeras/el formato:

Invertir el operador IN en una cláusula WHERE como VALUE IN <fields> (en contraposición al caso de uso más común de FIELD IN <values>).

SELECT col_1, col_2, ... , col_n 
FROM <table> 
WHERE CAST(<value> AS varchar(max)) IN 
    (
    CAST(col_1 AS varchar(max)), 
    CAST(col_2 AS varchar(max)), 
    ..., 
    CAST(col_n AS varchar(max)) 
    ) 

Desde varchar es un tipo de datos bastante maleable, esto se convierte en prácticamente toda prueba (se puede tirar ISNULL/NULLIF a modificar según sea necesario), y dependiendo del caso de uso, probablemente, se puede utilizar en más de un valor de búsqueda.

0

Me he encontrado con este problema, normalmente después de cargar datos de un archivo CSV donde tuve que modificar las comas ',' en los campos de texto para que los datos se carguen correctamente & una vez en SQL Server, se necesita cambiar el el carácter modificado vuelve a una coma & es útil para poder buscar toda la tabla. Greg Robidoux en mssqltips ha publicado un procedimiento almacenado que hace justamente esto, busca en las columnas de una tabla específica un valor de cadena específico. Lo puede encontrar junto con un procedimiento almacenado que no utiliza el cursor & más detalles aquí:

https://www.mssqltips.com/sqlservertip/1522/searching-and-finding-a-string-value-in-all-columns-in-a-sql-server-table/

He publicado el sproc originales a continuación:

USE master 
GO 

CREATE PROCEDURE dbo.sp_FindStringInTable @stringToFind VARCHAR(100), @schema sysname, @table sysname 
AS 

DECLARE @sqlCommand VARCHAR(8000) 
DECLARE @where VARCHAR(8000) 
DECLARE @columnName sysname 
DECLARE @cursor VARCHAR(8000) 

BEGIN TRY 
    SET @sqlCommand = 'SELECT * FROM [' + @schema + '].[' + @table + '] WHERE' 
    SET @where = '' 

    SET @cursor = 'DECLARE col_cursor CURSOR FOR SELECT COLUMN_NAME 
    FROM ' + DB_NAME() + '.INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_SCHEMA = ''' + @schema + ''' 
    AND TABLE_NAME = ''' + @table + ''' 
    AND DATA_TYPE IN (''char'',''nchar'',''ntext'',''nvarchar'',''text'',''varchar'')' 

    EXEC (@cursor) 

    OPEN col_cursor  
    FETCH NEXT FROM col_cursor INTO @columnName  

    WHILE @@FETCH_STATUS = 0  
    BEGIN  
     IF @where <> '' 
      SET @where = @where + ' OR' 

     SET @where = @where + ' [' + @columnName + '] LIKE ''' + @stringToFind + '''' 
     FETCH NEXT FROM col_cursor INTO @columnName  
    END  

    CLOSE col_cursor  
    DEALLOCATE col_cursor 

    SET @sqlCommand = @sqlCommand + @where 
    PRINT @sqlCommand 
    EXEC (@sqlCommand) 
END TRY 
BEGIN CATCH 
    PRINT 'There was an error. Check to make sure object exists.' 
    PRINT error_message() 

    IF CURSOR_STATUS('variable', 'col_cursor') <> -3 
    BEGIN 
     CLOSE col_cursor  
     DEALLOCATE col_cursor 
    END 
END CATCH 
+1

Intente agregar más detalles a su respuesta en el enlace que proporcionó. En el caso de que el enlace cambie alguna vez o no esté disponible, su respuesta no será útil. – dckuehn

+0

@dckuehn gracias por los comentarios, he agregado el SPROC – Sihusir

Cuestiones relacionadas