一尘不染

Derby对NULL值的处理

sql

我是Derby的新手,我注意到,就null值而言,我面临着与使用DB2
RDBMS时类似的问题。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类型。

以前,这个问题一直困扰着我使用DB2,但我还没有找到解决方案。有没有人知道这些RDBMS的 稳定通用的 解决方案?

  • Derby
  • DB2

阅读 167

收藏
2021-03-10

共1个答案

一尘不染

如果在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之类的强类型数据库引擎),或者该引擎将进行隐式类型转换(如果可能)。

2021-03-10