日付パラメータを使用したストアド プロシージャの実行:コマンドオブジェクトと接続オブジェクト
-
01-07-2019 - |
質問
パラメーターを介してストアド プロシージャに日付を指定する場合、日付にどの形式を使用するかについて少し混乱します。私の元の VBA 構文では、ADO Connection オブジェクトを使用してストアド プロシージャを実行しました。
Set SentDetailRS = Me.ADOConnectionToIntegrity.Execute("dbo.s_SelectAggregatedSentDetailList '" & fCSQLDate(EffectiveDate) & "'", , adCmdText)
これは日付構文を使用するとうまく機能します yyyy-mm-dd
しかし、別のユーザーがコードを実行すると、エラーが発生します。13 「タイプの不一致」。
いくつかの実験の後、日付を次の形式で指定するとわかりました dd/mm/yyyy
ユーザーのこのエラーは修正されますが、今度はエラーが表示されます。
パラメーターを指定したコマンド オブジェクトを使用してストアド プロシージャを実行すると、日付の形式に関係なく機能します (ADO が裏で形式設定を処理していると思います)。フォーマットを使用すると思いました yyyy-mm-dd
SQL Server では普遍的に動作しますか?
また、なぜこの問題がユーザー固有の問題のように見えるのかについても困惑しています。SQL Server の私のデフォルト言語が「英語」であるのに対し、他のユーザーのデフォルト言語は「イギリス英語」であることに気付きました。それが問題の原因でしょうか?
Access 2003 および SQL Server 2000 で ADO 2.8 を使用しています。SQL Server へのログインは Windows 統合セキュリティ経由です。
解決
ADO が問題に対処しているとは信じないように注意してください。ユニバーサル SQL の日付形式は「YYYYMMDD」ですが、SQL と ACCESS は日付の表示方法と文字列への変換方法においてマシンの地域設定の影響を受けます。
Access では日付区切り文字が # であるのに対し、SQL では日付区切り文字が ' であることを忘れないでください。
私の最善のアドバイスは、サーバーに命令を送信する前に、Access #MM-DD-YYYY# (または同様のもの) を「YYYYMMDD」に体系的に変換することです。次のような小さな関数を構築できます。
Public function SQLdateFormat(x_date) as string
SQLDateFormat = _
trim(str(datePart("yyyy",x_date))) & _
right(str(datePart("m",date)),2) & _
right(str(datePart("d",date)),2)
''be carefull, you might get something like '2008 9 3'
SQLDateFormat = replace(functionSQLDateFormat," ","0")
'' you will have the expected '20080903'
End function
INSERT/UPDATE 文字列をサーバーに送信する前にプログラムで作成しない場合は、すべてのマシンの地域設定を SQL をホストするマシンの地域設定に変更することをお勧めします。SQL サーバーに特定の日付形式があるかどうかも確認する必要があるかもしれません (よくわかりません)。個人的に、私はこの種のローカライズの問題 (フランス語で小数点としてカンマが使用されている場合にも発生します) や SQL 固有の文字の問題 (文字列に引用符または二重引用符が含まれている場合) を、SQL 命令を SQL 命令に送信する前に後退させることで解決しました。サーバ。
他のヒント
fCSQLDate 関数はカルチャ固有のものであると思います。つまり、ユーザーのロケール設定に基づいて日付を解析します。だからこそ問題が見えてくるのです。
いずれにしても、連結された文字列を含むクエリを使用することは常に悪い考えです (インジェクション攻撃)。パラメータを使用した方が良いでしょう。
Access では、日付フィールドの区切り文字として # が使用されます。形式は #mm/dd/yyyy# である必要があります。おそらく #mm-dd-yyyy# でも問題なく機能します。
申し訳ありませんが、mysql はわかりませんが、oracle では、期待する形式を常に明示的に指定します。例:「DD-MM-YYYY」、(地域の) 日付形式の問題を回避するため
なぜそのフォーマットを使わないのか
dd mmm yyyy
解釈できる方法は 1 つだけです。
Date() 関数を使用すると、マシンの日付と時刻の設定に基づいて汎用日付を返すことができます。マシンの地域設定によって、クライアント側でマシンがどのようにフォーマットされるかが決まります。フィールドを厳密な DateTime フィールドのままにすると、クライアント領域設定によって日付がフォーマットされる場合があります。
サーバーにアクセスして、Date() 関数を使用しても機能するはずです (汎用日付値を返します)。
また、文字列フィールドに対する SQL インジェクション攻撃を避けるために、クエリでコマンド オブジェクトとパラメータを渡すときにそれらを使用します。