Db2
DB2 BOOLEAN 類型、EXISTS 謂詞和可空性奇怪行為
我正在使用 DB2 LUW v11.1.4.5,
似乎 EXISTS 謂詞,當 FALSE 返回 NULL 時(是否記錄在案?)在以下查詢
X is null
中true
,所有其餘的行為就像FALSE
是 的同義詞NULL
,但元數據表明所有列都不可為空(請參閱dbfiddle)with boolstmt as ( select 'exists' stmt, exists(select 1 from sysibm.sysdummy1 where ibmreqd = 'N') as x from sysibm.sysdummy1 ) select stmt, x, x is null "x is null", not x "NOT x", x = FALSE "x = FALSE", smallint(x) "smallint(x)", char(x) "char(x)" from boolstmt
現在使用以下查詢,每列都可以為空,它表明
x
確實NULL
是EXISTS
with boolstmt as ( select 'exists' stmt, exists(select 1 from sysibm.sysdummy1 where ibmreqd = 'N') as x from sysibm.sysdummy1 union all select 'count' stmt, (select count(*) from sysibm.sysdummy1 where ibmreqd = 'N') > 0 as x from sysibm.sysdummy1 ) select stmt, x, x is null "x is null", not x "NOT x", x = FALSE "x = FALSE", smallint(x) "smallint(x)", char(x) "char(x)" from boolstmt
我的問題是:有人知道嗎,在我看來這是伺服器上的問題,但您知道它是否來自 JDBC 驅動程序(使用 4.27.25)?使用更高版本的問題仍然存在嗎?
一個有趣的問題,答案並不那麼有趣:在這個簡單的例子中,你
EXISTS
被優化掉了,所以引用這個謂詞評估結果的嘗試是未定義的。如果您執行db2exfmt
(或另一個可以檢索語句的“優化”版本的工具),您將看到這就是最終執行的內容:SELECT 'exists' AS "STMT", $INTERNAL_FUNC$() AS "X", $INTERNAL_FUNC$() AS "x is null", $INTERNAL_FUNC$() AS "NOT x", $INTERNAL_FUNC$() AS "x = FALSE", SMALLINT($INTERNAL_FUNC$()) AS "smallint(x)", CHAR($INTERNAL_FUNC$()) AS "char(x)", $INTERNAL_FUNC$() AS "Y", $INTERNAL_FUNC$() AS "y is null", $INTERNAL_FUNC$() AS "NOT y", $INTERNAL_FUNC$() AS "y = FALSE", SMALLINT($INTERNAL_FUNC$()) AS "smallint(y)", CHAR($INTERNAL_FUNC$()) AS "char(y)" FROM (SELECT NULL FROM (VALUES ) AS Q1 WHERE ('Y' = 'N')) AS Q2
這很可能是“按設計工作”™,因為謂詞(其中
EXISTS
之一)並不打算用來代替表達式。Db2 試圖盡最大努力將謂詞評估結果轉化為值,但優化器佔了上風。當您在它們各自所屬的地方使用表達式和謂詞時,事情會如您所願:
with boolstmt as ( select 'exists' stmt, case when exists(select 1 from sysibm.sysdummy1 where ibmreqd = 'N') then true else false end as x from sysibm.sysdummy1 )