如何将空值显式插入到参数化查询中?

15 delphi firebird

我正在使用Delphi 7和Firebird 1.5.

我有一个在运行时创建的查询,其中一些值可能为null.我无法弄清楚如何让Firebird接受我需要保留为null的值的显式空值.在这个阶段,我正在构建SQL,以便我不包含null的参数,但这很乏味且容易出错.

var
  Qry: TSQLQuery;
begin
  SetConnection(Query); // sets the TSQLConnection property to a live database connection
  Query.SQL.Text := 'INSERT INTO SomeTable (ThisColumn) VALUES (:ThisValue)';
  Query.ParamByName('ThisValue').IsNull := true; // read only, true by default
  Query.ParamByName('ThisValue').Clear; // does not fix the problem
  Query.ParamByName('ThisValue').IsNull = true; // still true
  Query.ParamByName('ThisValue').Bound := true; // does not fix the problem
  Query.ExecSQL;
Run Code Online (Sandbox Code Playgroud)

目前在DB.pas中引发了EDatabaseError"参数'ThisValue'''没有值,所以我怀疑这是设计而不是火鸟问题.

我可以将参数设置为NULL吗?如果是这样,怎么样?

(编辑:抱歉没有明确关于尝试.清除之前.我把它留下来支持提到IsNull.已添加声明和更多代码)

对不起,还有一件事:表上没有"NOT NULL"约束.我认为它没有那么远,但我想应该说.

完整的控制台应用程序,显示我的问题:

program InsertNull;

{$APPTYPE CONSOLE}

uses
  DB,
  SQLExpr,
  Variants,
  SysUtils;

var
  SQLConnection1: TSQLConnection;
  Query: TSQLQuery;
begin
  SQLConnection1 := TSQLConnection.Create(nil);

  with SQLConnection1 do
  begin
    Name := 'SQLConnection1';
    DriverName := 'Interbase';
    GetDriverFunc := 'getSQLDriverINTERBASE';
    LibraryName := 'dbexpint.dll';
    LoginPrompt := False;
    Params.clear;
    Params.Add('Database=D:\Database\ZMDDEV12\clinplus');
    Params.Add('RoleName=RoleName');

    //REDACTED Params.Add('User_Name=');
    //REDACTED Params.Add('Password=');

    Params.Add('ServerCharSet=');
    Params.Add('SQLDialect=1');
    Params.Add('BlobSize=-1');
    Params.Add('CommitRetain=False');
    Params.Add('WaitOnLocks=True');
    Params.Add('ErrorResourceFile=');
    Params.Add('LocaleCode=0000');
    Params.Add('Interbase TransIsolation=ReadCommited');
    Params.Add('Trim Char=False');
    VendorLib := 'gds32.dll';
    Connected := True;
  end;
  SQLConnection1.Connected;
  Query := TSQLQuery.Create(nil);
  Query.SQLConnection := SQLConnection1;
  Query.Sql.Text := 'INSERT INTO crs_edocument (EDOC_ID, LINKAGE_TYPE) VALUES (999327, :ThisValue)';
  //Query.ParamByName('ThisValue').IsNull := true; // read only, true by default
//  Query.ParamByName('ThisValue').Value := NULL;
  Query.ParamByName('ThisValue').clear; // does not fix the problem
  Query.ParamByName('ThisValue').Bound := True; // does not fix the problem
//  Query.ParamByName('ThisValue').IsNull; // still true
  Query.ExecSQL;
end.
Run Code Online (Sandbox Code Playgroud)

Ser*_*yuz 10

错误的原因是'dbx'不知道参数的数据类型.由于永远不会赋值,因此它的数据类型是ftUnknown执行时间,因此是错误.'ParamType'也是一样,但默认情况下假设'ptInput',所以没问题.

  Query.ParamByName('ThisValue').DataType := ftString;
Run Code Online (Sandbox Code Playgroud)


绝对不需要Clear参数,因为它已经存在了NULL.我们怎么知道呢?IsNull正在回归......

来自TParam.Clear方法:

使用"清除"为参数指定NULL值.

TParam.IsNull财产:

指示分配给参数的值是否为NULL(空白).


绝对不需要Bound参数,因为它完全无关紧要.当'Bound'为false时,数据集将尝试从其参数的数据源提供默认值.但是您的数据集甚至没有链接到数据源.从文档:

[...]表示查询和存储过程的数据集使用Bound的值来确定是否为参数指定默认值.如果Bound为false,则表示查询的数据集将尝试从其DataSource属性指示的数据集中分配值.[...]

如果文档不够,请参阅TCustomSQLDataSet.SetParamsFromCursor'sqlexpr.pas'中的代码.它是dbx框架中引用参数"Bound"的唯一位置.


awm*_*oss 9

使用 TParam.Clear

Query.ParamByName('ThisValue').Clear;
Run Code Online (Sandbox Code Playgroud)

"使用Clear为参数分配NULL值." (来自文件)

  • @RRUZ:我已经尝试过了.IsNull在我打电话给Clear之前是真的,之后更真实.错误仍然存​​在. (2认同)