【问题标题】:Delphi XE2: How to pass a field with null value?Delphi XE2:如何传递具有空值的字段?
【发布时间】:2014-04-24 12:55:20
【问题描述】:

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

在 Delphi XE2 中,他不接受为作为外键的字段传递 null,以下是当前在 Delphi 5 中的工作方式:

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

在带有 BDE 的 Delphi XE2 中发生的错误: 在表 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);

德尔福 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;

结果: 密钥违规。

【问题讨论】:

    标签: delphi nullif


    【解决方案1】:

    要将NULL 作为参数值传递,请使用TParameter.Clear

    ParamByName('id').Clear;
    

    顺便说一句:您现在真的应该摆脱 BDE。它已经被弃用了十多年,很难在现代版本的 Windows 上配置和使用,并且可能随时从 Delphi 发行版中消失,恕不另行通知。 (我个人很惊讶这还没有发生。)它也不支持现在可用的任何跨平台目标。当然,10 年的时间足以取代它。

    【讨论】:

    • 是的,我正在考虑在不久的将来更改 BDE。错误继续:字段“XX”的类型未知。但错误不在 BDE 中,而是在 Delphi 中。 Null 不插入,插入空白。 FreePascal 中的相同讨论:free-pascal-general.1045716.n5.nabble.com/…
    • 这篇文章中的同样错误,使用 Delphi XE4 和 Dbexpress:stackoverflow.com/questions/17042429/…
    • 我发布的内容有效。如果您必须传递 NULL 或字符串,则需要一个 if..else 块,它可以使用 AsString 分配字符串,如果为 NULL,则使用 Clear。 (我一直都在使用它,虽然不是与 BDE 一起使用。如果错误出现在 Delphi 中,请发布您收到的确切错误消息。
    【解决方案2】:

    传递 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;
    

    【讨论】:

    • 更新了显示我所做的测试的主要问题,并且发生了密钥冲突错误。
    • complete 错误信息是什么?它应该告诉你到底违反了什么。 密钥违规可能由多种不同原因之一引起。如果我不得不猜测(你永远不应该让人们猜测),我会猜测 TEST_1 在其 ID_1 字段中已经包含一个值为 1 的行,因为 ID_1 是一个主键,所以每一行必须具有唯一值。
    • 创建表后没有数据。在表 ID_TEST_1 中插入第一条记录时发生“键冲突”错误,因为该字段正在获取 ID_TEST_2 EMPTY 而不是 NULL。空 = 密钥冲突。 Null = 正确记录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 2021-10-31
    相关资源
    最近更新 更多