5

I am trying to pass in a null value to a TSQLDataset parameter. The query has the form:

Query_text:='MERGE INTO [Table] 
             USING (VALUES (:A,:B)) AS Source (Source_A, Source_B)
             ....
             WHEN MATCHED THEN 
             UPDATE SET A = :A
             WHEN NOT MATCHED THEN
             INSERT(A, B) VALUES (:A,:B);

SQL_dataset.CommandType:=ctQuery; 
SQL_dataset.CommandText:=Query_text;

SQL_dataset.ParamByName('A').AsString:='A';  
SQL_dataset.ParamByName('B').AsString:={ COULD BE NULL, OR A STRING };    

SQL_dataset.ExecSQL;

Parameter B is nullable, but is also a foreign key. If the user enters something in this field, then B must be validated against values in another table. If it is blank then I want it to be ignored. I was passing in '', but this obviously produces a FK violation error.

I tried:

SQL_dataset.ParamByName('B').Value:=Null;

..but then I get a "dbexpress driver does not support the tdbxtypes.unknown data type" error.

I also tried:

SQL_dataset.ParamByName('B').DataType:=ftVariant;
SQL_dataset.ParamByName('B').Value:=Null;

..but then got "dbexpress driver does not support the tdbxtypes.variant data type" error.

Not sure what I am doing wrong, any help would be appreciated. I am currently drawing up a parameter list based on whether the string is populated or not, and this works well; it's just a bit clunky (in my actual query) as there are quite a few parameters to validate.

I am using Delphi XE4 and SQL server 2012.

Update:

Thanks for all the help, your suggestions were right all along, it was something else that produced that 'dbexpress driver' error. I was creating a 'flexible' parameter list in an effort to get around my problem, and this caused the exception:

Parameter_string:='';

If B<>'' then Parameter_string:='B = :B,'

Query_text:='MERGE ...'
            '...'
            'UPDATE SET A = :A, '+Parameter_string+' C = :C' ....

... the idea being that if B is blank then the parameter won't be 'listed' in the query.

This doesn't work, or my implementation of it doesn't work (not sure why, I'm obviously missing a step somewhere).

Anyway, the working code:

Query_text:='MERGE ...'
            '...'
            'UPDATE SET A = :A, B = :B, C = :C' ....

SQL_dataset.CommandType:=ctQuery; 
SQL_dataset.CommandText:=Query_text;

If B<>'' then
begin
  SQL_dataset.ParamByName('B').AsString:='B';
end
else
begin
  SQL_dataset.ParamByName('B').DataType:=ftString;
  SQL_dataset.ParamByName('B').Value:=Null;
end;

3 Answers 3

3

what about:

SQL_dataset.ParamByName('B').Clear;

Sign up to request clarification or add additional context in comments.

2 Comments

I had read that suggestion elsewhere, but I get the "dbExpress driver does not support the TDBXTypes.UNKNOWN data type. Vendor error message:" error when I try that. Am I doing something else wrong?
Strange... currently I'm migrating from FIB+ to FireDAC and I tested it on both connectivities and it is possible to use either Clear or Value := null assignment. And I'd expect that it works on each dataset. At least I've never met a problem with this, but I never used dbExpress.
2

If I recall correctly, the db-null equivalent in Delphi is Variants.Null

Comments

0

Usual approach would be using parameters once per query and assign the appropriate datatype. Value may be assigned to NULL.

var
 Query_text:String;
begin
  Query_text:='Declare @A varchar(100) ' // or e.g. integer
       +#13#10'Declare @B varchar(100)'  
       +#13#10'Select @A=:A'
       +#13#10'Select @B=:B'
       +#13#10'Update Adressen Set Vorname=@A,Strasse=@B where Name=@B';
  SQL_dataset.CommandType := ctQuery;
  SQL_dataset.CommandText := Query_text;
  SQL_dataset.Params.ParseSQL(SQL_dataset.CommandText,true);
  Showmessage(IntToStr(SQL_dataset.Params.Count));
  SQL_dataset.ParamByName('B').DataType := ftString;
  SQL_dataset.ParamByName('B').Value := 'MyText';
  SQL_dataset.ParamByName('A').DataType := ftString;  // or e.g. ftInteger
  SQL_dataset.ParamByName('A').Value := NULL;
  SQL_dataset.ExecSQL;
end;

2 Comments

Thanks, I tried this, get same error as noted above in comment to @pf1957. Mayve I have something else that's casung this error?
in my experiance this is the correct way for xe series.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.