Почему происходит слияние (upsert) с несоответствиями типов в базе данных HSQLDB при использовании полей VARBINARY? - PullRequest
0 голосов
/ 22 апреля 2020

Движок базы данных: HSQLDB (потому что, ну, он позволяет встроенную базу данных приложения в Java)

Язык: Java 8 (на самом деле, Groovy 3.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 - это адреса IPv4 или IPv6, закодированные как байтовые массивы из 4 или 16 элементов.

Я получаю сообщение об ошибке "org.hsqldb .HsqlException: несовместимый тип данных в преобразовании "в этом коде (упрощенно):

stmt.addBatch(a, b, c, d, e)

При использовании этого" upsert "для вставки данных, которые еще не существуют в таблице:

  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).

В На самом деле кажется, что все параметры VARCHAR. Это кажется странным.

Я не думаю, что что-то явно не так с моим SQL, так как он работал, когда у меня были поля START и END, определенные как VARCHAR. Теперь они просто не VARBINARY.

(причина, по которой я хочу, чтобы VARBINARIES состоял в том, чтобы разрешить сравнение чисел c в стиле между значениями VARBINARY.)

Мой поиск в Google не находит ничего значимого, но возможно кто-то здесь может предложить подсказку?

1 Ответ

1 голос
/ 23 апреля 2020

Работает ли это, если вы явно 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)
...