Derby处理NULL值

时间:2011-02-05 08:11:35

标签: sql null db2 derby strong-typing

我是Derby的新手,我注意到我在使用DB2 RDBMS方面遇到的问题与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应该转换为的类型是未知的:

  • 在这个例子中,类型可以从insert子句派生,但对于更一般的用例,这可能被证明是复杂的或不可能的。
  • 在其他示例中,我可以选择任何类型的演员表(例如总是转换为int),但这不适用于此示例,因为您无法将cast(null as int)值放入ADDRESS
  • 使用HSQLDB(此问题的另一个候选者),我可以简单地编写cast(null as object),这在大多数情况下都可以使用。但是Derby没有object类型。

这个问题以前一直让我烦恼,我还没有找到解决方案。有没有人知道任何这些RDBMS的稳定一般解决方案?

  • 德比
  • DB2

4 个答案:

答案 0 :(得分:4)

如果在INSERT上使用VALUES子句,则不必转换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。

发出insert into ... select from语句时必须强制转换的原因是SELECT部分​​优先 - select语句返回某些数据类型,无论它们是否与您尝试的表兼容将它们插入。如果它们不兼容,您将收到错误(使用强类型数据库引擎,如DB2< = 9.5)或引擎将进行隐式类型转换(如果可能)。

答案 1 :(得分:2)

DB2使用空指示符...例如

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

注意NULL-IND2字段,可以设置为-1表示数据库表中的该字段应该为空。

是否有类似的JDBC或Derby指标?

答案 2 :(得分:1)

如果将列值保留为PreparedStatement中的问号替换值,然后使用PreparedStatement.setObject(N,null)在运行时设置值,该怎么办?

一般情况下,您的库更愿意通过替换参数值来提供列值,以处理字符串中的引号,数据类型转换等问题,我认为这种常规替换机制也应该处理您的null值问题

答案 3 :(得分:1)

也许这个解决方案可以帮助您:

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将返回所需类型的null。