sql >> データベース >  >> RDS >> Sqlserver

ADO.NET + SQL Server DateTime列のライフサイクルでタイムゾーンはどのように処理されますか?

    4 つの部分すべてで自分の質問に答えるために、いくつかの単体テストを実行しました。

    ###1:SQL Server はそれに応じて DateTime.UtcNow を保存しますか、それともサーバーがインストールされている場所のタイムゾーンに基づいて再度オフセットし、クエリを実行するとオフセットを逆にして返すのでしょうか?これを実行しました):

    cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));cmd.ExecuteNonQuery(); cmd.CommandText ="SELECT CAST(varchar としての値) 値 FROM testtbl";Console.WriteLine(cmd.ExecuteScalar());  

    現地時間午後 1 時 30 分 (-7h、または UTC 午後 8 時 30 分) でのこの結果:

    2010 年 6 月 3 日午後 8 時 30 分  

    次に、これを試しました:

    cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));cmd.ExecuteNonQuery(); Console.WriteLine("タイムゾーンを utc に変更");Console.ReadLine();cmd.CommandText ="SELECT CAST(varchar としての値) value FROM testtbl";Console.WriteLine(cmd.ExecuteScalar());Console.WriteLine (「タイムゾーンをローカルに戻す」);  

    UTC 午後 9 時 25 分に実行され、返されました

    2010 年 6 月 3 日午後 9 時 25 分  

    これを DateTime.Now と比較してください:

    cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now));cmd.ExecuteNonQuery(); Console.WriteLine("タイムゾーンを utc に変更");Console.ReadLine();cmd.CommandText ="SELECT CAST(varchar としての値) value FROM testtbl";Console.WriteLine(cmd.ExecuteScalar());Console.WriteLine (「タイムゾーンをローカルに戻す」);  

    午後 3 時 55 分 (ローカル; -7 時間) に実行され、返される:

    2010 年 6 月 3 日午後 3 時 55 分  

    ###2:それで、たとえば IDataReader 列から取得した後、クエリを実行し、オブジェクトから DateTime にキャストします。このキャストされた System.DateTime オブジェクトは、それが UTC DateTime インスタンスであることを既に認識していますか?それともオフセットされていると想定していますか?

    どちらでもない。

    cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));cmd.ExecuteNonQuery(); cmd.CommandText ="SELECT val 値 FROM testtbl";var retval =(DateTime)cmd.ExecuteScalar();Console.WriteLine("Kind:" + retval.Kind);Console.WriteLine("UTC:" + retval.ToUniversalTime ().ToString());Console.WriteLine("Local:" + retval.ToLocalTime().ToString());  

    この結果 (現地時間午後 1 時 58 分に実行) は次のとおりです。

    Kind:UnspecifiedUTC:6/4/2010 3:58:42 AMLocal:6/3/2010 1:58:42 PM  

    つまり、 .ToUniversalTime() 現地時間から UTC 時間へのオフセットが 1 回ではなく 2 回 (??) になり、 .ToLocalTime() まったく相殺されませんでした。

    ###3:ADO.NET はオフセットを SQL Server に渡し、SQL Server は DateTime.Now をオフセット メタデータと共に保存しますか?

    単体テストを実行しなくても、答えは「DateTimeOffsetのみ」のSQLタイプであることが既にわかっています。 SQL の datetime オフセットは行いません。

    ###4:このキャストされた System.DateTime オブジェクトは、それがオフセット時間であることを既に認識していますか、それとも UTC であると想定していますか?

    ない。 SQL の DateTimeOffset 型は、.NET DateTimeOffset 構造体として返されます。

    以下は、現地時間の午後 3 時 31 分に実行され、列 offval は datetimeoffset SQL タイプです。

    cmd.CommandText ="INSERT INTO testtbl (offval) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now));cmd.ExecuteNonQuery(); cmd.CommandText ="testtbl から offval 値を選択";object retvalobj =cmd.ExecuteScalar();Console.WriteLine("Type:" + retvalobj.GetType().Name);var retval =(DateTimeOffset)retvalobj;Console.WriteLine ("ToString():" + retval.ToString());Console.WriteLine("UTC:" + retval.ToUniversalTime().ToString());Console.WriteLine("Local:" + retval.ToLocalTime(). ToString());  

    その結果:

    タイプ:DateTimeOffsetToString():6/3/2010 3:31:47 PM +00:00UTC:6/3/2010 3:31:47 PM +00:00Local:6/3/2010 8 :31:47 AM -07:00  

    驚くべき格差。

    DateTime.UtcNow の代わりに DateTime.Now を使用して上記の質問 1 のテストに戻り、データベースに保存する前に ADO.NET が世界時に変換されないことを検証しました。

    つまり、これは現地時間の午後 3 時 27 分 (-7h) に実行されます:

     cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)"; cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now)); cmd.ExecuteNonQuery(); Console.WriteLine("タイムゾーンを utc に変更"); Console.ReadLine(); cmd.CommandText ="SELECT CAST(varchar としての値) value FROM testtbl"; Console.WriteLine(cmd.ExecuteScalar()); Console.WriteLine("タイムゾーンをローカルに戻す");  

    ..返されました..

    2010 年 6 月 3 日午後 3 時 27 分  

    これを現地時間午後 3 時 17 分に実行:

    cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.UtcNow));cmd.ExecuteNonQuery(); cmd.CommandText ="SELECT val FROM testtbl";var result =(DateTime)cmd.ExecuteScalar();Console.WriteLine("Kind:" + result.Kind);Console.WriteLine("ToString():" + result. ToString());Console.WriteLine("1 分足します。UtcNow より大きいですか?" + (result.AddMinutes(1)> DateTime.UtcNow).ToString());Console.WriteLine("1 分足します。大きいですか? " + (result.AddMinutes(1)> DateTime.Now).ToString());Console.WriteLine("1分追加、UtcNow未満? " + (result.AddMinutes(1)  DateTime.UtcNow).ToString());Console.WriteLine("1 分減算します。今より大きいですか? " + (result.AddMinutes(-1)> DateTime.N ow).ToString());Console.WriteLine("1分引いて、UtcNow未満? " + (result.AddMinutes(-1)   

    結果:

    Kind:UnspecifiedToString():6/3/2010 10:17:05 PMAdd 1 分、UtcNow より大きいですか? TrueAdd 1分、今より大きい? TrueAdd 1 分、UtcNow 未満ですか? FalseAdd 1分、今より短い? FalseSubtract 1 分、UtcNow より大きいか? FalseSubtract 1 分、Now より大きいか? TrueSubtract 1 分、UtcNow 未満ですか? TrueSubtract 1分、今より少ない?偽  

    これを DateTime.Now と比較してください:

    cmd.CommandText ="INSERT INTO testtbl (val) 値 (@newval)";cmd.Parameters.Add(new SqlParameter("@newval", DateTime.Now));cmd.ExecuteNonQuery(); cmd.CommandText ="SELECT val FROM testtbl";var result =(DateTime)cmd.ExecuteScalar();Console.WriteLine("Kind:" + result.Kind);Console.WriteLine("ToString():" + result. ToString());Console.WriteLine("1 分足します。UtcNow より大きいですか?" + (result.AddMinutes(1)> DateTime.UtcNow).ToString());Console.WriteLine("1 分足します。大きいですか? " + (result.AddMinutes(1)> DateTime.Now).ToString());Console.WriteLine("1分追加、UtcNow未満? " + (result.AddMinutes(1)  DateTime.UtcNow).ToString());Console.WriteLine("1 分減算します。今より大きいですか? " + (result.AddMinutes(-1)> DateTime.Now) .ToString());Console.WriteLine("1 分減算、UtcNow 未満ですか? " + (result.AddMinutes(-1)   

    午後 3 時 58 分に実行 (ローカル、-7 時間):

    Kind:UnspecifiedToString():6/3/2010 3:59:26 PMAdd 1 分、UtcNow より大きいですか? FalseAdd 1分、今より大きい? TrueAdd 1 分、UtcNow 未満ですか? TrueAdd 1分、今より短い? FalseSubtract 1 分、UtcNow より大きいか? FalseSubtract 1 分、Now より大きいか? FalseSubtract 1 分、UtcNow 未満ですか? TrueSubtract 1分、今より少ない?真  

    1. HOUR()の例– MySQL

    2. ハイブリッドOLTP/Analyticsデータベースワークロード:MySQLデータをClickHouseに複製する

    3. SQLServerを使用するためのAzure仮想マシン

    4. Mysql Duplicate Rows(2列を使用して重複が検出されました)