问题
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;
回答1:
what about:
SQL_dataset.ParamByName('B').Clear;
回答2:
If I recall correctly, the db-null equivalent in Delphi is Variants.Null
回答3:
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;
来源:https://stackoverflow.com/questions/17042429/passing-null-value-into-parameterized-delphi-sql-server-query