Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

SQL Server - Chọn các cột đáp ứng các điều kiện nhất định?

Tôi đã tạo một thủ tục được lưu trữ cho bạn.

Quy trình này kiểm tra meta MSSQL để xây dựng một chuỗi SQL động trả về kết quả chứa các tên cột N và các giá trị của chúng V và khóa hàng tương ứng K từ đó giá trị đó được truy xuất, cho một bảng cụ thể.

Khi điều này được thực thi, kết quả được lưu trữ trong một bảng tạm thời chung có tên là ## ColumnsByValue, sau đó có thể được truy vấn trực tiếp.

Tạo GetColumnsByValue thủ tục được lưu trữ, bằng cách thực thi tập lệnh này:

-- =============================================
-- 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 nhận một số đầu vào làm tham số, chúng được giải thích trong đoạn mã sau.

Cũng xin lưu ý rằng tôi đã cung cấp một cơ chế để thêm "danh sách bỏ qua" làm đầu vào:

  • Điều này cho phép bạn liệt kê bất kỳ tên cột nào không nên đưa vào kết quả.
  • Bạn KHÔNG cần thêm cột mà bạn đang sử dụng làm khóa của mình, tức là row_id từ cấu trúc mẫu của bạn.
  • Bạn PHẢI bao gồm các cột khác không phải là varchar do đó sẽ gây ra lỗi (vì SP chỉ thực hiện một varchar so sánh tất cả các cột mà nó nhìn thấy).
  • Điều này được thực hiện thông qua một bảng tạm thời mà bạn phải tạo / điền
  • Đề xuất cấu trúc bảng mẫu của bạn trong bảng chỉ chứa các cột quan tâm, vì vậy điều này có thể không áp dụng cho bạn.

Tôi đã bao gồm mã ví dụ về cách thực hiện việc này (nhưng chỉ làm điều này nếu bạn cần đến):

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

Bây giờ, để loại bỏ quy trình xây dựng bảng kết quả tạm thời của bạn, hãy sử dụng đoạn mã sau (và tất nhiên là sửa đổi nếu thích hợp).

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

Điều này để lại cho bạn ##ColumnsByValue , trên đó bạn có thể thực hiện bất kỳ tìm kiếm nào bạn cần, ví dụ:

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

Bạn cần thực hiện lại quy trình đã lưu trữ (và nếu có liên quan, hãy tạo / sửa đổi bảng danh sách bỏ qua trước nó) cho mỗi bảng bạn muốn kiểm tra.

Một mối quan tâm với cách tiếp cận này là độ dài nvarchar có thể bị vượt quá trong trường hợp của bạn. Bạn sẽ thăm dò. cần sử dụng loại dữ liệu khác nhau, giảm độ dài tên cột, v.v. Hoặc chia nhỏ thành các bước phụ và kết hợp các kết quả lại với nhau để có được tập kết quả mà bạn đang theo dõi.

Một mối quan tâm khác mà tôi có là điều này là hoàn toàn quá mức cần thiết cho tình huống cụ thể của bạn, trong đó cửa sổ script-to-query-một lần duy nhất sẽ cung cấp cho bạn cơ sở về những gì bạn cần, sau đó một số chỉnh sửa văn bản thông minh trong ví dụ Notepad ++ sẽ giúp bạn có được tất cả ở đó ... và do đó vấn đề này có thể (và khá hợp lý) khiến bạn không thể làm theo cách này! Nhưng đó là một câu hỏi hay cho trường hợp chung, và vì vậy xứng đáng có câu trả lời cho bất kỳ ai quan tâm trong tương lai;-)




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hiểu thời gian chờ của giao dịch

  2. Sử dụng IDENT_CURRENT () để trả lại giá trị nhận dạng hiện tại trên cột nhận dạng trong SQL Server

  3. Tại sao kết nối ODBC của tôi không thành công khi chạy tải SSIS trong Visual Studio nhưng không phải khi chạy cùng một gói sử dụng Tiện ích gói thực thi

  4. Bảo trì theo lịch trình của Cơ sở dữ liệu IS 24/7 trong MS SQL Server

  5. PowerShell - Liệt kê tất cả các phiên bản SQL trên hệ thống của tôi?