Я пытаюсь запустить запрос на слияние ниже в sybase 16.0, но он не работает с ошибкой
Ошибка SQL [102] [42000]: неправильный синтаксис рядом с '('.
merge into account_balance( id , account_name) as G
using SELECT (?, ?) AS D( id , account_name)
ON D.account_number=G.account_number
when not matched then
insert ( id , account_name) values ( D.id , D.account_name)
when matched then
update set G.id = D.id,G.account_name = D.account_name
Что означает эта ошибка ? эта команда не поддерживается в версии sybase 16.0, но в документации указано иное.
Предполагая, что OP использует Sybase (теперь SAP) ASE...
tl;dr - документация неверна.
Документация Sybase ASE всегда была случайной; после того, как SAP купила Sybase, им (SAP) удалось поднять термин «дрянная документация» на новую высоту; в данном случае утверждение merge
...
ПРИМЕЧАНИЕ. Следующее было получено в результате а) анализа утверждения merge
в других продуктах РСУБД и б) некоторого тестирования методом проб и ошибок.
Первая проблема: в предложении into
нет списка столбцов; ссылки на столбцы обрабатываются другими предложениями:
--------
-- replace this:
merge into account_balance( id , account_name) as G
---------
-- with this:
merge into account_balance as G
Вторая проблема: в документации используется ?
для (не столь четкого) обозначения места, куда должны быть предоставлены фактические значения данных; это значения, которые будут использоваться в результирующих insert
или update
:
--------
-- replace this:
using SELECT (?, ?)
---------
-- with this:
using SELECT (3, 'name3')
Третья проблема: при использовании производной таблицы в предложении using
необходимо заключить производную таблицу (так называемый подзапрос) в круглые скобки; кроме того, значения данных не заключаются в круглые скобки:
--------
-- replace this:
using SELECT (3, 'name3') AS D( id , account_name)
---------
-- with this:
using (SELECT 3, 'name3') AS D( id , account_name)
Четвертая проблема: столбцы, указанные в предложении on
, должны быть определены в предложении using
(в данном случае производная таблица OP); в этом случае нам нужно предоставить значение и ссылку на столбец соединения account_number
:
--------
-- replace this:
using (SELECT 3, 'name3') AS D( id , account_name)
---------
-- with this:
using (SELECT 3, 'name3', 'acct3') AS D( id , account_name, account_number)
Я предполагаю, что ОП хочет заполнить столбец account_number
, поэтому предложение insert
необходимо будет расширить, включив в него столбец account_number
:
--------
-- replace this:
insert ( id , account_name) values ( D.id , D.account_name)
---------
-- with this:
insert ( id , account_name, account_number) values ( D.id , D.account_name, D.account_number)
Объединив эти изменения, мы получаем следующее утверждение merge
:
merge into account_balance as G
using (SELECT 3,'name3','acct3') AS D (id,account_name,account_number)
ON D.account_number = G.account_number
when not matched then
insert ( id, account_name, account_number)
values (D.id,D.account_name,D.account_number)
when matched then
update set G.id = D.id,
G.account_name = D.account_name
Берем на тест-драйв:
Создадим нашу таблицу:
create table account_balance
(id int
,account_name varchar(100)
,account_number varchar(100)
)
go
select * from account_balance
go
id account_name account_number
-- ------------ --------------
(0 rows affected)
merge
, что приводит к insert
:
merge into account_balance as G
using (SELECT 3,'name3','acct3') AS D (id,account_name,account_number)
ON D.account_number = G.account_number
when not matched then
insert ( id, account_name, account_number)
values (D.id,D.account_name,D.account_number)
when matched then
update set G.id = D.id,
G.account_name = D.account_name
go
select * from account_balance
go
id account_name account_number
-- ------------ --------------
3 name3 acct3
(1 row affected)
merge
, что приводит к update
(id: 3
=> 5
; имя_аккаунта: name3
=> name5
):
merge into account_balance as G
using (SELECT 5,'name5','acct3') AS D (id,account_name,account_number)
ON D.account_number = G.account_number
when not matched then
insert ( id, account_name, account_number)
values (D.id,D.account_name,D.account_number)
when matched then
update set G.id = D.id,
G.account_name = D.account_name
go
select * from account_balance
go
id account_name account_number
-- ------------ --------------
5 name5 acct3
(1 row affected)
ПРИМЕЧАНИЕ: проверено с ASE 16.0 SP04 PL04
Спасибо, я понял подсказку из вашего ответа, заменив ваши жестко запрограммированные значения на? и установил параметры, и все заработало. Принимаю ваш ответ
Да, я знаком с использованием вопросительных знаков при построении подготовленных операторов, и возможно, человек, написавший эту часть руководства, имел опыт разработки/подготовки операторов. Большинство примеров SQL, которые я считаю полезными, связаны с фактическими значениями, и я предполагаю, что любой, у кого есть опыт написания подготовленных операторов, знает, как преобразовать такие примеры в ссылки с вопросительным знаком. Для удобства тех, кто может столкнуться с этими вопросами и ответами в будущем, вы можете рассмотреть возможность добавления собственного ответа, показывающего ваше окончательное решение. С уважением.
Не могли бы вы помочь мне и с этим вопросом stackoverflow.com/questions/78784695/…
Спасибо за ответ. Вы предоставили жестко закодированные значения, мне нужно использовать их с подготовленным оператором, так как я могу предоставить параметры в приведенном выше запросе, используя подготовленный оператор jdbc. Если я заменю жестко закодированные значения на ? Затем мне нужно указать имена столбцов также в таблице account_balance.