#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