2011-02-05 81 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將返回空值與所需的類型。