5

我正在尝试将空值传递给 TSQLDataset 参数。查询具有以下形式:

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 可以为空,但也是一个外键。如果用户在此字段中输入内容,则 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 Server 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

3

关于什么:

SQL_dataset.ParamByName('B').Clear;

于 2013-06-11T17:14:05.397 回答
2

如果我没记错的话,Delphi 中的 db-null 等效项是 Variants.Null

于 2013-06-11T11:36:32.547 回答
0

通常的方法是每次查询使用一次参数并分配适当的数据类型。可以将值分配给 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 回答