5

TSQLDataset パラメータに null 値を渡そうとしています。クエリの形式は次のとおりです。

Query_text:='MERGE INTO [Table] 
             USING (VALUES (:A,:B)) AS Source (Source_A, Source_B)
             ....
             WHEN MATCHED THEN 
             UPDATE SET A = :A
             WHEN NOT MATCHED THEN
             INSERT(A, B) VALUES (:A,:B);

SQL_dataset.CommandType:=ctQuery; 
SQL_dataset.CommandText:=Query_text;

SQL_dataset.ParamByName('A').AsString:='A';  
SQL_dataset.ParamByName('B').AsString:={ COULD BE NULL, OR A STRING };    

SQL_dataset.ExecSQL;

パラメータ B は null 可能ですが、外部キーでもあります。ユーザーがこのフィールドに何かを入力した場合、B は別のテーブルの値に対して検証する必要があります。空白の場合は無視してください。'' を渡していましたが、これは明らかに FK 違反エラーを生成します。

私は試した:

SQL_dataset.ParamByName('B').Value:=Null;

..しかし、「dbexpress ドライバーは tdbxtypes.unknown データ型をサポートしていません」というエラーが表示されます。

私も試しました:

SQL_dataset.ParamByName('B').DataType:=ftVariant;
SQL_dataset.ParamByName('B').Value:=Null;

..しかし、「dbexpress ドライバーは tdbxtypes.variant データ型をサポートしていません」というエラーが発生しました。

私が何を間違っているのかわからないので、助けていただければ幸いです。現在、文字列が入力されているかどうかに基づいてパラメーター リストを作成していますが、これはうまく機能します。検証するパラメーターがかなりあるため、(実際のクエリでは)少し不格好です。

Delphi XE4 と SQL サーバー 2012 を使用しています。

アップデート:

すべての助けに感謝します。あなたの提案はずっと正しかったのですが、その「dbexpress ドライバー」エラーを引き起こしたのは別の何かでした。私の問題を回避するために「柔軟な」パラメーターリストを作成していましたが、これにより例外が発生しました。

Parameter_string:='';

If B<>'' then Parameter_string:='B = :B,'

Query_text:='MERGE ...'
            '...'
            'UPDATE SET A = :A, '+Parameter_string+' C = :C' ....

... B が空白の場合、パラメーターはクエリに「リスト」されないという考えです。

これが機能しないか、私の実装が機能しません (理由はわかりませんが、明らかにどこかでステップが欠落しています)。

とにかく、作業コード:

Query_text:='MERGE ...'
            '...'
            'UPDATE SET A = :A, B = :B, C = :C' ....

SQL_dataset.CommandType:=ctQuery; 
SQL_dataset.CommandText:=Query_text;

If B<>'' then
begin
  SQL_dataset.ParamByName('B').AsString:='B';
end
else
begin
  SQL_dataset.ParamByName('B').DataType:=ftString;
  SQL_dataset.ParamByName('B').Value:=Null;
end;
4

3 に答える 3

0

通常のアプローチでは、クエリごとに 1 回パラメーターを使用し、適切なデータ型を割り当てます。値は NULL に割り当てることができます。

var
 Query_text:String;
begin
  Query_text:='Declare @A varchar(100) ' // or e.g. integer
       +#13#10'Declare @B varchar(100)'  
       +#13#10'Select @A=:A'
       +#13#10'Select @B=:B'
       +#13#10'Update Adressen Set Vorname=@A,Strasse=@B where Name=@B';
  SQL_dataset.CommandType := ctQuery;
  SQL_dataset.CommandText := Query_text;
  SQL_dataset.Params.ParseSQL(SQL_dataset.CommandText,true);
  Showmessage(IntToStr(SQL_dataset.Params.Count));
  SQL_dataset.ParamByName('B').DataType := ftString;
  SQL_dataset.ParamByName('B').Value := 'MyText';
  SQL_dataset.ParamByName('A').DataType := ftString;  // or e.g. ftInteger
  SQL_dataset.ParamByName('A').Value := NULL;
  SQL_dataset.ExecSQL;
end;
于 2013-06-11T12:05:51.780 に答える