ClientDataset.RefreshRecord no longer works in Delphi XE for joined tables - any workarounds? - sql

TClientDataset.RefreshRecord no longer generates the table join part of SQL when trying to refresh a record on a ClientDataset connected to a dataset with a joined table in the SQL statement.
As a result, calling this method results in SQL error "invalid column names" for each field not in the main table.
This was not a problem in Delphi 2010 and earlier.
The error occurs with both DBX4 or BDE components connected to the TClientDataset and thus it is highly likely the issue is a problem with changes to TClientDataset code.
To replicate this problem:
Create a new app in Delphi XE with only a single form and drop the required database components on it (TSQLMonitor, TSQLConnection, TSQLQuery, TDatasetProvider, TClientDataset, TDatasource, and TDBGrid) and bind them to each other.
Created a simple SQL statement with a table join and placed this in the TSQLDataset.SQL property.
The SQL statement included just two fields - the key field of the main table, and a field from a joined table - for example in pseudocode:
Select
MainTable.IntegerKeyField
, JoinedTable.JoinField
FROM MainTable
LEFT OUTER JOIN JoinedTable ON MainTable.LookupFieldID = JoinedTable.JoinKeyField
Add both of these fields as persistent fields in both TSQLQuery and TClientDataset with Provider Flag for the key field including pfInKey (RefreshRecord will not work if it does not know which field is the key hence persistent fields is a must).
Add two buttons on the form - one just opens the Clientdataset and the 2nd button calls clientdataset.refreshrecord;
Run the app, press button to open dataset and data displays in the grid.
Press the Refresh Record button, and you will get SQL error "invalid column name" for the joined field.
Close the app, open the SQLMonitor log and in the refresh record SQL statement that Delphi generated, you will see it has not included the table join statement.
====
I would really appreciate any ideas on how to fix this.

Try using a view on the database to implement the required join. Then the delphi component can just select from view_name rather than have to handle the join itself.

Related

I get this error "Optimistic concurrency control error" when I want edit a SQL Server view

I have two tables table_1 and Table_2; I created this view in SQL Server:
SELECT dbo.Table_1.ID, dbo.Table_1.Title, dbo.Table_2.Descc
FROM dbo.Table_1
LEFT OUTER JOIN dbo.Table_2 ON dbo.Table_1.ID = dbo.Table_2.ID
But when I want to enter data into Descc column, I get an error
Optimistic concurrency control error
This issue occurs if the following conditions are true:
The table contains one or more columns of the text or ntext data type.
The value of one of these columns contains the following characters:
Percent sign (%)
Underscore (_)
Left bracket ([)
The table does not contain a primary key.
Note This issue also occurs when you try to use Table Designer in Microsoft Visual Studio 2005 to update a table that is in a SQL Server 2005 database.
Workaround
To work around this issue, create a new query window in SQL Server Management Studio. Then, run a SQL UPDATE statement to update the row in the table.
Note If you receive the first error message that is mentioned in the "Symptoms" section, you can click Yes to update the row.
microsoft link

Why does this dropdown form filter work on a native table but not an ODBC linked table?

I'm transitioning an Access user app from using native Access tables to using ODBC-linked SQL Server tables.
I have a set of forms that are filtered by a selection from a dropdown (in a stand-alone selection form). By design, if the user leaves the dropdown blank the form launches unfiltered.
All of this works with the native tables, but when I try it using the linked tables I get an ODBC--call failed error
The SQL query Access generated for the query I'm using as the Record Source of the form that is filtered is:
SELECT linked.ASSIGNED_CARE_COORDINATOR, [rest of the variables]
WHERE (((linked.ASSIGNED_CARE_COORDINATOR)=[Forms]![frmCoord_Selector]![cmbCoords]))
OR (((([linked].[ASSIGNED_CARE_COORDINATOR])
Like [Forms]![frmDeadline_Report_Coord_Selector]![cmbCoords]) Is Null));
I know the ODBC connection itself is fine; if I remove the code after OR the query works with the linked table, but of course doesn't have the show-all-if-null functionality.
Why would this work with a native table but not the linked version of the exact same table?
The problem is the LIKE in the OR clause, but Access can apparently run that strange code on native tables. The correct code that will result in the desired behavior regardless of linked or native table is thus:
SELECT linked.ASSIGNED_CARE_COORDINATOR, [rest of the variables]
FROM linked
WHERE ((linked.ASSIGNED_CARE_COORDINATOR)=[Forms]![frmCoord_Selector]![cmbCoords])
OR [Forms]![frmCoord_Selector]![cmbCoords] Is Null

Update multiple records in SQL from Access without error "The data has been changed"

I am working with an ODBC connection between Access 2013 front end and a SQL Server 2008R2 back end. I have both “Datasheet” and “Continuous” forms that display multiple records which are sorted on an “order” field (integer).
The record source of these forms is a query (an Access local query right now, but I don’t think that switching it to a SQL Server view will solve my problem). Users use these forms to set/update the order of their records for reporting purposes.
My problem: the forms are updateable, but keep throwing the error
The data has been changed. Re-edit the record.
I know this error can be solved by setting the respective form to re-query after every update, but that is equally frustrating to the user because then their records are constantly re-sorting on them as they are trying to set the order (and the form "blips" after every entry).
(I have the field "Timestamp" in all my tables. I know a similar error is raised if one does not have this field in a SQL BE database linked to an Access FE.)
What is the best way to allow the users to update the order of all their records without the form resorting on them? (I would like to keep the “sort” in the query on the “order” field so when they open the form next time it displays the records in the order they specified.) I’ve read about using unbound forms with a stored procedure to update the SQL data, but this seems to be useful for one record at a time. Could I use a temp local table, and then do a batch update with a stored procedure? If that is the best answer, I also ask for some example code to get me headed in the right direction. :)
A simple answer! Add Me.Refresh to the AfterUpdate event on the form or subform. Then when a user does want to update the form based on their new order, they can click a "refresh" button that is set to Me.Requery or Me.Parent.Requery depending on the form or subform, respectively.

ADO Updateable Queries - error when a one of the joined tables has no record

I use the 'updateable query' feature of ADO, being able to select a dataset from several tables and criteria and display it in a grid or some other UI for the user to browse and edit.
However, and I'm surprised I've not hit this problem before now, when one of the joined tables doesn't have a record for the (master) key, and the user tries to edit a field in that table, ADO gives the famous "Row cannot be located.." error on post.
As far as I understand this error, the ADO driver is trying to locate the record in order to update its fields - and, of course, in this instance, there is no record to find. What I was expecting in these circumstances would be that the ADO driver would issue the equivalent of an UPDATE query for the main table, but an INSERT query for the subsidiary table.
Has anyone else come across this problem and found a workround?
The ADO driver used is the Jet 4.0 OLE DB Provider connecting to an Access (mdb) database.
I have ensured that the primary keys fields for both tables are available in the query dataset for the driver to utilise.
Here is a basic version of the SQL I have using:
SELECT
Table1.CustomerNo, Table1.Field1, Table1.Fieldn,
Table2.CustomerNo, Table2.Field1, Table2.Fieldn
FROM
Table1
LEFT JOIN Table2
ON Table1.CustomerNo = Table2.CustomerNo
WHERE
Table1.CustomerNo = Newcode;
As an experiment, I tried the same thing in MS Access 2007, and that worked, so there maybe a solution within ADO (but then Access is probably using a different driver).
In the end, I went for the 'hack' solution. The updateable ADO query over 2 tables would only work if
the customer's reocrds existed in both tables. So, I had to check that, and if the relevant record was missing from table2, had to insert it first, before calling the main query. Here is the code:
//Query customer account - open query from Table1 and Table2 tables
TwoTableQuery.Close;
//
//SELECT Table2.CustomerNo
// FROM Table2
//WHERE (Table2.CustomerNo = CustomerCode);
Table2Query.Close;
Table2Query.Parameters[0].Value := CustomerCode;
Table2Query.Open; /
//does the Table2 record exist for this customer?
if Table2Query.RecordCount = 0 then
begin //no, so create a new record
Table2Query.Insert;
Table2Query.FieldByName('CustomerNo').AsString := CustomerCode;
Table2Query.Post;
Table2Query.Close;
end;
//okay, now okay to open main query
TwoTableQuery.Parameters[0].Value := CustomerCode;
TwoTableQuery.Open;
It's not efficient, and also creates records (in Table2) that may not be needed. But it seems the only solution.
First try the locate function to make sure both fields are there. Make a parameter equal to the field if found and boolean true else update or insert new field with the value of the other one. After that you know the entry exists and you can join the fields...or you can use try except finally to first try and execute the statement except if the field is not found then finally create new entry. Put all of that in a repeat until and make sure the until statement uses locate on both tables to see if its found.

MS Access error "ODBC--call failed. Invalid character value for cast specification (#0)"

Does anyone have an idea what this error means or how to solve it? I am using Access 2003 and SQL2005. It comes up when trying to add a record on a particular subform.
[Microsoft][SQL Native Client] Invalid character value for cast specification (#0)
This MS bug report describes the same message, but it is a bug in SQL Server 6.5 that has already been solved.
Solved: Apparently having no PK on the destination table was causing this, it didn't have anything to do with the subform or the query from Access. I wasn't even aware there were tables in this database without PK. Adding PK to the destination table solved it. The strange thing is the same query string that errored when executed via SQL native client, executed through SSMS with no errors. Hope this helps anyone else who has come across that strange message.
Hum, I would check the text box default on the access side. I would also bring up the linked table in design mode, and you want to check the data type that ms-access assumes here. For non supported data types ms-access will generally use a string, and sql server might be wanting something else.
So, check both the Primary key (PK) in main table, and then check the data type used (assumed) in the child table for the foreign key (FK) column. While we are at this, check your expressions used for the child/master link settings in the sub-form control (not the form, not the sub-form, but the sub-form control used in your form that links up these two tables).
Sub forms in access are sensitive if you don’t have a timestamp column in the sql server table. As mentioned check the PK and the FK data types and make sure they match up (just bring up the tables in design mode in ms-access -- you get an error message about the design mode being read only, but just continue on so you can check/view to ensure the data types match up).
So for the child table, you need a PK, a FK, and also a timestamp column (you don’t have to display the TS column in the sub-form, but you need it in the table).
Sub-forms in ms-access are sensitive and often fail if you don’t include a timestamp column in the sql table. (access uses these row version columns to determine if the data been changed).
Is one of your fields in the view calculated/built with the CAST function? In this case, you might not have the right to update/add a value for that field.
Can you execute your view in the MS SQL Studio interface and try to insert a record?
Another cause to this issue is that if you change a table name without alterting the view then the "Dependencies" of that view still remians with the table old name.
Let say I have a table 'A' and a view 'Av' which derives from 'A', and I created a new Table which will be named 'A' and I changed 'A's name to 'A_old' but I didn't executed an ALTER VIEW, so the dependencies of 'Av' still remain on 'A_old' but the view is derives from 'A' and it cuasing this Error in Access when trying to open the view as a linked table
I just spent a day battling this with an Access ADP project that was imported into a new Access 2016 ACCDB file. Initially I figured it was an issue with the application code, but I was getting this keying records directly into the table. Interestingly, the records always got written - it seemed to be the read-back that was triggering the error. Profiling the insert sql and running that from SQL Management Studio worked without any issues.
The table that was causing the problems had a GUID Primary Key. Switching that to an int column resolved the issue.
The SQL database was also littered with a few thousand extended properties which I removed before switching the PK. There was a strong suggestion from the web that these cause problems. The source of that process is documented here: Remove All SQL Extended Properties
I had this problem with Access 2016 trying to update an ODBC linked sQL Server database. Problem was a null value in field used to join the two tables. Eliminating the null value solved the problem
OK I just had this bad experience and it had nothing to do with PK or any of this stuff in my situation. The view that reported this problem in Access was created in SQL Server originally and used a CAST of DATETIME to plain old DATE to get rid of the unneeded time part. Up until today this view had caused 0 issues in Access, but started to generate heartburn just as described above.
So, I generated a Drop/Create script for the MSS view, ran it, relinked the views in Access, and the Access database was happy with the result. All my so-called tables in Access are basically views through links to MSS for reporting. I only have 1 table that actually does changes. Other than that, I do not edit through views in Access.
The message is of course useless as usual but this was my solution in my situation.
Based solely in the message you provided above, it appears that you are trying to set an invalid value to some field or parameter, etc... The message is telling you that it is trying to convert a value into an specific data type but the value is invalid for that data type... makes sense?
Please add more details so we can help you better.