I am creating a temp table in SQL and then adding a new field to it. It seems Firedac is caching the field list for this temp table.
The following code gives me "FDQuery5: Field 'Available' not found."
FDQuery5.Connection := FDConnection1;
FDConnection1.ExecSQL('Select StockNo into #Temp from Stock');
FDQuery5.SQL.Text := 'Select * From #Temp';
FDQuery5.open;
FDConnection1.ExecSQL('Alter Table #Temp add Available Char(1)');
FDQuery5.Close;
FDQuery5.open;
ShowMessage(FDQuery5.FieldByName('Available').AsString);
using XE5 with Firedac.
I have tried Connection.RefreshMetadataCache and I have removed fiMeta from FetchOptions.Cache.
I can get Firedac to recognise the new field if I modify the SQL.Text. This is undesirable as my application will need modifying in quite a few places.
The query remains prepared after you call FDQuery5.Close. That means, it caches also result set structure. To prepare the query replace FDQuery5.Close with FDQuery5.Disconnect.
Related
I am working on a simple database application in Delphi using FireDAC and SQLite3. Whenever I insert a new record into the database, the date format that is shown on my form is always in the format of yyyy-mm-dd and once I close and reopen the application the format changes to m/d/yyyy which is the format I was expecting and wish to always be displayed without closing and reopening my application.
The Definition Parameters and Options for the FireDAC connection are all at their default values. The DataType set for the field that holds the date in the SQLite3 database is set to DATE. Finally, the code I use to insert the record is below.
Qry.SQL.Text := 'INSERT INTO employees (HireDate) VALUES (:HiredOn)';
Qry.ParamByName('HiredOn').AsDate := DateTimePicker1.Date;
Qry.ExecSQL;
Qry.Open('SELECT * FROM employees');
Any help would be appreciated.
Make sure that any format settings for the date field in the underlying BindingSource / List / Adapter matches that of the form/grid field. It might be that the underlying binding formatting for the field is overriding your new settings for the form/grid field.
Set the format/display on your form field to "m/d/yyyy" and for good measure, *also do it through code in the InitializeGrid event handler
This is happening b/c when the date format on your form field doesn't match that in SQLite3 which is "yyyy-mm-dd". So you would need to set the format/display on your form field to match that.
Uses DateUtils ...
DateUtils.DateOf(DateTimePicker1.Date);
Try
FormatDateTime('dd/mm/yyyy', DateTimePicker1.Date);
I was using UniDac for a long time now and decided to move on to FireDac as it has good Asynch methods after moving on i saw that none of my data editing works anymore it gives me an error:
[FireDAC][Phys]-330. Cannot generate update query. Update table undefined.
What I am trying to do here is i have a TFDStoredProc component who gets all the data from the database and lets me edit it, with unidac I could easily edit the data without any problem like this:
StoredProc.Edit;
StoredProcCreatedID.Value := SomeValue;
StoredProc.Post;
and it worked, but with AnyDac it doesn't, I tried specifying manually the UpdateTable which leads to another problem:
[FireDAC][Phys][ODBC][Microsoft][SQL Server Native Client 11.0][SQL Server]Invalid column name 'CreatedID'.
I am using Microsoft SQL Server 2012 FireDac 8.0 and stored procedures for getting back results any ideas?
P.S.
The query looks like this
SELECT
CreatedBy as CreatedID,
usr.UserName as CreatedBy
FROM
Sales
LEFT JOIN
Users usr ON usr.ID = Sales.CreatedBy
it looks like the FireDac update builder doesn't recognize the aliases on the fields, any help would be appreciated.
Well i figured out what was the issue, it seems that if you specify a alias in the query for a field the Origin property will be set to the alias and not the real field i downloaded CNPack a must have for a delphi developer also its free, ran the component selector and changed all my aliased fields to their real fields and it works, but this is still a big issue in FireDac component because it doesnt recognize the aliased fields, lets hope it will be fixed in the future as to specify for every query what table it should update and what fields that just allot of work if you are migrating from a big project in my case 220+ stored procedures.
I have a DLL created in Delphi XE2 that is using DB Express and TClientDataSet to display the results of a join in a DB Grid. There is a simple function to launch/show the form that is exported for use in other applications. The query is executed, and the grid populated, on FormActivate.
When I call the function to show the form from a separate Delphi XE2 application, everything runs fine - no issues that I can find.
However, when I call the same function from a separate Delphi 7 application, I get an error that that TClientDataSet can't find fields from the join.
For Example, data is returned like this:
[dbxds == TSQLDataSet
cds == TClientDataSet]
dbxds.commandtext='select s.sfield1, s.sfield2, t.tfield1, t.tfield2 from s left join t on s.sfield1 = t.tfield1';
cds.Open;
cds.fieldByName(sfield2).visible:=false;//to hide from a dbgrid
cds.fieldByName(tfield2).visible:=false;//to hide from a dbgrid
When called from XE2, no issues.
When called from Delphi 7, the last line (used to hide that field from the db grid) gives an error that:
cds: Field 'tfield2' not found
Though the first line is fine - if I switch the order of the query so that that 't' fields are retrieved first ('from t left join s'), then I get the error on the 's' field instead.
Any thoughts on what could be causing the incompatibility?
Thanks!
OK so, I noticed something odd and that put me on the path to getting the answer to this.
It just happened that, in either table, the field I was trying to access to hide was of type 'tinyint(1)'. If I tried to hide a field of type int/varchar etc, no error was thrown.
I swapped my 'tinyint(1)' fields for 'int(1)' and it works fine.
No idea why this was happening, but I'm glad I caught it and, if any one else runs into this issue, I hope that this answers their question for them too.
I have a database table in which I need to insert records.
I'm using a updatable TClientDataset and everything works just fine.
Now, I need to add a dummy field; not a calculated one.
One field where I can write the row state (just some information I will use before ApplyUpdates) but that is not part of the database table.
I've seen this illuminating post, but the added field is calculated and it is not possible to update and keep informations.
It is not ok for me.
I've tried to add a 'dummy field' from the database select and fix the ProviderFlags to remove the pfUpdate.
cds.CommandText := 'SELECT 1 AS DUMMY , CUSTOMERS.* FROM CUSTOMERS';
cds.Open;
cds.FieldByName('DUMMY').ProviderFlags := [];
I've seen in the Provider.pas that before building the insert sql, the ProviderFlags is checked. This should work indeed, the problem is it seems that ProviderFlags is not updated from my statement above.
Please, do you know how to add a Field on the fly, that is writable but then ignored by the delphi database update process?
I'm using delphi 7.
Thanks for you help.
Make the field an InternalCalc field and set its ProviderFlags to []. This makes the field writable to your application, but skips the field when updating the underlying database.
I have the following query to one of my database tables:
select count(*) as mycount
from mytable
where fieldone = :fieldone
and fieldtwo = :fieldtwo
Parameters are correctly loaded into the query (both of type String).
When I run this query outside the app (for instance, through the dbexplore) and replace the parameters with the actual values, I get the correct result. But when running it in the app, I get a Field 'fieldtwo' not found error, right on the Query.Open call.
Why would the BDE not find this field, when it actually exist?
Update: The following query, executed right after the first one (the one that fails), works fine in the app:
select *
from mytable
where fieldone = :fieldone
order by fieldone, fieldtwo
The best guess is that you have populated the field list in the query, this overrides any concept of the underlying fields that are in the query and is a cause of countless confusion.
Right click on the query, pick the fields editor clear all the values that are there and then choose 'add all fields' that should cause the missing field to appear once the query is executed.
I think it should auto-populate the fields if there are no defined fields when the query is executed, so you may not need to choose 'add all fields' after clearing the fields.
Whenever we come across a problem like this we tend to remove the query from the form and create it dynamically at run time... It depends how ingrained into the form it is...
E.g. If you have a data aware control looking at "fieldtwo" which tries to fetch some data when the underlying data set gets updated then it'll trigger an error like this, but it's more obvious when you've written code such
SomeEdit.Text = Query.FieldByName("fieldtwo").AsString;
That way it falls over on the relevant line instead of the open (triggering a related event)
Clear the query content using Query1.SQL.Clear; statement before opening it.
Other reason can be you are opening other database which may not have the specified field. Be sure that both the DatabaseName's in your app and dbexplore are same
I used to face porblems with BDE when i have SQLExplorer open and the app accesses the DB at the same time (but i had errors like ), try closing the Explorer it may help, if not i would build the SQL as text without the Parameters and try if it works then (if its possible in your situation).
I don't use parameters, so I'm just grabbing at straws here. I still use the BDE regularly, but am no expert. I find I shy away from more complex expressions (which yours is not!) because of the little "surprises" like this that the BDE throws at you.
Perhaps adding parentheses:
where (fieldone = :fieldone)
and (fieldtwo = :fieldtwo)
Or, single or double quote signs (this probably will make it worse?)
where (fieldon = ":fieldone")
and (fieldtwo = ":fieldtwo")
Or, to explore the problem, remove the "and fieldtwo = :fieldtwo" line and see if it runs.
Would it be possible for you to do your own parameter substitution with a StringReplace as in
Query1.SQL.Text := StringReplace(Query1.SQL.Text, ":fieldone", "MyVarName",[rfReplaceAll ]);
If you are creating a ClienDataSet in memory by the Create DataSet method, you should check the TFieldDefs property, which must have a different field name or not created
I was having a weird but small problem, I'll post in case it will help someone in some day.
uRegPeople.pas
with frmEditPerson do
begin
PersonID := qryPerson.FieldByName(ID).AsInteger;
...
end;
I had qryPerson both in frmRegPeople and in frmEditPerson, by using with I was referencing to frmEditPerson.qryPerson, however I wanted to reference to frmRegPeople.qryPerson. Then I need to change to the following code.
with frmEditPerson do
begin
PersonID := Self.qryPerson.FieldByName(ID).AsInteger;
...
end;
// Explanation
// qryPerson --> frmEditPerson.qryPerson;
// Self.qryPerson --> frmRegPeople.qryPerson;