Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

SQL Server - Pilih kolom yang memenuhi kondisi tertentu?

Saya telah membuat prosedur tersimpan untuk Anda.

Prosedur ini memeriksa meta MSSQL untuk membangun string SQL dinamis yang mengembalikan hasil yang berisi nama kolom N dan nilainya V , dan kunci baris yang sesuai K dari mana nilai itu diambil, untuk tabel tertentu.

Ketika ini dijalankan, hasilnya disimpan dalam tabel sementara global yang disebut ##ColumnsByValue, yang kemudian dapat ditanyakan secara langsung.

Buat GetColumnsByValue prosedur tersimpan, dengan menjalankan skrip ini:

-- =============================================
-- 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 mengambil beberapa input sebagai parameter, ini dijelaskan dalam kode berikut.

Perhatikan juga saya telah menyediakan mekanisme untuk menambahkan "daftar abaikan" sebagai input:

  • Ini memungkinkan Anda untuk membuat daftar nama kolom apa pun yang tidak boleh disertakan dalam hasil.
  • Anda TIDAK perlu menambahkan kolom yang Anda gunakan sebagai kunci Anda, yaitu row_id dari contoh struktur Anda.
  • Anda HARUS menyertakan kolom lain yang bukan varchar karena ini akan menyebabkan kesalahan (karena SP hanya melakukan varchar perbandingan pada semua kolom yang dilihatnya).
  • Ini dilakukan melalui tabel temp yang harus Anda buat/isi
  • Contoh struktur tabel Anda menunjukkan bahwa tabel hanya berisi kolom yang diinginkan, jadi ini mungkin tidak berlaku untuk Anda.

Saya telah menyertakan kode contoh untuk cara melakukannya (tetapi lakukan ini hanya jika Anda membutuhkan ke):

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');

Sekarang, untuk menjalankan prosedur yang membuat tabel hasil temp Anda, gunakan kode berikut (dan modifikasi seperlunya, tentu saja).

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

Ini memberi Anda ##ColumnsByValue , di mana Anda dapat melakukan pencarian apa pun yang Anda butuhkan, misalnya:

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

Anda perlu menjalankan kembali prosedur tersimpan (dan jika relevan, buat/ubah tabel daftar abaikan sebelumnya) untuk setiap tabel yang ingin Anda periksa.

Kekhawatiran dengan pendekatan ini adalah panjang nvarchar mungkin terlampaui dalam kasus Anda. Anda akan mencoba. perlu menggunakan tipe data yang berbeda, kurangi panjang nama kolom, dll. Atau bagi menjadi beberapa sub-langkah dan gabungkan hasilnya untuk mendapatkan kumpulan hasil yang Anda cari.

Kekhawatiran lain yang saya miliki adalah bahwa ini benar-benar berlebihan untuk skenario khusus Anda, di mana jendela skrip-ke-permintaan satu kali akan memberi Anda dasar dari apa yang Anda butuhkan, kemudian beberapa pengeditan teks pintar di misalnya Notepad ++ akan memberi Anda semua jalan ke sana ... dan karenanya masalah ini kemungkinan akan (dan cukup masuk akal) membuat Anda tidak melakukannya dengan cara ini! Tapi ini adalah pertanyaan kasus umum yang bagus, dan pantas mendapat jawaban untuk siapa pun yang tertarik di masa depan;-)




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server ODBC Driver tidak memunculkan kesalahan

  2. Secara Otomatis Jatuhkan dan Buat kembali indeks saat ini

  3. Bagaimana saya bisa membuat DSN secara terprogram?

  4. MS SQL Server dan JDBC:koneksi tertutup

  5. Koreksi Rencana Otomatis di SQL Server