2011-01-13 181 views
1

私は、ADOを使用してSQL ServerまたはMS AccessのいずれかのデータベースをサポートするDelphi 2010アプリケーションを使用しています。パラメータ化されたクエリを使用してデータベースにSQLを送信する場合、日付表現の違いが正しく処理されます。しかし、時には動的SQLを作成してデータベースに送る必要があります。ADOプロバイダに基づいて日付をフォーマットする

TADOConnection形式の日付を現在のデータベースに適したテキスト文字列にする方法や、日付をどのように書式設定する必要があるかを調べるために接続を調べる方法はありますか?さもなければ私はプロバイダ名と日付書式設定関数のテーブルを作成しています。

答えて

3

変換する

チェックはあなたにも動的SQLを使用したパラメータを使用することができるはずです。私は自分のOPFフレームワークのいくつかのバージョンでこれを行っています。

パラメータを使用してSQL文を書き、それを文字列としてTAdoQuery(またはTAdoCommand)のSQLテキストに割り当てます。コンポーネントはテキストを解析し、パラメータコレクションを設定する必要があります。その後、あなたのパラメータに値を代入し、[開く]を呼び出したり、実行することができるはず...

あなたのアイデアを与える:

:FillSelectParamsは以下FillParamsプロシージャを呼び出し

する

DS := DatasetClass.Create(self.Connection); 
    try 
    DS.QueryText := SQL.Text; 
    FillSelectParams(DS); 
    DS.Open; 
    try 
     ... 
    finally 
     DS.Close; 
    end; 
    finally 
    DS.Free; 
    end; 

この場合、パラメータ値はカスタムドメインオブジェクト(CDO)から取得されますが、ここで独自の味を使用することができます。

AdjustParamValue関数は、いくつかの変換を処理します。異なるTDataSetの子孫との部品のばらつきの世話をするために、使用TCustomDataSetクラスの子孫のADOのバージョンで実装されていないが、どこにもSQLデータベースのタイプが遊びに来るん:

function TADODCDataset.AdjustParamValue(Attr: TCustomDomainAttribute): Variant; 
begin 
    if Attr is TIdentityAttribute then begin 
    if Attr.AsInteger = 0 then begin 
     Result := Null; 
    end else begin 
     Result := Attr.Value; 
    end; 
    end else if Attr is TBooleanAttribute then begin 
    if Attr.AsBoolean then begin 
     Result := Integer(-1); 
    end else begin 
     Result := Integer(0); 
    end; 
    end else if Attr is TDateTimeAttribute then begin 
    if Attr.AsDateTime = 0 then begin 
     Result := Null; 
    end else begin 
     Result := Attr.Value; 
    end; 
    end else if Attr is TEnumAttribute then begin 
    Result := Attr.AsString 
    end else begin 
    Result := Attr.Value; 
    end; 
end; 
+0

ありがとう、このようなシステムは私が私の既存のコードに適応できない場合、私がしなければならないと思っていたものです。私の考えは、独自のTParametersオブジェクト(パラメータ化されたSQLからデータセットによって生成されたオブジェクトではない)を作成し、それをFillParamsメソッドに非常に似たバインディング関数に渡すことでした。 –

+0

これは私がやっていることです。 –

2

Larry、私はあなたにSQL Server Partの回答を提供します。

あなたは、このビューによって返される列の1は、例えば、日付順を示すdateformatと呼ばれ、SQLサーバにインストールされている言語に関する情報を取得するDMYをsys.syslanguagesシステムビューを使用することができます。

@@langid(現在使用されている言語のローカル言語識別子(ID)を返します)関数を使用すると、Sql Serverで使用されている現在の日付形式を取得できます。

select dateformat from sys.syslanguages where [email protected]@langid 

これで、デルファイで解析して日付をフォーマットすることができる文字列が表示されます。

別のオプションは、SQL Serverの定義済み形式の1つを選択し、文字列を日付に変換するためにSQL文でCONVERT関数を使用することです。 ISO形式を使用しています。このサンプルは

//The ISO format is yyyymmdd so i can use the FormatDateTime function to convert any TdateTime to a Iso format sdatetiem string 
DateStr:=FormatDateTime('YYYYMMDD',Now); 
//Now construct the sql server sentence 
SqlSentence:=Format('UPDATE MyTable SET DateField=CONVERT(DATETIME,%s,112)',QuotedStr(DateStr)); 
+0

Ah - ISO形式はYYYYMMDDではなくYYYY-MM-DDです。 http://en.wikipedia.org/wiki/ISO_8601 – TomTom

+0

私は、SQL Serverでも複数のフォーマットを処理する必要はないと思っていました。別の言語に設定されたシステムで実行されている場合、標準日付を受け付けませんか? –

+0

@TomTom、このリンクをチェックしてください。http://msdn.microsoft.com/en-us/library/ms187928.aspx、「ISOフォーマット」と言うと、私はSqlサーバーの112コードを参照しています。 – RRUZ

0

は、ODBCの日付を使用してみてくださいエスケープシーケンスは、SQL ServerおよびAccess OLEDBプロバイダによってサポートされる可能性があります。たとえば:

{d '2011-01-14'} 
+0

私はそれが動作するかどうかを知るために、他の理由であれば、それを与えます。 –

0

マージャンが示唆するように、あなたは常にパラメータを使用shoud。 (SQLインジェクションの検索を試みてください)

パラメータを使用する別の理由は、クエリプランをSQL Server上で再利用できることです。 作成された最初のステートメントがSELECT> *であり、作成された> 2010-12-21で、生成された次のステートメントがSELECT *である場合(作成された> 2010-12-22の場合)、クエリオプティマイザ/両方の時間(別のステートメント)をコンパイルします。しかし、両方のステートメントがSELECT *である場合、顧客は>?を作成した場合、計画はSQLサーバー上で再利用されます - >(わずかに)低くなります。

私はあなたが試したすべてのSQL(実装)(私はアクセスしようとしていません)は、ISO日付フォーマットを受け入れて理解することができます(例えば '2010-12-21' )

+0

ありがとう、私はよくSQLインジェクションの問題を認識しています。この場合、SQLスニペットは、DateWhere(AFrom、ATo:TDate)というシグネチャを持つ関数によって構築されるため、注入の危険はありません。 –

関連する問題