【问题标题】:TADOQuery : Passing null as parameter and getting the resultsetTADOQuery : 将 null 作为参数传递并获取结果集
【发布时间】:2017-10-27 08:24:22
【问题描述】:

我正在研究 Delphi7 和 SQlserver 2008 R2。 我有一个表格,上面有一些数据,如下所示。\

CREATE TABLE dbo.tstTable (
    ID int IDENTITY(1,1) PRIMARY KEY,
    Name varchar(255) NOT NULL,
    Eid int null,
    Pid int null
);

insert into tstTable(Name,Eid,Pid) values ('name1',1,null);
insert into tstTable(Name,Eid,Pid) values ('name2',2,null);
insert into tstTable(Name,Eid,Pid) values ('name3',3,null);
insert into tstTable(Name,Eid,Pid) values ('name4',null,4);
insert into tstTable(Name,Eid,Pid) values ('name5',null,5);
insert into tstTable(Name,Eid,Pid) values ('name4',null,6);
insert into tstTable(Name,Eid,Pid) values ('name7',null,null);

现在我想获取 Eid 等于 1 的记录。在 sql server 中我能够得到结果。

当我在 delphi 中尝试相同的操作时,我没有得到任何结果。 在 Delphi 中,我使用了 TADOConnection、TADOQuery、TDataSource 和 TDBGrid。

SET TADOQuery.Query = 'select Name from tstTable where Eid=:Eid and Pid =:Pid'

  with ADOQuery1 do
  begin
    Parameters.ParamByName('Eid').Value := 1;
    Parameters.ParamByName('pid').Value := NULL;//i tried with Unassigned also
    Close;
    open;
  end; //with

当我打开 AdoQuery 时,在网格中它没有显示任何记录。 下面的代码也没有返回任何记录。

  with ADOQuery1 do
  begin
    Parameters.ParamByName('Eid').Value := NULL;
    Parameters.ParamByName('pid').Value := NULL;//i tried with Unassigned also
    Close;
    open;
  end; //with

如何处理这种情况?

【问题讨论】:

  • 使用AND Pid IS NULLNULL 不是一个值。这是一种没有价值的状态。
  • @Victoria:我试过了。当我想传递所有参数为空时它失败了。当我们有类似“insert into tstTable(Name,Eid,Pid) values ('name7',null,null);”这样的记录时
  • where something = null 只是不起作用。只有 ISIS NOT 可以在将某些内容与 null 进行比较时返回 true。其他运算符始终返回 false。你说它在 SQL Server 中工作,但它没有。您正在那里执行不同的查询,其中(可能)省略了整个条件。
  • 你能再测试一下吗?屏幕截图中的查询应该返回结果。也许您没有运行完整的查询,或者您使用的工具执行了一些魔术,但该查询原样不应返回任何内容。这是 SQL 的基本规则,通常您需要stuff like this 来解决它。
  • 也许您的SET ANSI_NULLS 在SSMS 中设置为OFF?您可以使用它来使用带有 null 的 =<> 运算符,但我不推荐它,因为在未来的版本中,ANSI_NULLS 将始终为 ON。按照已经建议使用IS NULL

标签: sql-server delphi delphi-7 ado


【解决方案1】:

我可以说,如果 SET ANSI_NULLSON,则您在图像中提供的查询返回 (0) 行:

你可以尝试使用设置为OFF:

procedure TForm1.Button1Click(Sender: TObject);
begin
  ADOQuery1.SQL.Clear;
  ADOQuery1.SQL.Add('SET ANSI_NULLS OFF;');     
  ADOQuery1.SQL.Add('select Name from tstTable where Eid=:Eid and Pid =:Pid');
  ADOQuery1.Parameters.ParamByName('Eid').Value := 1;
  ADOQuery1.Parameters.ParamByName('pid').Value := NULL;
  ADOQuery1.Open;    
end; 

测试于:Delphi V7 (Build 4.453)。

【讨论】:

  • 您不必将 SET ANSI_NULLS OFF 作为单独的命令发送,只需将其放在“select”语句之前,该语句也可以工作并为您节省额外的命令
【解决方案2】:

您不应该为参数分配任何东西,而是将其清除以将其设置为 NULL

Parameters.ParamByName('Eid').Clear;

更新。不幸的是,这不适用于 TADOxxx 组件,因为 TParameter 没有 Clear() 方法。

所以解决办法

  ADOQuery1.SQL.Add('SELECT * FROM mytable');
  ADOQuery1.SQL.Add('WHERE mycol = :Param1 OR (:Param1 IS NULL AND mycol IS NULL)';
  ADOQuery1.Parameters.ParamByName('Param1').Attributes :=
    ADOQuery1.Parameters.ParamByName('Param1').Attributes + [paNullable];
  ADOQuery1.Parameters.ParamByName('Param1').Value := Null();
  ADOQuery1.Open;

使用 Delphi 7/SQL Server 2014 测试正常

由于兼容性问题和全局会话范围,请尽量不要更改任何 SET ANSI_XXX 设置。如果您确实需要更改会话默认设置,请在连接开始时进行。在查询之前执行SET ANSI_NULLS OFF 时,这将更改整个会话(连接)的设置。

【讨论】:

  • TADOQuery 没有 TParameter.Clear 方法。
  • 没错,ADO 组件不存在 Clear()。我添加了解决方案。
  • 我的解决方案适合您吗?我看到上面的解决方案需要更改全局 ANSI 设置。 Parameter.Clear() 是将其值设置为 NULL 的推荐方法。您应该始终正常使用它。
猜你喜欢
  • 1970-01-01
  • 2018-11-10
  • 1970-01-01
  • 1970-01-01
  • 2020-08-01
  • 2018-10-17
  • 2016-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多