質問: SQL Server 2008 R2インスタンスが英語(米国)の言語でインストールされています。 SSMS>インスタンス>プロパティ>一般。 デフォルトの言語「イギリス英語」でログインを設定しました。 SSMS> Security>ログイン> User> Properties。 フロントエンド.NET Coreアプリケーションはフォーム/ Web APIを介してinsertステートメント(EF)を生成します。フォーム/ Web APIは、上記のLogin設定を使用して "sp_executesql"システムストアドプロシージャを作成します。 SQL Serverプロファイラを使用して、生成された挿入SQLに`'yyyy-mm-dd'.`形式`'yyyy-mm-dd'.`文字列の日付が含まれていることがわかります`'yyyy-mm-dd'.`たとえば、 `"2019-01-15 10:59:19.410"`です。 このステートメントを実行する前に、exec sp_reset_connectionとそれに続く以下のSETステートメントがあります(これは、各ログインの正しい設定を確実にするために接続プールの共有と関係があると思います)。 ``` -- network protocol: LPC set quoted_identifier on set arithabort off set numeric_roundabort off set ansi_warnings on set ansi_padding on set ansi_nulls on set concat_null_yields_null on set cursor_close_on_commit off set implicit_transactions off set language British set dateformat dmy set datefirst 1 set transaction isolation level read committed ``` 私を混乱させているのは、環境がイギリス英語(DMY)としてセットアップされているのに、 `yyyy-mm-dd`形式の日付があってもステートメントが正常に実行されることです。例えば、 `"2019-01-15 10:59:19.410"`です。 DMYが現在の設定であれば、「2019-01-15 10:59:19.410」は2019年15月15日の1日目と解釈されることを私は学びました。 たとえば、SQLが日付文字列をyyyy-dd-mmとして解釈しようとすると、これは失敗します。 ``` SET LANGUAGE [British English]; SELECT CAST('2019-01-13' AS DATETIME); ``` > メッセージ242、レベル16、状態3、行3 varcharデータ型からdatetimeデータ型への変換の結果、範囲外の値になりました。 > > 言語を英語(us_english)に設定すると、文字列の解釈がMDYに変わり、上記のステートメントが機能します。 あいまいでない日付文字列を使用できることを認識していますが、私が抱えている問題はEFフロントエンドによって生成される日付文字列に関連しています。 ステートメントが正常に実行されている理由はわかりません。明らかに日付文字列からDATETIME型への暗黙のキャストがあります。 SQLプロファイラーからステートメントをコピーしてSSMSに貼り付け、同じデータベース/同じユーザーに対して実行しようとすると、予期したとおりに失敗します。 > メッセージ8114、レベル16、状態1、行14データ型varcharからdatetimeへの変換中にエラーが発生しました。 > > そう... 文字列の日付からDATETIME型に変換するときに何が起こっているのか理解していて、SSMSでクエリを実行すると一貫した結果が得られますが、SSMSで失敗するクエリがフロントエンドから実行される理由はわかりません。 これがあまり説明されていない場合はお詫び申し上げます。
回答: https://weblogs.sqlteam.com/dang/2007/10/11/sql-trace-parameter-values-are-not-always-as-they-seem - 私はそれを非常に明確に説明しているこのブログに出会ったばかりです。 / 上のリンクの画像はもう利用できません(もともと2007年に投稿されました)。 しかし、このテキストは非常に参考になります。完全に表示されなくなる前に、以下に貼り付けました。 これが誰かに役立つことを願っています。 > Dan Guzmanブログ > ============== > > ### SQLトレースパラメータの値は、Dan Guzmanによる2007年10月11日の木曜日のように常に表示されるわけではありません。 > > 私は言及する価値があると思う、驚くべきSQL Trace / Profilerの動作に出会いました。トレースRPC開始/完了イベントで報告されたパラメータ値は、SQL Serverがクエリの実行に使用する値ではありません。これが私が最近発見した例で、これはこの動作を示しています。次のC#コードを実行して、パラメータ化されたクエリ "SELECT @ DateTime"を2007年10月11日に設定して実行しました。コンソールメッセージは、SQL Serverが予定日を返したことを確認しました。 > > スクリプトをトレースから貼り付けて、SQL Server Management Studioのクエリウィンドウから実行しました。これがSSMSスクリプトの実行のトレースです。 > > SQLは同じに見えますが、SSMSクエリはアプリケーション( "2007年10月11日")とは異なる日付( "2007年11月10日")を返しました。それは何ですか?同一のセッション設定であっても、アプリケーションコードとManagement Studio(またはQuery Analyzer)から実行すると、同じスクリプトが異なる値を返すのはなぜですか? > > 動作が異なる理由は、トレースイベントクラスです。アプリケーショントレースはRPC:Completedイベントを示しましたが、SSMSセッショントレースはSQL:BatchCompletedを示しました。両方とも、TextDataに同じ「exec sp_executesql」ステートメントがありました。トレースが両方のイベントに対して同じTextDataを報告したとしても、SQL ServerはRPCをSQLバッチとは異なる方法で処理し、トレースはRPCイベントの完全なストーリーを示しませんでした。 > > 問題は、RPCイベントの日時入力パラメーター値が、トレースRPC:Completedイベントのように実際にはSQLステートメントに含まれていなかったことです。 SQL ServerがRPCの実行中に使用した実際のdatetimeパラメータ値は、低レベルのTDSプロトコルを介してネイティブ(バイナリ)形式で渡されました。トレースTextDataは、SQL Serverが実際に使用した値ではなく、その値のリバースエンジニアリングされた文字列表現のみでした。 > > これとは対照的に、SSMSによって送信されたバッチはパラメータ化されていなかったため、SQL Serverはバッチテキスト内の日時文字列値を解析する必要がありました。日時文字列 "2007-10-11 00:00:00:000"(トレースによって生成され、アプリからは渡されません)はあいまいで、DATEFORMAT設定によって解釈が異なります。スクリプトの "DATEFORMAT DMY"設定により、日付文字列値は2007年10月11日ではなく2007年11月10日として(誤って)解釈されていました。DATEFORMAT設定はRPCに影響を与えませんでした。アプリケーションによって提供されるネイティブの日時値ではなく、ストリング解析のみ。 > > フランス語のSQL Serverを使用しているユーザー(DATEFORMAT DMYを指定した理由)がdatetimeパラメーターの問題をトラブルシューティングするのを手伝っていたときにこの問題を発見しました。 1)DATEFORMATはRPC datetimeパラメータに影響を与えず、2)trace RPC TextDataはクエリの実行には使用されません。これについてConnectのフィードバックを提出し、SQL Trace / Profilerを変更してRPC日付/時刻値を "2007-10-11T00:00:00:000"や "20071011 00:00:00:000"のようなDATEFORMATニュートラル形式でシリアル化するように提案。これは、トレースTextData SQLがバッチとして実行されるときと同じ動作を提供し、トレースデータを分析するときにもう少し直感的になります。 > > **著作権©2018 - Dan Guzman** > >