Delphi XE2:如何传递一个空值字段?

3

我正在将一个应用程序从Delphi 5转换到Delphi XE2,并遇到了使用BDE的情况。

在Delphi XE2中,如果字段是一个外键,它不接受传递null值。以下是目前在Delphi 5中正常工作的方式:

ParamByName('id').datatype: = ftInteger;

在 Delphi XE2 中使用 BDE 时出现的错误:

在表 YY 中的外键 'XX' 的主键值中发生了错误。

以下测试方式都出现了相同的错误:

ParamByName('id').datatype: = ftInteger;
ParamByName('id').value: = NULL;

ParamByName('id').DataType: = ftstring;
ParamByName('id').clear;

ParamByName('id').DataType: = ftstring;
ParamByName('id').Bound: = true;

ParamByName('id').Value: = null;

ParamByName('id').IsNull;

如何传递一个空值字段?
更新:
数据库:
CREATE TABLE TEST_1 (
    ID_1 INTEGER NOT NULL,
    ID_TEST_2 INTEGER NULL,
    DESC_1 VARCHAR(10) NULL,
    PRIMARY KEY (ID_1)
);

CREATE TABLE TEST_2 (
    ID_2 INTEGER NOT NULL,
    DESC_2 VARCHAR(10) NULL,
    PRIMARY KEY (ID_2)
);

ALTER TABLE TEST_1 ADD FOREIGN KEY FK_TEST(ID_TEST_2) REFERENCES TEST_2(ID_2);

Delphi XE2:

Close;
SQL.Clear;
SQL.Add('insert into test_1 (id_1, id_test_2, desc_1) values (:id_1, :id_test_2, :desc_1)');
ParamByName('ID_1').AsInteger := 1;
ParamByName('ID_TEST_2').DataType := ftInteger;
ParamByName('ID_TEST_2').Clear;
ParamByName('ID_TEST_2').Bound := True;
ParamByName('DESC_1').AsString := 'DESCRIPTION TEST';
ExecSQL;

结果:关键词冲突。

2个回答

8

如果要将参数值设置为NULL,请使用TParameter.Clear函数。

ParamByName('id').Clear;

顺便说一句:你真的应该现在就摆脱BDE了。它已经过时十多年了,难以在现代Windows版本上配置和使用,并且可能会在不经过通知的情况下从Delphi发行版中消失。 (就我个人而言,我很惊讶这件事还没有发生。)它也不支持现在可用的任何跨平台目标。 10年肯定足够长的时间来替换它了。


是的,我正在考虑在不久的将来更改BDE。错误仍然存在:字段“XX”是未知类型。但错误不在BDE中而是Delphi中。不插入空值,请插入空白。FreePascal中的相同讨论:http://free-pascal-general.1045716.n5.nabble.com/How-to-clear-the-value-of-a-field-in-a-table-using-parameters-td5716247.html - Leonardo Gregianin
这篇帖子中有相同的错误,使用Delphi XE4和Dbexpress:https://dev59.com/questions/iXPYa4cB1Zd3GeqPfy2C?rq=1 - Leonardo Gregianin
1
我发布的代码是有效的。如果你需要传递一个NULL或字符串,你需要使用if..else块,在其中使用AsString分配字符串或者在为NULL时使用Clear。我经常使用它,虽然不是与BDE一起使用。如果错误出现在Delphi中,请发布确切的错误信息。 - Ken White

1
当传递NULL时,即使在调用Clear()时,您也必须手动设置Bound=True。如果这是第一次使用该参数,则通常还需要手动设置DataType。我倾向于使用以下代码:
Param := ParamByName('id');
if (shound assign a value) then
begin
  Param.AsInteger := ...;
end else
begin
  Param.DataType := ftInteger;
  Param.Clear;
  Param.Bound := True;
end;

更新了主要问题,展示了我所做的测试和出现的关键违规错误。 - Leonardo Gregianin
完整的错误信息是什么?它应该告诉你到底违反了什么。键冲突可能由多种不同的原因引起。如果我必须猜测(而你永远不应该让人们猜测),我会猜测TEST_1已经包含一个在其ID_1字段中具有值为1的行,因为ID_1是主键,所以每行必须具有唯一值。 - Remy Lebeau
创建表后没有数据。在向表ID_TEST_1插入第一条记录时出现“键冲突”错误,因为该字段正在获取ID_TEST_2 EMPTY而不是NULL。Empty = 键冲突。 Null = 正确记录。 - Leonardo Gregianin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接