#sql #sql-server #tsql
Вопрос:
Я пытаюсь использовать таблицу SQL server в открытом запросе к базе данных Oracle с использованием связанного сервера.
Мой код выглядит следующим образом.
select * INTO #customer from openquery( [Linkedserver], 'select * from customer c left join customer_contact cc ON c.main_contact_id = cc.contact_id where c.customer_account in (' (select customer_id from [database].[dbo]. [ChangeCustomers]) ') ' ) SELECT * FROM #customer
Однако ошибка, которую я получаю, заключается в
Msg 102, Уровень 15, Состояние 1, Проверка клиента процедуры, Строка 24 [Строка Запуска пакета 7] Неправильный синтаксис рядом с» «. Msg 102, Уровень 15, Состояние 1, Проверка клиента процедуры, Строка 24 [Строка Запуска пакета 7] Неправильный синтаксис рядом с» «.
Любая помощь будет признательна.
Комментарии:
1.Запрос
OPENQUERY
должен быть буквальным. Вы должны использовать динамический SQL, и ввести списка поддержки кодов безопасно в заявление, хотя вы не сможете использоватьSELECT...INTO
потом, но я не уверен, почему вы используете это (и если список длинный, это может иметь очень плохую работу или даже привести к сбою запроса) или поставитьWHERE
вне связаны запрос, который может означать, что запрос идет медленно из-за объема данных, необходимых для передаться от одного экземпляра к другому.2. Спасибо @Larnu, я изучу динамический SQL.
Ответ №1:
У вас есть две проблемы
- Вы не можете использовать
OPENQUERY
с переменной или выражением. Это должен быть литерал, поэтому вам нужен динамический SQL. - Вам нужно объединить подзапрос, иначе он будет ожидать только один результат.
DECLARE @sql nvarchar(max) = N' select * INTO #customer from openquery( [Linkedserver], ''select * from customer c left join customer_contact cc ON c.main_contact_id = cc.contact_id where c.customer_account in ( ' ( select STRING_AGG(QUOTENAME(QUOTENAME(customer_id, ''''), ''''), ',') from [database].[dbo].[ChangeCustomers] ) ' ) '' ); SELECT * FROM #customer; '; PRINT @sql; --for testing EXEC sp_executesql @sql;
Обратите внимание, как OPENQUERY
часть дважды экранируется, потому что она динамична в динамике.
Я не комментирую производительность такого запроса и не объясняю, почему вы решили сбросить данные во временную таблицу только для того, чтобы сразу же выбрать их обратно (у вас мог быть просто обычный SELECT
).
Комментарии:
1. Обратите внимание, как я уже упоминал в своем комментарии под вопросом, что
SELECT...INTO
здесь это в значительной степени бессмысленно. Я действительно не вижу пользы от вставки данных в таблицу и их выбора; особенно когда таблица затем будет неявно удалена, когда она выйдет за рамки2. Именно это я и сказал внизу: я не думаю, что это хорошая идея, но, возможно, OP сделал это из-за другого кода, который они не показывают. «Я не комментирую»-это британский пассивно-агрессивный способ в основном сказать: я даю комментарии, но это не имеет прямого отношения к рассматриваемому вопросу
3. Да, я просто удивлен, что вы просто не удалили временную таблицу из решения полностью.
4. Спасибо, да будет выполнять некоторые преобразования в выводимых данных. @Charlieface единственная проблема, которую я нахожу в данный момент, заключается в том, что string_agg не помещает значения в «» для передачи в Oracle, что затем приводит к сбою идентификатора. Если я попытаюсь выбрать STRING_AGG(concat(«‘,customer_id,»‘),’,’), произойдет сбой в Msg 189, уровень 15, Состояние 1, строка 14. Для функции concat требуется от 2 до 254 аргументов. Msg 137, Уровень 15, Состояние 2, Строка 27 Должна объявить скалярную переменную «@sql». Msg 137, Уровень 15, Состояние 2, Строка 29 Должна объявить скалярную переменную «@sql».
5. Хорошо, изменили, я предположил, что это целые числа.
Must declare the scalar variable "@sql"
вы получаете, потому что выполняете команды по отдельности, а не в пакетном режиме.