Как выбрать значения строк в качестве имен столбцов другой таблицы?

#sql #sql-server

#sql #sql-сервер

Вопрос:

итак, у меня есть запрос, который при запуске выдает мне имена столбцов в другой таблице. Таблица, к которой я обращаюсь, является пользовательской конфигурацией столбцов в нашем программном обеспечении. это может измениться с отображения 3 до 20 столбцов. В таблице хранятся имена фактических столбцов в базе данных. затем я хочу иметь возможность брать данные из этой таблицы и запрашивать другую таблицу только на основе тех имен столбцов, которые были возвращены. я в тупике, как это сделать, чтобы при выполнении запроса для разных пользователей запрос перехватывал только столбцы, которые они сохранили в своей конфигурации.

мой первый запрос:

 SELECT field_name
FROM list_config
WHERE list_config.config_name = 'username'
  AND list_config.visible = 'Y';
  

возвращает имена столбцов:

 field_name (header)

create_date       
customer_id       
id                
update_date       
update_user_id    
short_description    
ops_note          
create_user_id    
resp_user_id      
activity_status_id
  

затем я хочу запросить таблицу work_order только для этих столбцов, созданных первым запросом.

я все еще новичок в SQL, любая помощь была бы замечательной. я пытался возиться с переменными и некоторыми процедурами, но на данный момент я просто недостаточно знаю.

Комментарии:

1. Уверен, что вы ищете динамический SQL.

2. @Sami Да, это звучит правильно.

3. @Sami это может быть простое «in» или даже объединение, но нам нужно иметь больше информации о таблице work_order

4. @DanielE. что еще вам нужно?

Ответ №1:

Это непроверено, однако это должно дать вам то, что вам нужно:

 DECLARE @SQL nvarchar(MAX);

SET @SQL = N'SELECT '  
           STUFF((SELECT N','   NCHAR(13)   NCHAR(10)  
                         N'       '   QUOTENAME(field_name)
                  FROM list_config
                  WHERE list_config.config_name = 'username'
                    AND list_config.visible = 'Y'
                  --ORDER BY ??? --without an ORDER BY the order of the columns will be random/unpredictable
                  FOR XML PATH(N''),TYPE).value(N'.','nvarchar(MAX)'),1,10,N'')   NCHAR(13)   NCHAR(10)  
           N'FROM work_order;';
--PRINT @SQL; --your debugging best friend
EXEC sp_executesql @SQL;
  

Если вам нужно передать параметры, то убедитесь, что вы параметризовали свой sp_execute оператор; не вводите значения параметров в свой динамический оператор.

Если вы хотите проверить, что имена столбцов являются реальными именами столбцов, вы можете использовать EXISTS :

 DECLARE @SQL nvarchar(MAX);

SET @SQL = N'SELECT '  
           STUFF((SELECT ','   NCHAR(13)   NCHAR(10)  
                         N'       '   QUOTENAME(lc.field_name)
                  FROM list_config lc
                  WHERE lc.config_name = 'username'
                    AND lc.visible = 'Y'
                    AND EXISTS (SELECT 1
                                FROM INFORMATION_SCHEMA.COLUMNS C
                                WHERE C.COLUMN_NAME = lc.field_name
                                  AND C.TABLE_NAME = N'Work_order')
                  --ORDER BY ???
                  FOR XML PATH(N''),TYPE).value(N'.','nvarchar(MAX)'),1,10,N'')   NCHAR(13)   NCHAR(10)  
           N'FROM work_order;';
--PRINT @SQL; --your debugging best friend
EXEC sp_executesql @SQL;
  

Как работает этот ответ, так это то, что он создает список всех столбцов в формате с разделителями. Следовательно, настоящая «магия» находится в FOR XML PATH , поэтому мы собираемся начать с подзапроса.

FOR XML PATH в основном выполняет то, что указано в tin, он преобразует результирующий набор в XML. Мы можем использовать эту функциональность для объединения всех значений из результирующего набора из таблицы work_order . Я добавляю к каждому значению префикс (это важно) с N',' NCHAR(13) NCHAR(10) N' ' . Это может показаться немного странным (некоторые используют только ',' ), поэтому я объясню. запятая — самый простой вариант, между именами каждого столбца нам нужна одна из них. NCHAR(13) NCHAR(10) — это возврат каретки (символ Юникода 13) и разрыв строки (символ Юникода 10). Тогда у нас остается немного пробелов. Я делаю это исключительно для форматирования, так как хорошо отформатированный динамический SQL намного легче устранить неполадки, чем плохо отформатированный.

Тогда мы имеем STUFF . STUFF Используется для удаления первого префикса для каждого значения field_name (вот почему я сказал, что важно, чтобы это был префикс). STUFF вторым параметром ( 1 в данном случае) является позиция, с которой следует начать замену, а 3-й — количество символов для замены (итак, символы 1-10). Этот последний параметр — это то, чем заменить эти символы ( '' ). Таким образом, первый префикс ( N',' NCHAR(13) NCHAR(10) N' ' ) заменяется на '' .

Комментарии:

1. Понимание является важной частью получения ответов по Stack Overflow, @Kyle. Какой бит вы не понимаете, и я буду рад объяснить.

2. ну, я еще не видел STUFF или NCHAR и ключевые слова XML

3. Хорошо, я добавлю немного больше деталей для вас в ответе @Kyle и дам вам знать, когда закончу.

4. Надеюсь, это даст вам немного объяснений здесь @Kyle

5. могу я еще немного позаимствовать ваши мысли? у меня есть другой вопрос, связанный с этой темой, но он включает в себя другой, более сложный запрос

Ответ №2:

Это другой подход (он не тестировался)

 declare @query nvarchar(1000) = ''

select @query = @query ',[' field_name ']'
FROM list_config
WHERE list_config.config_name = 'username'
  AND list_config.visible = 'Y';

 set @query =substring(@query,2,len(@query))

 set @query ='select ' @query   ' from work_order'

exec (@query)
  

вы можете создать любой скрипт с помощью этого

Комментарии:

1. Учитывая, что это поступает из списка пользователей ( list_config ) Я бы не стал доверять этим ценностям. Они должны, по крайней мере, заключаться в кавычки.

2. [' field_name ']' значение не заключено в кавычки. Что бы произошло, если бы значение field_name было id] FROM Work_order; CREATE LOGIN SysAd WITH PASSWORD = '1';-- ?

3. на самом деле я пробовал что-то очень, очень похожее, но мой синтаксис был неправильным, и я не смог разобраться

4. Привет, @ Kyle, не мог бы ты отправить ошибку? Мой подход более прост, сценарий Lamu является более полным способом

5. я удалил свою собственную попытку, но для вашей подстроки требуется как минимум 3 аргумента в соответствии с SSMS