Я создал хранимую процедуру для вас.
Эта процедура проверяет мету MSSQL, чтобы построить динамическую строку SQL, которая возвращает результат, содержащие имена 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
СП имеет несколько входов в качестве параметров, они описаны в следующем коде.
Отметим также, что я предоставил механизм для добавления «список игнорирования» в качестве входного сигнала:
- Это позволяет перечислить все имена столбцов, которые не должны быть включены в результатах.
- Вам не нужно добавлять столбец n, который вы используете в качестве ключа, то есть
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 может быть превышена в вашем случае. Вы бы пробовали. необходимо использовать разные типы данных, уменьшить длину имен столбцов и т. д. Или разбить его на подэтапы и объединить результаты вместе, чтобы получить нужный вам результат.
Еще одна проблема, с которой я сталкиваюсь, заключается в том, что это полный избыток для вашего конкретного сценария, где одноразовое окно сценария для запроса даст вам основу того, что вам нужно, тогда какое-то умное редактирование текста, например, Notepad ++, будет добирайся до конца ... и, следовательно, эта проблема, скорее всего, (и вполне разумно) заставит тебя так поступать! Но это хороший общий вопрос, и поэтому заслуживает ответа для всех, кто интересуется будущим ;-)
Да, я видел это, используя meta из системных таблиц, и я уверен, что кто-то более узнаваемый, чем я, будет дать ответ в этом направлении. Но в то же время попробуйте щелкнуть правой кнопкой мыши по таблице> Таблица сценариев как> Создать в> Новое окно редактора запросов? Весь список столбцов указан в скрипте. Скопируйте его и используйте поля по мере необходимости. (из http://stackoverflow.com/questions/600446/sql-server-how-do-you-return-the-column-names-from-a-table) – Sepster
Поскольку никто не активизировал мета- основанный на ответе ... Я добавил один ниже, который работал для меня на небольшом тестовом db. – Sepster