ストアド プロシージャを作成しました。
N
このプロシージャは、MSSQL メタを調べて、指定されたテーブルの列名とその値、およびその値が取得されV
た対応する行キーを含む結果を返す動的 SQL 文字列を作成します。K
これが実行されると、結果は ##ColumnsByValue と呼ばれるグローバル一時テーブルに格納され、直接クエリを実行できます。
GetColumnsByValue
次のスクリプトを実行して、ストアド プロシージャを作成します。
-- =============================================
-- Author: Ben Roberts (sepster@internode.on.net)
-- 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 '+@idColumn+' as K, '''+@colName+''' as N, ' +@colName+ ' 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 はいくつかの入力をパラメーターとして受け取ります。これらについては、次のコードで説明します。
入力として「無視リスト」を追加するメカニズムを提供したことにも注意してください。
- これにより、結果に含めるべきではない列名を一覧表示できます。
- キーとして使用している列を追加する必要はありません。つまり、
row_id
例の構造からのものです。
- そうでない他の列を含める必要が
varchar
あります。これらはエラーの原因となります (SP は参照するvarchar
すべての列を比較するだけなので)。
- これは、作成/入力する必要がある一時テーブルを介して行われます
- テーブル構造の例は、テーブルに目的の列のみが含まれていることを示唆しているため、これは当てはまらない場合があります。
これを行う方法のサンプル コードを含めました (ただし、これは必要な場合にのみ行ってください)。
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');
ここで、結果の一時テーブルを作成するプロシージャを開始するには、次のコードを使用します (もちろん、必要に応じて変更します)。
-- 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
これにより##ColumnsByValue
、必要な検索を実行できる が残ります。たとえば、次のようになります。
select * from ##ColumnsByValue WHERE v = 'luxury' and k = 5 --some_row_id
調べたいテーブルごとに、ストアド プロシージャを再実行する必要があります (関連する場合は、その前に無視リスト テーブルを作成/変更します)。
このアプローチに関する懸念は、あなたのケースでは nvarchar の長さが超過する可能性があることです。あなたはおそらくでしょう。異なるデータ型を使用したり、列名の長さを短くしたりする必要があります。または、サブステップに分割し、結果を結合して、目的の結果セットを取得します。
私が持っているもう1つの懸念は、これが特定のシナリオでは完全にやり過ぎであることです.1回限りのスクリプトからクエリウィンドウへのスクリプトが必要なものの基礎を提供し、たとえばNotepad ++での巧妙なテキスト編集がすべてを取得します.そこまで...したがって、この問題はおそらく(そしてかなり合理的に)この方法で行うことを先延ばしにします!しかし、これは一般的な質問であり、将来に関心のある人にとっては回答に値するものです ;-)