web-dev-qa-db-ja.com

SQL Server 2016の互換性レベルと日時2

私たちはしばらくの間SQL Server 2016を実行していますが、最初はデータベースの互換性レベルをSQL Server 2008(100)のままにしました。最近、DB互換性レベルを2016(130)に更新しましたが、そこではいくつかの問題が発生しました。クエリがdatetimeをdatetime2に変換し、値を返す必要があるときにNULLを返す特定の1つを見つけることに成功しました。CEか何かかどうかはわかりませんか?以下の例をご覧ください。

CREATE TABLE TestCE
(
    Id           INT IDENTITY(1,1),
    CurrentDateTime  DATETIME
)
GO

INSERT dbo.TestCE(CURRENTDATETIME)
SELECT GETDATE()
UNION ALL SELECT '2018-04-11 08:44:42.643'
UNION ALL SELECT '2018-04-12 09:49:45.334'
GO

SELECT * FROM TestCE 
--The resultset

1    2018-04-17 16:49:02.813
2    2018-04-11 08:44:42.643
3    2018-04-12 09:49:45.333

しかし、次のクエリを実行しても結果が得られません。

SELECT * FROM TESTCE 
  WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-12 09:49:45.333') 
GO

SELECT * FROM TESTCE 
  WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-11 08:44:42.643') 
GO

SELECT * FROM TESTCE 
  WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-17 16:49:02.813') 

また、後方CEに対してQueryTraceOnオプションを試してみましたが、成功しませんでした。

SELECT * FROM TESTCE 
  WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-12 09:49:45.333') 
  OPTION(QUERYTRACEON 9481);
GO

SELECT * FROM TESTCE 
  WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-11 08:44:42.643') 
  OPTION(QUERYTRACEON 9481);
GO

SELECT * FROM TESTCE 
  WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-17 16:49:02.813') 
  OPTION(QUERYTRACEON 9481);

また、次のDBオプションを設定しますが、いずれも成功しません。

ALTER DATABASE SCOPED CONFIGURATION 
  SET LEGACY_CARDINALITY_ESTIMATION = ON

互換性レベルを2008に戻すとすぐに、クエリは期待どおりにデータを返し始めます。

3
Sajid

から このKB記事

SQL Server 2016とAzure SQL Database以降、データベースエンジンには、データ型変換とその他のいくつかの操作が改善されています。これらの改善のほとんどは、浮動小数点型や従来の日時型を処理するときに精度を向上させます。これらの改善点はすべて、少なくともデータベース互換性レベル130を使用している場合に利用できます。これは、データベースを互換性レベル130以上に設定した後、一部の(ほとんど一般的ではない)式で一部の入力値に対して異なる結果が表示されることを意味します.

特定の例では、次の場合に比較が機能します。

  • datetime2への変換を強制しません(そして、入力の精度がそれ以上ないため、これは不要です)。
  • 最初にdatetime2列から始めます。
  • datetime2に変換した後、入力をdatetimeに変換します。または、
  • 古い互換レベルを維持します。

それ以外の場合は、SQL Serverに.333 = .334などのように永久に知らせようとしています。新しいタイプはSQL Server 2008で導入され、このタイプの不正確さに正確に対処するために置き換えられました。彼らはいつか先に進む必要があると感じていると思います。

余談ですが、私は現在の動作が100%正しいとは思いませんが、今のところそれは行き詰まっています。

さらに、互換性レベルは、カーディナリティ推定モデルに影響を与える1つの方法ですが(実際に良い方法ではありません)、逆は当てはまりません。 CEモデルを変更して互換性レベルを変更することはできません。これが、クエリレベルのトレースフラグまたはデータベース構成オプションを使用して成功しなかった理由です。ただし、100に戻る必要はありません。 120もおそらく機能します。

3
Aaron Bertrand