Pergunta

I am converting a application from Delphi 5 to Delphi XE2 and came across a situation using the BDE.

In Delphi XE2 he does not accept pass null for a field that is a foreign key that follows is how this currently working in Delphi 5:

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

Error that occurs in Delphi XE2 with BDE: In the primary key value for foreign key 'XX' in table YY

Tested in the following ways with the same error:

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;

How to pass a field with null value?

UPDATE:

Database:

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;

Result: Key violation.

Foi útil?

Solução

To pass NULL as a parameter value, use TParameter.Clear.

ParamByName('id').Clear;

As an aside: You really should have gotten rid of the BDE by now. It's been deprecated for more than a decade now, it is difficult to configure and use on modern versions of Windows, and may simply disappear from the Delphi distribution without notice at any time. (I'm surprised this hasn't happened yet, personally.) It also does not support any of the cross-platform targets that are available now. Surely 10 years is long enough to have been able to replace it.

Outras dicas

When passing a NULL, you have to set Bound=True manually even when calling Clear(), and if it is the first time using the parameter than you usually have to set DataType manually as well. I tend to use code like this:

Param := ParamByName('id');
if (shound assign a value) then
begin
  Param.AsInteger := ...;
end else
begin
  Param.DataType := ftInteger;
  Param.Clear;
  Param.Bound := True;
end;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top