web-dev-qa-db-ja.com

SQL Server 2016 ISNULLが1900-01-01を返す

DocDateという名前のdatetime2列があり、ISNULLチェックを評価して、NULLではなく空の''値を返します。

ステートメントのスニペット:

SELECT TOP 100
    DocumentId
    ,DocDate
    ,ISNULL(DocDate,'') AS 'DocDateEmpty'
FROM
    DocDetails
WHERE
    DocDate IS NULL

これは以下を返します:1900-01-01 00:00:00.0000000

私のWHERE句は、明示的にNULLである行のみを明確に返すため、DocDateが空の文字列であり、0に評価されるという問題はありません。

SSMS Capture

どのようにDocDate IS NULLを正しく評価できますが、ISNULLは失敗しますか?

[〜#〜] msdn [〜#〜] ごとに、ISNULLliteralNULLの値を正しく評価し、空を返す必要があります値。

check_expressionと同じ型を返します。 check_expressionとしてリテラルNULLが指定されている場合、replacement_valueのデータ型を返します。 check_expressionとしてリテラルNULLが提供され、replacement_valueが提供されない場合、intを返します

3
PicoDeGallo

これは、DATETIMEおよび_DATETIME2_で発生します。

_DECLARE @dummy DATETIME2 = NULL
SELECT @dummy, ISNULL(@dummy, N'')
GO 

DECLARE @dummy DATETIME = NULL
SELECT @dummy, ISNULL(@dummy, N'')
GO 
_

DATEおよびTIMEとともに

_DECLARE @dummy DATE = NULL
SELECT @dummy, ISNULL(@dummy, N'')
GO 

DECLARE @dummy TIME = NULL
SELECT @dummy, ISNULL(@dummy, N'')
GO 
_

私はそれを回避する最も簡単な方法は、2番目のCONVERTを文字列に追加することだと思います:

_DECLARE @dummy DATETIME2 = NULL
SELECT @dummy, ISNULL(CONVERT(NVARCHAR(30), @dummy), N'')
GO 
_

必要に応じて空の文字列を返します。

whyに関する質問に答えるために、別のシナリオを見てみましょう。

_DECLARE @dummy INT = NULL 
SELECT @dummy, ISNULL(@dummy, '')
_

ここでのISNULLは0を返します。SQLServerが日付を格納および処理する方法がわからない場合は、詳細について、「my Q&A here 」を参照してください。

つまり、SELECT CONVERT(DATETIME, 0)を実行すると、おなじみの結果が得られます。空の数値のようなものはなく、空の文字列から数値式への変換もありません。

お役に立てれば!

2
Erik Darling