Могу ли я создать динамический SQL-запрос на основе записей таблицы (имя таблицы, столбец, выборки для оператора WHERE)?

#sql #sql-server #dynamic

#sql #sql-сервер #динамический

Вопрос:

Мне нужно создать динамический запрос для импорта данных в Azure DataFactory, используя пару таблиц в качестве источника запроса (у меня уже есть конвейер, который импортирует таблицы «как есть» на основе списка исходной таблицы в SQL).

В настоящее время используется SQL Server 2014, поскольку это то, что у меня есть в моей системе разработки.

Одна таблица содержит список исходных таблиц, которые будут импортированы, в то время как вторая содержит список фильтров для каждой таблицы.

Чтобы сделать его немного более сложным, для каждого включения может быть несколько вариантов на основе столбца «Счетчик».

Исходная таблица:

 TableName
---------
Table1
Table2
Table3
 

Таблица запросов:

 TableName  ColumnName  Counter  Value
--------------------------------------
Table1,    Column1,    1,       abc
Table2,    Column1,    1,       def
Table2,    Column1,    2,       ghi
Table2,    Column1,    3,       jkl
Table3,    Column1,    1,       mno
Table3,    Column2,    1,       pqr
 

Поэтому в этом случае я хотел бы сгенерировать что-то вроде приведенного ниже в отдельную таблицу для чтения конвейером Azure:

(На основе выбора * из [исходных таблиц].[Имя таблицы] присоединяется к [QueryTable] в SourceTable.Имятаблицы = Таблица запросов.Имя таблицы)

 select * from Table1 where Column1 in ('abc')
select * from Table2 where Column1 in ('def','ghi','jkl')
select * from Table3 where Column1 in ('mno') and Column2 in ('pqr')
 

Если есть какие-либо указания, я был бы признателен за помощь.

Примечание: На данный момент мне «только» действительно нужно, чтобы первые 2 сценария 2 работали (одна / несколько записей в одном столбце), хотя сценарий 3 вполне возможен.

Заранее благодарю.

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

1. Действительно ли все ваши значения в таблице QueryTable имеют запятые ( , ) в конце их?

2. Нет. Это было мое форматирование.

Ответ №1:

Это действительно некрасиво, я не собираюсь лгать. Честно говоря, я бы предложил исправить дизайн здесь, но (говоря это) вы можете достичь того, что вам нужно. Однако это далеко не «просто» для понимания, поскольку при этом достигается результат с помощью агрегированной строки внутри агрегированной строки:

 CREATE TABLE dbo.YourTable (--SchemaName sysname DEFAULT N'dbo', --This appears to be missing
                            TableName sysname,
                            ColumnName sysname,
                            Counter int,
                            Value varchar(128)); 

INSERT INTO dbo.YourTable (TableName,ColumnName,Counter, Value)
VALUES(N'Table1',N'Column1',1,'abc'),
      (N'Table2',N'Column1',1,'def'),
      (N'Table2',N'Column1',2,'ghi'),
      (N'Table2',N'Column1',3,'jkl'),
      (N'Table3',N'Column1',1,'mno'),
      (N'Table3',N'Column2',1,'pqr');
GO

DECLARE @CRLF nchar(2) = NCHAR(13)   NCHAR(10);
DECLARE @AND nchar(7) = @CRLF   N'  AND ';

SELECT N'SELECT *'   @CRLF  
       N'FROM dbo.'   QUOTENAME(TableName)   @CRLF   
       N'WHERE '  
       STUFF((SELECT @AND   N' '   QUOTENAME(sq1.ColumnName)   N' IN ('   
                     STUFF((SELECT N','   QUOTENAME(sq2.Value,'''')
                            FROM dbo.YourTable sq2
                            WHERE sq2.TableName = YT.TableName
                              AND sq2.ColumnName = sq1.ColumnName
                            ORDER BY Counter ASC
                            FOR XML PATH(''),TYPE).value('(./text())[1]','nvarchar(MAX)'),1,1,'')  
                     N')'
              FROM dbo.YourTable sq1
              WHERE sq1.TableName = YT.TableName
              GROUP BY sq1.ColumnName
              ORDER BY sq1.ColumnName
              FOR XML PATH(''),TYPE).value('(./text())[1]','nvarchar(MAX)'),1,LEN(@AND) 1,'')   N';'
FROM dbo.YourTable YT
GROUP BY TableName;

GO
DROP TABLE dbo.YourTable;
 

db<>скрипка

Обратите внимание, что если [Value] может иметь значение длиннее 128 символов, вам нужно будет заключить значение в одинарные кавычки ( ' ) и REPLACE те, что внутри них. Кроме того, если это an nvarchar (не a varchar ), вам нужно будет префиксить эти одинарные кавычки символом nvarchar обозначения ( N ).

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

1. Спасибо, Ларну. Таблица, которая у вас есть как [YourTable], уже существует на моем сервере разработки как [QueryTable] , но мне нужно, чтобы она присоединилась к таблице [SourceTable], о которой я упоминал. Итак, в принципе, мне нужно прочитать столбец [TableName] из [SourceTable], затем проверить наличие любых соответствующих фильтров в [QueryTable] при объединении в столбце [TableName] в каждом.

2. Вы можете JOIN SourceTable , если вам «нужно» @pieyed , но, учитывая, что в нем один столбец и те же значения, что и в QueryTable , я не видел необходимости в решении.

3. Извините. Моя ошибка. Это потому, что не в каждой таблице есть фильтры.

4. Хорошо, тогда вы можете добавить JOIN или EXISTS , если необходимо, @pieyed ; это не меняет базовое решение.