मैंने आपके लिए एक संग्रहित प्रक्रिया बनाई है।
यह प्रक्रिया एक गतिशील SQL स्ट्रिंग बनाने के लिए MSSQL मेटा की जांच करती है जो एक परिणाम देता है जिसमें कॉलम नाम N
होता है और उनके मान V
, और संबंधित पंक्ति कुंजी K
जिससे उस मान को एक निर्दिष्ट तालिका के लिए पुनर्प्राप्त किया गया था।
जब इसे निष्पादित किया जाता है, तो परिणाम ##ColumnsByValue नामक वैश्विक अस्थायी तालिका में संग्रहीत होते हैं, जिसे बाद में सीधे पूछताछ की जा सकती है।
GetColumnsByValue
बनाएं संग्रहीत कार्यविधि, इस स्क्रिप्ट को क्रियान्वित करके:
-- =============================================
-- 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 कई इनपुट को पैरामीटर के रूप में लेता है, इन्हें निम्नलिखित कोड में समझाया गया है।
ध्यान दें कि मैंने इनपुट के रूप में "अनदेखा सूची" जोड़ने के लिए एक तंत्र प्रदान किया है:
- इससे आप उन कॉलम नामों को सूचीबद्ध कर सकते हैं जिन्हें परिणामों में शामिल नहीं किया जाना चाहिए।
- आपको उस कॉलम को जोड़ने की आवश्यकता नहीं है जिसका उपयोग आप अपनी कुंजी के रूप में कर रहे हैं, अर्थात
row_id
आपकी उदाहरण संरचना से। - आपको अन्य कॉलम शामिल करने होंगे जो
varchar
. नहीं हैं asthese एक त्रुटि का कारण बनेगा (जैसा कि 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 की लंबाई पार हो सकती है। आप जांच करेंगे। विभिन्न डेटाटाइप का उपयोग करने की आवश्यकता है, कॉलम नाम की लंबाई आदि कम करें। या इसे उप-चरणों में विभाजित करें और परिणामों को एक साथ जोड़कर परिणाम प्राप्त करें।
मेरे पास एक और चिंता यह है कि यह आपके विशेष परिदृश्य के लिए पूरी तरह से ओवरकिल है, जहां एक बार की स्क्रिप्ट-टू-क्वेरी-विंडो आपको वह आधार देगी जो आपको चाहिए, फिर कुछ चतुर टेक्स्ट संपादन जैसे नोटपैड ++ आपको सभी प्राप्त करेगा वहाँ रास्ता ... और इसलिए यह समस्या (और काफी यथोचित) आपको इसे इस तरह से करने से रोक देगी! लेकिन यह एक अच्छा सामान्य-मामला प्रश्न है, और इसलिए भविष्य में रुचि रखने वाले किसी भी व्यक्ति के उत्तर के योग्य है;-)