2011-02-05 42 views
4

我是Derby的新手,我注意到我面临类似的问题,因为在使用DB2 RDBMS时,直到涉及null值。 Derby文档状态,即一个null值必须有一个与之关联的类型(的东西,DB2终于得到了在9.7版本去掉):Derby处理NULL值

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),这在大多数情况下都可以工作。但德比没有object类型。

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

  • 德比
  • DB2

回答

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处理。

你必须c当发出insert into ... select from语句时,由于SELECT部分​​优先 - select语句返回某些数据类型,无论它们是否与要插入的表格兼容。如果它们不兼容,您将得到一个错误(使用类型为DB2 < = 9.5的强类型数据库引擎),否则引擎将执行隐式类型转换(如果可能)。

1

如果你离开的列值作为问号替换值在你的PreparedStatement,然后设置使用PreparedStatement.setObject在运行时的值(N,NULL) ?

一般而言,您的库将更喜欢通过替换参数值来提供列值,以处理字符串中的引号,数据类型转换等问题,我认为这种通用的替换机制应该将空值问题作为好。

+0

感谢您输入Bryan。我不知道为什么我放弃绑定变量。当然,我的库总是使用绑定变量来提高性能/安全性等,而不是直接将值内联到SQL。我会修改这个问题。 – 2011-02-05 15:33:51

+0

不用担心。您可能遇到https://issues.apache.org/jira/browse/DERBY-1938,这是刚刚修复的。你在使用最新的德比(10.7)吗?如果没有,请尝试一下,看看setObject(null)现在是否工作得更好。 – 2011-02-05 19:59:55

+0

是的,我正在使用Derby 10.7.1.1。但实际上这是`setObject(null)`的一个好提示。我有两个错误的组合,首先``Connection.prepareStatement()`调用不接受`null`文字或'cast(?as integer)`表达式(如果整数是错误的类型)。当我简单地为空值准备`?`时,我的库调用`PreparedStatement.setNull(N,Object.class)`,这也没有工作。但`setObject(N,null)`似乎工作。我会仔细检查... – 2011-02-06 08:33:03

2

DB2使用空指针...例如

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

通知NULL-IND2场可以设置为-1,表明该领域在数据库中的表应为空。

是否有类似的JDBC或德比指标?

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