I'm reading data from an .mdb file (MSAccess 2000 format). There are some tables that have colons in their names. I'm getting an exception when I try to open queries on these tables:
EOleException with message 'Parameter object is improperly defined. Inconsistent or incomplete information was provided'.
this is my code:
procedure TForm1.Button1Click(Sender: TObject);
var
Query: TADOQuery;
begin
Query := TADOQuery.Create(nil);
Query.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;'+
'Data Source=DB.mdb;Persist Security Info=False';
Query.SQL.Text := 'select * from [Table1:1]';
try
Query.Open;
finally
Query.Free;
end;
end;
If your colon is a cast like SELECT reltuples::BIGINT then you can rewrite it as a cast(reltuples as BIGINT) to avoid the colons.
CREATE TEMP FUNCTION InsertColons(s STRING) AS ( CONCAT(SUBSTR(s, 1, 2), ':', SUBSTR(s, 3, 2), ':', SUBSTR(s, 5, 2)) ); SELECT s, InsertColons(s) AS result FROM ( SELECT '123456' AS s UNION ALL SELECT '170519' );
The colon (:) is used to select "slices" from arrays. (See Section 5.12.) In certain SQL dialects (such as Embedded SQL), the colon is used to prefix variable names. The asterisk (*) has a special meaning when used in the SELECT command or with the COUNT aggregate function.
To select a column name with spaces, use the back tick symbol with column name. The symbol is ( ` `). Back tick is displayed in the keyboard below the tilde operator ( ~).
TQuery
will interpret the :
if ParamCheck = true
.
Set ParamCheck:= false
and then set the SQL.Text
.
procedure TForm1.Button1Click(Sender: TObject);
var
Query: TADOQuery;
begin
Query := TADOQuery.Create(nil);
Query.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;'+
'Data Source=DB.mdb;Persist Security Info=False';
Query.ParamCheck:= false;
Query.SQL.Text := 'select * from [Table1:1]';
try
Query.Open;
finally
Query.Free;
end;
end;
Now it works.
Combining coloned table/column names and parameters
If you absolutely must go down the path of using table/column names with colons in them and still want to use params elsewhere in your query then you can use a macro to fill in the table/column name.
This requires FireDac though.
I do recommend you be very careful with this because unlike parameters macro's are not safe against SQL injection!
See: http://docwiki.embarcadero.com/CodeExamples/Seattle/en/FireDAC.TFDQuery.Macros_Sample
I was checking solutions in other languages. However Johan's answer seems to be the right one, but the one posted here also works in Delphi/Access case:
Using backticks ` around your tablename should allow it to be ignored by the param check.
Query.SQL.Text := 'select * from `Table1:1`';
This one also can be combined with using parameters in query string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With