问题出在Postgres的"ON CONFLICT"语法上。
版本(maven依赖):
- postgresql: 42.2.9 - jooq: 3.12.3 - h2database: 1.4.200
得到以下错误日志(似乎问题可能是由于
版本(maven依赖):
- postgresql: 42.2.9 - jooq: 3.12.3 - h2database: 1.4.200
// mocking connection
final Connection connection = DriverManager.getConnection("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;Mode=PostgreSQL", "sa", "");
final Settings settings = new Settings().withRenderNameStyle(RenderNameStyle.AS_IS);
Mockito.doReturn(DSL.using(connection, SQLDialect.POSTGRES, settings)).when(mockDbConn).getDSLContext();
// java code for upsert:
dc.insertInto(MY_TABLE)
.columns(MY_TABLE.TOKEN, MY_TABLE.NAME, MY_TABLE.EMAIL)
.values(token, name, email)
.onDuplicateKeyUpdate()
.set(MY_TABLE.EMAIL, email)
.execute();
得到以下错误日志(似乎问题可能是由于
[*]
(第4行↓)引起的)。 我不明白它为什么出现,也不知道如何解决它。-- Syntax error in SQL statement:
INSERT INTO PUBLIC.MY_TABLE (TOKEN, NAME, EMAIL)
VALUES (?, ?, ?)
ON CONFLICT ([*]TOKEN, NAME) -- line 4
DO UPDATE SET EMAIL = EXCLUDED.EMAIL;
-- expected "DO";
-- SQL statement:
insert into public.my_table (token, name, email)
values (?, ?, ?)
on conflict (token, name)
do update set email = excluded.email;
-- [42001-200]
如果我从SQLDialect.POSTGRES
切换到SQLDialect.H2
方言,会发生以下情况:
-- Column "EXCLUDED.EMAIL" not found; SQL statement:
merge into public.my_table using (select 1 one)
on (public.my_table.token = cast(? as varchar) and public.my_table.name = cast(? as varchar))
when matched then update set public.my_table.email = excluded.email
when not matched then insert (token, name, email)
values (cast(? as varchar), cast(? as varchar), cast(? as varchar))
-- [42122-200]
[*]
只是H2附加到查询中的标记,用于指示SQL中包含第一个解析错误的位置。您应该在jOOQ中使用H2方言,H2的兼容模式提供了非常有限的兼容性,H2不是其他数据库的仿真器。但是,jOOQ为H2生成的查询也无效;EXCLUDED
虚拟表是来自PostgreSQL的ON CONFLICT
子句,不能在标准的MERGE
命令中使用。 - Evgenij Ryazanov