Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

SQL Server — Wybierz kolumny, które spełniają określone warunki?

Stworzyłem dla Ciebie procedurę składowaną.

Ta procedura sprawdza meta MSSQL w celu zbudowania dynamicznego ciągu SQL, który zwraca wynik zawierający nazwy kolumn N i ich wartości V i odpowiedni klawisz wiersza K z którego ta wartość została pobrana, dla określonej tabeli.

Kiedy to jest wykonywane, wyniki są przechowywane w globalnej tabeli tymczasowej o nazwie ##ColumnsByValue, do której można następnie bezpośrednio zapytać.

Utwórz GetColumnsByValue procedura składowana, wykonując ten skrypt:

-- =============================================
-- Author:      Ben Roberts ([email protected])
-- Create date: 22 Mar 2013
-- Description: Returns the names of columns that contain the specified value, for a given row
-- =============================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID ( 'dbo.GetColumnsByValue', 'P' ) IS NOT NULL 
    DROP PROCEDURE dbo.GetColumnsByValue;
GO
CREATE PROCEDURE dbo.GetColumnsByValue
    -- Add the parameters for the stored procedure here
    @idColumn sysname,
    @valueToFind nvarchar(255), 
    @dbName sysname,
    @tableName sysname,
    @schemaName sysname,
    @debugMode int = 0

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @SQL nvarchar(max);
    DECLARE @SQLUnion nvarchar(max);
    DECLARE @colName sysname;
    DECLARE @dbContext nvarchar(256);
    DECLARE @Union nvarchar(10);

    SELECT @dbContext = @dbName + '.' + @schemaName + '.sp_executeSQL';
    SELECT @SQLUnion = '';
    SELECT @Union = '';

    IF OBJECT_ID ( 'tempdb..##GetColumnsByValueIgnoreList') IS NULL -- no columns to ingore have been specified, need to create an empty list.
    BEGIN
        CREATE TABLE ##GetColumnsByValueIgnoreList (column_name nvarchar(255));
    END

    DECLARE DBcursor CURSOR FOR
        SELECT 
            COLUMN_NAME
        FROM 
            INFORMATION_SCHEMA.COLUMNS
        WHERE 
            TABLE_NAME = @tableName 
            AND 
            TABLE_SCHEMA = @schemaName;

    OPEN DBcursor; 
        FETCH DBcursor INTO @colName;
        WHILE (@@FETCH_STATUS = 0)
        BEGIN
            IF (
                @colName != @idColumn
                AND
                @colName NOT IN (SELECT column_name FROM ##GetColumnsByValueIgnoreList)
            )
            BEGIN
                SELECT @SQL = 'SELECT '[email protected]+' as K, '''[email protected]+''' as N, ' [email protected]+ ' as V FROM ' + @dbName + '.' + @schemaName + '.' + @tableName;
                --PRINT @SQL;
                SELECT @SQLUnion = @SQL + @Union + @SQLUnion;
                SELECT @Union = ' UNION ';
            END
            FETCH  DBcursor INTO @colName;
        END; -- while
    CLOSE DBcursor; DEALLOCATE DBcursor;

    IF (@debugMode != 0)
        BEGIN
            PRINT @SQLUnion;
            PRINT @dbContext;
        END
    ELSE
        BEGIN
            -- Delete the temp table if it has already been created.
            IF OBJECT_ID ('tempdb..##ColumnsByValue') IS NOT NULL 
                BEGIN 
                    DROP TABLE ##ColumnsByValue 
                END

            -- Create a new temp table
            CREATE TABLE ##ColumnsByValue (
                K nvarchar(255), -- Key
                N nvarchar(255), -- Column Name
                V nvarchar(255)  -- Column Value
            )

            -- Populate it with the results from our dynamically generated SQL.
            INSERT INTO ##ColumnsByValue EXEC @dbContext @SQLUnion;
        END
END
GO

SP przyjmuje kilka danych wejściowych jako parametry, są one wyjaśnione w poniższym kodzie.

Zauważ też, że udostępniłem mechanizm dodawania „listy ignorowanych” jako danych wejściowych:

  • Dzięki temu możesz wyświetlić listę nazw kolumn, które nie powinny być uwzględnione w wynikach.
  • NIE musisz dodawać kolumny, której używasz jako klucza, tj. row_id z przykładowej struktury.
  • MUSISZ uwzględnić inne kolumny, które nie są varchar asthese spowoduje błąd (ponieważ SP po prostu robi varchar porównanie we wszystkich kolumnach, na które patrzy).
  • Odbywa się to za pomocą tabeli tymczasowej, którą musisz utworzyć/wypełnić
  • Przykładowa struktura tabeli sugeruje, że tabela zawiera tylko interesujące kolumny, więc może to nie dotyczyć Ciebie.

Dołączyłem przykładowy kod, jak to zrobić (ale rób to tylko wtedy, gdy potrzebujesz do):

IF OBJECT_ID ( 'tempdb..##GetColumnsByValueIgnoreList') IS NOT NULL
    BEGIN
        DROP TABLE ##GetColumnsByValueIgnoreList;
    END
CREATE TABLE ##GetColumnsByValueIgnoreList (column_name nvarchar(255));
INSERT INTO ##GetColumnsByValueIgnoreList VALUES ('a_column');
INSERT INTO ##GetColumnsByValueIgnoreList VALUES ('another_column');
INSERT INTO ##GetColumnsByValueIgnoreList VALUES ('yet_another_column');

Teraz, aby uruchomić procedurę, która buduje twoją tymczasową tabelę wyników, użyj poniższego kodu (i oczywiście odpowiednio zmodyfikuj).

-- Build the ##ColumnsByValue table
EXEC dbo.GetColumnsByValue
    @idColumn = 'row_id',   -- The name of the column that contains your row ID (eg probably your PK column)
    @dbName = 'your_db_name',
    @tableName = 'your_table_name',
    @schemaName = 'dbo',
    @debugMode = 0          -- Set this to 1 if you just want a print out of the SQL used to build the temp table, to 0 if you want the temp table populated

Pozostaje Ci ##ColumnsByValue , na którym możesz przeprowadzić dowolne wyszukiwanie, np.:

select * from ##ColumnsByValue WHERE v = 'luxury' and k = 5 --some_row_id

Musisz ponownie wykonać procedurę składowaną (i jeśli to konieczne, utworzyć/zmodyfikować przed nią tabelę listy ignorowanych) dla każdej tabeli, którą chcesz sprawdzić.

Problemem związanym z tym podejściem jest to, że w twoim przypadku może zostać przekroczona długość nvarchar. Zapewne. musisz użyć różnych typów danych, skrócić długości nazw kolumn itp. Lub podziel je na podetapy i połącz wyniki, aby uzyskać zestaw wyników, którego szukasz.

Kolejną obawą, jaką mam, jest to, że jest to kompletna przesada w przypadku twojego konkretnego scenariusza, w którym jednorazowy skrypt do zapytania da ci podstawę tego, czego potrzebujesz, a następnie sprytna edycja tekstu w np. Notepad ++ zapewni ci wszystkie droga tam ... i stąd ten problem prawdopodobnie (i całkiem rozsądnie) zniechęci cię do robienia tego w ten sposób! Ale jest to dobre pytanie ogólne i dlatego zasługuje na odpowiedź dla każdego zainteresowanego przyszłością;-)




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. stracony podział linii na serwerze sql

  2. Muszę zaimportować dane z Excela do SQL Server za pomocą VBA

  3. Jak działa IIF() w SQL Server

  4. Co spowodowałoby podsłuchiwanie parametrów na jednym komputerze, a nie na drugim?

  5. Jak uzyskać listę tabel w bazie danych przy użyciu MS SQL 2008?