How to set a GUID as ADO query parameters from Delphi?
Question
MS Access allows the numeric type GUID (in German it's called 'Replikations-ID', so I guess in English that would be 'replication id') which is stored as a 16 byte binary field in the database.
I found how to access these fields in Delphi with TADOQuery/TADOTable using
(TheQuery.FieldByName('SomeGuidField') as TGUIDField).AsGuid;
But now I want to execute an SQL-Query like this:
SELECT * FROM SomeTable WHERE SomeGuidField=:AGuid
I tried setting a TADOQuery.SQL property to the above statement, but found no way to actually set the AGuid
parameter such that the query can be opened. Whatever I tried resulted in the (ADO/COM) error
No value given for one or more required parameters
For example:
TheQuery.ParamByName('AGuid').Value := QuotedString(GuidToStr(AGuid));
TheQuery.Open; // <<== crashes here
This doesn't work either:
TheQuery.ParamByName('AGuid').Value := GuidToStr(AGuid);
TheQuery.Open; // <<== crashes here
I had a look at how TGuidField(...).AsGuid
works and found that it first converts the GUID to a string and then the string to a variant (and vice versa).
It works fine, if I always generate the SQL-Statement like this:
SELECT * FROM SomeTable WHERE SomeGuidField='<a guid goes here>'
As I am passing that TADOQuery object around in the program I would like to only change the AGuid
-Parameter to keep most methods agnostic on the actual SQL-Statement.
Is there any other way to set a GUID-Parameter than always change the complete SQL-Statement?
(It must be a GUID because I need a globally unique identifier to synchronize with other databases which are MS SQL or MS Access based.)
Edit vradmilovic is right, this works:
TheQuery.ParamByName('AGuid').Value := GuidToStr(AGuid);
TheQuery.Open;
I don't understand why it didn't work the first time I tried it.
Solution
That's correct way to set parameters with ADO. The message you get is most probably due to typo with some of fields (you get same message if field does not exist).
OTHER TIPS
For what is worth I'm using GUIDs but I save them in DB as strings.
You should not save them as strings. You should use uniqueidentifier. The two functions to use are GUIDToString and StringToGUID (not the str-ones).
If you copy values from the active directory (comes as ftVarBytes) you can use assign which does the magic for you:
QueryIns.Parameters.ParamByName('GUID').Assign(Query.FieldByName('objectGUID'));
If you want to extract the objectGUID from AD you need to cast the objectGUID to uniqueidentifier:
Query.SQL.Add('select cast(objectGUID as uniqueidentifier) as objectGUID');
Query.SQL.Add('from vwADGroups');
Query.Open;
while not Query.Eof do begin
Index := List.IndexOfName(Query.FieldByName('objectGUID').AsString);
//...
end;
If you are sure the parameter is a TGuid, then the following should work :
TGuidField(TheQuery.ParamByName('AGuid')).AsGuid
Although this does a GuidToString internally, so the problem maybe the same. Worth a try!