Обработка значений NULL в Derby - PullRequest
4 голосов
/ 05 февраля 2011

Я новичок в Derby и заметил, что сталкиваюсь с аналогичными проблемами, что и при использовании СУБД DB2 в отношении значений null. Документация Derby гласит, что со значением null должен быть связан тип, с которым DB2 наконец-то избавилась в версии 9.7:

http://db.apache.org/derby/docs/10.7/ref/crefsqlj21305.html

Теперь я пытаюсь найти общее решение этой проблемы здесь, так как оно будет частью моей библиотеки абстракций базы данных jOOQ . Приведенный ниже пример просто документирует проблему. Подумайте о любом другом (более сложном) примере. Следующее не работает:

insert into T_AUTHOR (
  ID, FIRST_NAME, LAST_NAME, 
  DATE_OF_BIRTH, YEAR_OF_BIRTH, ADDRESS) 
select 
  1000, 'Lukas', 'Eder', 
  '1981-07-10', null, null 
from SYSIBM.SYSDUMMY1

Ни один из них не делает этого (что на самом деле делает jOOQ):

insert into T_AUTHOR (
  ID, FIRST_NAME, LAST_NAME, 
  DATE_OF_BIRTH, YEAR_OF_BIRTH, ADDRESS) 
select ?, ?, ?, ?, ?, ? 
from SYSIBM.SYSDUMMY1

Поскольку два значения null не имеют типа, связанного с ним. Решением было бы написать что-то вроде этого:

insert into T_AUTHOR (
  ID, FIRST_NAME, LAST_NAME, 
  DATE_OF_BIRTH, YEAR_OF_BIRTH, ADDRESS) 
select 
  1000, 'Lukas', 'Eder', 
  '1981-07-10', cast(null as int), cast(null as varchar(500)) 
from SYSIBM.SYSDUMMY1

Или вот так, соответственно

insert into T_AUTHOR (
  ID, FIRST_NAME, LAST_NAME, 
  DATE_OF_BIRTH, YEAR_OF_BIRTH, ADDRESS) 
select 
  ?, ?, ?, ?, cast(? as int), cast(? as varchar(500)) 
from SYSIBM.SYSDUMMY1

Но очень часто в Java тип, к которому следует привести null, неизвестен:

  • В этом примере типы могут быть получены из условия вставки, но это может оказаться сложным или невозможным для более общих случаев использования.
  • В других примерах я мог бы просто выбрать любой тип для приведения (например, всегда приведение к int), но это не сработает в этом примере, так как вы не можете поместить значение cast(null as int) в ADDRESS.
  • С HSQLDB (другой кандидат для этой проблемы) я могу просто написать cast(null as object), который будет работать в большинстве случаев. Но у Дерби нет типа object.

Эта проблема раздражала меня в DB2 раньше, и я пока не нашел решения. Кто-нибудь знает о стабильном и общем решении этой проблемы для любой из этих СУБД?

  • Derby

Ответы [ 4 ]

4 голосов
/ 05 февраля 2011

Если вы используете предложение VALUES в INSERT, вам не нужно приводить значения NULL:

insert into T_AUTHOR (
  ID, FIRST_NAME, LAST_NAME, 
  DATE_OF_BIRTH, YEAR_OF_BIRTH, ADDRESS) 
VALUES ( 
  1000, 'Lukas', 'Eder', 
  '1981-07-10', null, null 
);

Это будет работать так, как вы ожидаете (т. Е. База данных может определить, что значения NULL соответствуютцелое число и varchar (500). Это работает как в DB2, так и в Derby (и должно работать практически во всех других механизмах баз данных).

Вы также можете использовать VALUES с маркерами параметров, без необходимостиCAST them.

Причина, по которой вы должны приводить при выдаче оператора insert into ... select from, заключается в том, что часть SELECT имеет приоритет - оператор select возвращает определенные типы данных независимо от того, совместимы ли они с таблицей, которую вы используете.вы пытаетесь вставить их в. Если они несовместимы, вы либо получите ошибку (со строго типизированными механизмами баз данных, такими как DB2 <= 9.5), либо механизм выполнит неявное преобразование типов (когда это возможно). </p>

2 голосов
/ 17 ноября 2011

DB2 использует нулевой индикатор ... например,

EXEC SQL INSERT INTO TABNAM (FILD1, FILD2) 
                     VALUES (:HOSTVAR1, :HOSTVAR2:NULL-IND2)  END-EXEC.

обратите внимание на поле NULL-IND2, которое можно установить в -1, чтобы указать, что это поле в таблице базы данных должно быть нулевым.

Есть ли аналогичный индикатор для JDBC или Derby?

1 голос
/ 07 октября 2016

Может быть, это решение поможет вам:

insert into T_AUTHOR (
    ID, 
    FIRST_NAME, 
    LAST_NAME, 
    DATE_OF_BIRTH, 
    YEAR_OF_BIRTH, 
    ADDRESS
) select 
    1000, 
    'Lukas', 
    'Eder', 
    '1981-07-10', 
    (select YEAR_OF_BIRTH from T_AUTHOR where true = false), 
    (select ADDRESS from T_AUTHOR where true = false) 
from SYSIBM.SYSDUMMY1

Этот метод не требует явного приведения null, потому что внутренний select вернет ноль с требуемым типом.

1 голос
/ 05 февраля 2011

Что если вы оставите значения столбца в качестве значений подстановки вопросительного знака в PreparedStatement, а затем установите значения во время выполнения, используя PreparedStatement.setObject (N, null)?

В целом, ваша библиотека предпочитает предоставлять значения столбцов путем подстановки значений параметров, для обработки таких вопросов, как кавычки в строках, преобразования типов данных и т. Д., И я думаю, что этот общий механизм подстановки должен также обрабатывать проблемы с нулевыми значениями .

...