我是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
应该转换为的类型是未知的:
int
),但这不适用于此示例,因为您无法将cast(null as int)
值放入ADDRESS
。cast(null as object)
,这在大多数情况下都可以使用。但是Derby没有object
类型。这个问题以前一直让我烦恼,我还没有找到解决方案。有没有人知道任何这些RDBMS的稳定和一般解决方案?
答案 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。