Похоже, что #temptables, созданные с использованием динамического SQL с помощью строкового метода EXECUTE, имеют другую область видимости и на них не могут ссылаться "фиксированные" SQL в той же хранимой процедуре.
Однако я могу сослаться на временную таблицу, созданную оператором динамического SQL, в динамическом SQL подпоследовательности, но кажется, что хранимая процедура не возвращает результат запроса вызывающему клиенту, если SQL не исправлен.
Простой сценарий на 2 стола:
У меня есть 2 таблицы. Давайте назовем их Заказами и Предметами. У Order есть Первичный ключ OrderId, а у Items - Первичный ключ ItemId. Items.OrderId - это внешний ключ для идентификации родительского ордера. Заказ может содержать от 1 до n пунктов.
Я хочу иметь возможность предоставить пользователю очень гибкий интерфейс типа «построитель запросов», чтобы пользователь мог выбирать, какие элементы он хочет видеть. Критерии фильтрации могут основываться на полях из таблицы «Предметы» и / или из родительской таблицы «Заказ». Если Предмет удовлетворяет условию фильтра, включающему и условие родительского Заказа, если таковой существует, Предмет должен быть возвращен в запросе, а также в родительском Заказе.
Обычно, я полагаю, большинство людей создают соединение между таблицей Item и родительскими таблицами Order. Я хотел бы выполнить 2 отдельных запроса вместо этого. Один для возврата всех соответствующих Предметов, а другой для возврата всех отдельных родительских Приказов. Причина в два раза, и вы можете или не можете согласиться.
Первая причина заключается в том, что мне нужно запросить все столбцы в родительской таблице Order, и если бы я сделал один запрос, чтобы соединить таблицу Orders с таблицей Items, я бы повторил информацию о Order несколько раз. Поскольку в каждом заказе обычно содержится большое количество элементов, я бы хотел этого избежать, поскольку это привело бы к тому, что гораздо больше данных передавалось бы толстому клиенту. Вместо этого, как уже упоминалось, я хотел бы вернуть две таблицы по отдельности в наборе данных и использовать эти две таблицы для заполнения пользовательских клиентских объектов Order и дочерних элементов. (Я еще недостаточно знаю о LINQ или Entity Framework. Я создаю свои объекты вручную). Вторая причина, по которой я хотел бы вернуть две таблицы вместо одной, заключается в том, что у меня уже есть другая процедура, которая возвращает все элементы для данного OrderId вместе с родительским Order, и я хотел бы использовать тот же подход с двумя таблицами, чтобы я может повторно использовать клиентский код для заполнения моих пользовательских объектов Order и Client из 2 возвращаемых таблиц данных.
Я надеялся сделать следующее:
Построение динамической строки SQL на клиенте, которая присоединяет таблицу заказов к таблице элементов и фильтрует соответствующие таблицы для каждой таблицы, как указано в настраиваемом фильтре, созданном в приложении толстого клиента Winform. Сборка SQL на клиенте выглядела бы примерно так:
TempSQL = "
INSERT INTO #ItemsToQuery
OrderId, ItemsId
FROM
Orders, Items
WHERE
Orders.OrderID = Items.OrderId AND
/* Some unpredictable Order filters go here */
AND
/* Some unpredictable Items filters go here */
"
Тогда я бы вызвал хранимую процедуру,
CREATE PROCEDURE GetItemsAndOrders(@tempSql as text)
Execute (@tempSQL) --to create the #ItemsToQuery table
SELECT * FROM Items WHERE Items.ItemId IN (SELECT ItemId FROM #ItemsToQuery)
SELECT * FROM Orders WHERE Orders.OrderId IN (SELECT DISTINCT OrderId FROM #ItemsToQuery)
Проблема этого подхода заключается в том, что таблица #ItemsToQuery, поскольку она была создана с помощью динамического SQL, недоступна из следующих 2 статических SQL, и если я изменю статический SQL на динамический, результаты не будут переданы толстому клиенту.
3 вокруг приходят на ум, но я ищу лучшего:
1) Первый SQL можно выполнить, выполнив динамически построенный SQL из клиента. Затем результаты могут быть переданы в виде таблицы в модифицированную версию вышеописанной хранимой процедуры. Я знаком с передачей данных таблицы в виде XML. Если бы я сделал это, то сохраненный процесс мог бы затем вставить данные во временную таблицу, используя статический SQL, который, поскольку он был создан динамическим SQL, мог быть запрошен без проблем. (Я мог бы также изучить возможность передачи нового параметра типа Table вместо XML.) Однако я хотел бы избежать передачи потенциально больших списков в хранимую процедуру.
2) Я мог бы выполнить все запросы от клиента.
Первым будет что-то вроде этого:
SELECT Items.* FROM Orders, Items WHERE Order.OrderId = Items.OrderId AND (dynamic filter)
SELECT Orders.* FROM Orders, Items WHERE Order.OrderId = Items.OrderId AND (dynamic filter)
Это все еще дает мне возможность повторно использовать мой клиентский код заполнения объектов, потому что Заказы и Предметы продолжают возвращаться в двух разных таблицах.
У меня есть ощущение, что у меня могут быть некоторые варианты использования типа данных Table в моем сохраненном процессе, но это также ново для меня, и я был бы признателен за небольшую подачу ложки.
Если вы даже отсканировали так далеко в том, что я написал, я удивлюсь, но если это так, я буду признателен за любые ваши мысли о том, как добиться этого лучше.