为什么在使用 VARBINARY 字段时,我的合并(更新插入)失败并在 HSQLDB 数据库中出现类型不匹配?
Why is my merge (upsert) failing with type mismatches in a HSQLDB database when using VARBINARY fields?
数据库引擎:HSQLDB(因为它允许在 Java 中嵌入应用程序数据库)
语言:Java8(其实是Groovy3.0.2,不过基本上是JRE)
架构如下:
CREATE TABLE A (
START VARBINARY(16) NOT NULL,
END VARBINARY(16) NOT NULL,
ID BIGINT NOT NULL,
COUNTRY VARCHAR(8),
DESCRIPTION VARCHAR(256),
PRIMARY KEY (START, END)
);
START 和 END 是编码为 4 或 16 元素字节数组的 IPv4 或 IPv6 地址。
我在这段代码(简化版)中收到错误 "org.hsqldb.HsqlException: incompatible data type in conversion":
stmt.addBatch(a, b, c, d, e)
当使用此 "upsert" 插入 table 中尚不存在的数据时:
MERGE INTO A
USING (VALUES ?,?,?,?,?) I (START, END, ID, COUNTRY, DESCRIPTION)
ON (A.START = I.START AND A.END = I.END)
WHEN MATCHED THEN UPDATE
SET A.ID = I.ID, A.COUNTRY = I.COUNTRY, A.DESCRIPTION = I.DESCRIPTION
WHEN NOT MATCHED THEN INSERT (START, END, ID, COUNTRY, DESCRIPTION)
VALUES (I.START, I.END, I.ID, I.COUNTRY, I.DESCRIPTION)
这里a
和b
是byte[]
,c
是long
,d
和e
是Strings
和 stmt
是 BatchingPreparedStatementWrapper
.
调试意味着 stmt
变量认为语句的参数 1 和 2(a
和 b
)是 VARCHAR 类型...它们应该是 VARBINARY(16 ).
实际上好像认为所有的参数都是VARCHARs。这似乎很奇怪。
我认为我的 SQL 没有任何明显的错误,因为它曾经在我将 START 和 END 字段定义为 VARCHAR 时工作。只是现在它们不是 VARBINARY。
(我想要 VARBINARIES 的原因是允许在 VARBINARY 值之间进行数字样式比较。)
我的谷歌搜索没有找到任何相关内容,但也许这里有人可以提供线索?
您在查询中显式 cast()
输入参数是否有效?
MERGE INTO A
USING
(VALUES CAST(? AS VARBINARY(16)), CAST(? AS VARBINARY(16)), ?, ?, ?)
I (START, END, ID, COUNTRY, DESCRIPTION)
ON (A.START = I.START AND A.END = I.END)
WHEN MATCHED
THEN UPDATE
SET A.ID = I.ID, A.COUNTRY = I.COUNTRY, A.DESCRIPTION = I.DESCRIPTION
WHEN NOT MATCHED
THEN INSERT (START, END, ID, COUNTRY, DESCRIPTION)
VALUES (I.START, I.END, I.ID, I.COUNTRY, I.DESCRIPTION)
数据库引擎:HSQLDB(因为它允许在 Java 中嵌入应用程序数据库)
语言:Java8(其实是Groovy3.0.2,不过基本上是JRE)
架构如下:
CREATE TABLE A (
START VARBINARY(16) NOT NULL,
END VARBINARY(16) NOT NULL,
ID BIGINT NOT NULL,
COUNTRY VARCHAR(8),
DESCRIPTION VARCHAR(256),
PRIMARY KEY (START, END)
);
START 和 END 是编码为 4 或 16 元素字节数组的 IPv4 或 IPv6 地址。
我在这段代码(简化版)中收到错误 "org.hsqldb.HsqlException: incompatible data type in conversion":
stmt.addBatch(a, b, c, d, e)
当使用此 "upsert" 插入 table 中尚不存在的数据时:
MERGE INTO A
USING (VALUES ?,?,?,?,?) I (START, END, ID, COUNTRY, DESCRIPTION)
ON (A.START = I.START AND A.END = I.END)
WHEN MATCHED THEN UPDATE
SET A.ID = I.ID, A.COUNTRY = I.COUNTRY, A.DESCRIPTION = I.DESCRIPTION
WHEN NOT MATCHED THEN INSERT (START, END, ID, COUNTRY, DESCRIPTION)
VALUES (I.START, I.END, I.ID, I.COUNTRY, I.DESCRIPTION)
这里a
和b
是byte[]
,c
是long
,d
和e
是Strings
和 stmt
是 BatchingPreparedStatementWrapper
.
调试意味着 stmt
变量认为语句的参数 1 和 2(a
和 b
)是 VARCHAR 类型...它们应该是 VARBINARY(16 ).
实际上好像认为所有的参数都是VARCHARs。这似乎很奇怪。
我认为我的 SQL 没有任何明显的错误,因为它曾经在我将 START 和 END 字段定义为 VARCHAR 时工作。只是现在它们不是 VARBINARY。
(我想要 VARBINARIES 的原因是允许在 VARBINARY 值之间进行数字样式比较。)
我的谷歌搜索没有找到任何相关内容,但也许这里有人可以提供线索?
您在查询中显式 cast()
输入参数是否有效?
MERGE INTO A
USING
(VALUES CAST(? AS VARBINARY(16)), CAST(? AS VARBINARY(16)), ?, ?, ?)
I (START, END, ID, COUNTRY, DESCRIPTION)
ON (A.START = I.START AND A.END = I.END)
WHEN MATCHED
THEN UPDATE
SET A.ID = I.ID, A.COUNTRY = I.COUNTRY, A.DESCRIPTION = I.DESCRIPTION
WHEN NOT MATCHED
THEN INSERT (START, END, ID, COUNTRY, DESCRIPTION)
VALUES (I.START, I.END, I.ID, I.COUNTRY, I.DESCRIPTION)