dbExpress/No key specified
Asked Answered
B

2

7

I am working on a database program, using the dbExpress components (Delphi 7). The data is retrieved from the database via the following components: TSQLDataSet -> TDataSetProvider -> TClientDataSet -> TDatasource -> TDBEdit. Until now, the form has worked correctly. The query in the TSQLDataset is

select id, name, byteken, timeflag from scales where id = :p1

I added a large (2048) varchar field to the database table; when I add this field to the above query (and connect either a TDBMemo or a TDBRichEdit) to the TDatasource), I receive the following message when I try to edit the value in the new text field

Unable to find record. No key specified.

I get the same error when there is no TDBMemo on the form (but with the varchar field in the query). As soon as I remove the varchar field from the query, everything works properly again.

What could be the cause of this problem?

==== More information ====

I have now defined persistent fields in the form. The field which holds the key to the table has its provider flags set to [pfInUpdate,pfInWhere,pfInKey], whereas all the other fields have their flags as [pfInUpdate,pfInWhere]. This doesn't solve the problem.

The persistent fields were defined on the clientdataset. When I defined them on the TSQLDataSet, the error message about 'no key specified' does not occur. The program still puts out this error message (which I neglected to mention earlier):

EDatabase error: arithmetic exception, numeric overflow or string truncation

The large string field has the correct value in 'displaywidth' and 'size'.

==== Even more information ====

I rewrote the form to use non-data aware components. One query retrieves the data from the database (using exactly the same query string as I am using in the TSQLDataSet); the data is then transferred to the controls. After the user presses the OK button on the form, the data is passed back to the database via another query which performs an update or an insert. As this works correctly, I don't see what the problem is with the data aware components.

==== Yet another snippet of information ====

I found this question on Stack Overflow which seems to address a similar issue. I changed the query to be

select id, name, name, byteken, timeflag, 
cast (constext as varchar (2048)) as fconstext
from scales
where id = :p1

and set the dbMemo's datafield to be 'fconstext'. After adding text to the dbMemo, the 'applyupdates' call now fails with the following message

column unknown 'fconstext'

despite the fact that there is a persistent field created with that name.

I don't know whether this helps or simply muddies the water.

==== More information, 23 April ====

I dropped the field from the database table, then added it back. The program as written works fine as long as the string being entered into the problematic data field is less than about 260 chars. I added ten characters at a time several times without problem until the string length was 256. Then I added some more characters (without counting), tried to save - and got the error. From this point on, trying to add even one more character causes the error message (which comes at the 'applyupdates' method of the clientdataset).

Originally, the field contained 832 characters, so there is not a hard limit to the number of characters which I can successfully store. But once the error message appears, it always appears, as if the database remembers that there is an error.

==== More information, 24 April ====

Once again, I dropped the field from the database then added it back; the character set is WIN1251, for reasons which are not clear to me now (I don't need Cyrillic characters). The maximum number of characters which I can enter using data-aware controls seems to be about 280, regardless of how the field itself is defined.

I have since moved to using non-data aware controls in the real program where this problem occurs, and I can assure you that this limit does not exists there. Thus I am fairly sure that the problem is not due to a mismatch in character size, as has been suggested. Don't forget that I am using Delphi 7, which does not have unicode strings. I think that there is a bug in one of the components, but as I'm using old versions, I imagine that the problem has been solved, but not in the versions which I use.

==== Hopefully final edit, 25/04/12 ====

Following mosquito's advice, I created a new database whose default character set is WIN1252 (UTF-8 did not appear as a choice and and anyway my programs are not unicode). In this clean database I defined the one table, where the 'constext' string's character set was also defined as WIN1252. I ran the data-aware version of the problematic form and was able to enter text without problem (currently over 1700 characters).

It would seem, thus, that the problem was created by having one character set defined for the database and one for the field. I don't know how to check in retrospect what the default character set of the database was defined as, so I can't confirm this.

I now have the small problem of defining a new database (there are 50+ tables) and copying the data from the original database. As this database serves the customer's flagship product, I am somewhat wary of doing this....

Bradstreet answered 12/4, 2012 at 10:49 Comment(13)
Wouldn't this be somehow related to this ? Have you installed the updates on your Delphi 7 ?Eustoliaeutectic
@TLama: I'm fairly certain that I did uploaded the fix a long time. The form in question uses what is boiler plate code for me - it works almost everywhere else in my programs. In the rare cases that the code doesn't work, I've used non-data aware controls which has always fixed the problem - but this requires more programming. I wanted to find the reason why sometimes my boiler plate code doesn't work.Genna
Try setting pfInKey for the ID field in the TSQLDataSet. Also make sure that if you use Persistent fields, you need to add the new varchar field.Mazzard
@kobik: I tried both the above suggestions. Normally, I don't use persistent fields on this kind of form, but I tried adding them (and setting the maxlength propery) to no avail.Genna
Have you tried it on the TSQLDataSet or the TClientDataSet?Mazzard
@Kobik: The persistent fields are defined on the clientdataset. I am revising my question as this has caused a change.Genna
Re: your edit. -> Firebird is returning that exception. Somehow your query string must be malformed. Look here.Airport
You should use it with the TSQLDataSet as I first commented (not the TClientDataSet) - The new error you get is probably specific to Firebird.Mazzard
@SertacAkyuz: I'm aware of the meaningless message. As the query works without the string field, and as the field is much larger than the string which I'm trying to add, I can't figure out what's wrong.Genna
@No'am - I wasn't aware of your last edit when I replied to your comment, hence I deleted the last comment. Regarding your last edit, then the first thing to look into is if the parameter (TParam) is correctly defined (paramtype, datatype etc..) of the SQLDataSet.Airport
why pfInKey? If this (long) field is not part of the table key fields, I would remove this flagFluky
maybe my dbexpress update SQL debugging tips are useful: https://mcmap.net/q/1625468/-dbexpress-quot-record-not-found-or-changed-by-another-user-quotFluky
@mjn: The key field has pfInKey set, whereas the string field does not.Genna
R
2

Unable to find record. No key specified.

set select id, name, byteken, timeflag from scales where id = :p1

to

select id, name, byteken, timeflag from scales where id = 245

an existing id while designing.


to casts cast (constext as varchar (2048))..... If a column's definition is altered, existing CASTs to that column's type may become invalid

Arithmetic exception, numeric overflow, or string truncation

  1. String truncation It happens when the concatenated string doesn't fit the underlying CHAR or VARCHAR datatype size. If the result goes into a table column, perhaps it's a valid error. Or maybe you really need to increase the column size. Similar goes for intermediary values stored in stored procedure or trigger variables.

  2. Character transliteration failed This happens when you have data in database stored in one character set, but the transliteration to required character set fails. There are various points where character set transliteration occurs. There is an automatic one: Every piece of data you retrieve from database (via SELECT or otherwise) is transliterated from character set of database table's column to connection character set. If character sets are too different, there will be two translations: first from column charset to Unicode and then from Unicode to the connection charset. Also, you can request transliteration manually by CASTing the column to another charset, example: CAST(column_name AS varchar(100) character set WIN1251). The reason that transliteration can fail is that simply some characters don't exist in certain character sets. For example, WIN1252 doesn't contain any Cyrillic characters, so if you use connection charset WIN1252 and try to SELECT from a column with Cyrillic characters, you may get such error. In modern times, it is best to use Unicode or UTF8 in your applications and UTF8 connection character. And make sure you use at least Firebird 2.0, has UTF8 support.

  3. Wrong order of parameters when using DotNetFirebird The order in which Parameters are added to a FbCommand when using DotNetFirebird might cause the -303 exception with the hint "Arithmetic exception, numeric overflow, or string truncation". The order of the parameters has to fit the order of the params in the stored procedure - otherwise the exception will be thrown. Example (.NET, C#, DotNetFirebird (using FirebirdSql.Data.FirebirdClient;))

    FbCommand CMD = new FbCommand("TBLTEXT_ADDTEXT", cnn); CMD.Parameters.Add("TEXT1", FbDbType.VarChar, 600).Value = strText1; CMD.Parameters.Add("TEXT2", FbDbType.VarChar, 600).Value = strText2; CMD.CommandType = CommandType.StoredProcedure; CMD.ExecuteNonQuery(); If the order of the parameters inside the procedure "TBLTEXT_ADDTEXT" differ from the order in which you´re adding parameters to the FbCommand-Object, you´ll receive the -303 error.

4.

No'am Newman said But once the error message appears, it always appears, as if the database remembers that there is an error.

no remembers; the database is damaged !!!


As long as you are not able to change your database character-set and always experiment with dropping and adding fields to a damaged table, it's hard to solve the problem. 1. For every new test there must be an new database created (TIP: create one and copy them x times). 2. The field set with plain text not with Cyrillic characters stored in originally field; you can not see them but they are there. 3. set varchar(8191) and database PAGE_SIZE to 8192. The actual maximum VARCHAR length with UTF8 is 8191

CREATE DATABASE statement:

CREATE DATABASE localhost:mybase
  USER SYSDBA
  PASSWORD masterkey
  PAGE_SIZE 8192
  DEFAULT CHARACTER SET UTF8;
  SET NAMES ISO8859_1;

CREATE TABLE scales (
  ID ...,      
  byteken VARCHAR(8191) COLLATE DE_DE,
  ....

Collations

There is no default collation. So you should define a collation for every field that is to be used for sorting (ORDER BY) or comparing (UPPER):

You can also specify the collation with the ORDER BY clause:

ORDER BY LASTNAME COLLATE FR_CA, FIRSTNAME COLLATE FR_CA

or with the WHERE clause:

WHERE LASTNAME COLLATE FR_CA = :lastnametosearch

Unicode

Firebird 2.0. and above. Now there is the new UTF8 character set that correctly handles Unicode strings in UTF-8 format. The Unicode collation algorithm has been implemented so now you can use UPPER() and the new LOWER() function without the need to specify a collation.

Reefer answered 22/4, 2012 at 8:31 Comment(5)
Even if I pass the parameter as a string literal, as suggested above, I still get the 'EDatabase error: arithmetic exception, numeric overflow or string truncation' error message.Genna
Referring to your expanded answer: 1) I have removed the cast, making no difference. 2) The field is defined with length 2048, the record contains 832 characters at the moment, so there is no string overflow. 3) I added a new field to the table with a different character set - when I tried to access this field, I received an error message about being unable to transliterate the contents. As I don't receive this message with the given field, this is not the problem. 4) As there is only one parameter, it can hardly be in the wrong order.Genna
Is the client database set to UTF8 and the server also to UTF8. Create a new database with charset=UTF8;Reefer
@No'am Newman: As long as you are not able to change your database charakter-set and always experiment with dropping and adding fields to a damaged table, it's hard to solve the problem. 1. For every new test there must be an new database created. 2. The field set with plain text not with Cyrillic characters stored in originally field; you can not see them but they are there. 3. set varchar(8192) and database pagesize to 8192.Reefer
See my revision to the question, dated 25/04/12.Genna
C
3

Check the UpdateMode property of the provider. If it is set to upWhereChanged or upWhereKeyOnly you need a key in the database table to work properly.

Caye answered 12/4, 2012 at 12:36 Comment(3)
(a) The updatemode of the provider is upWhereAll. (b) Data is updated whenever the new text field is not present. (c) The database table has a key and it is definitely present.Genna
Sorry, I'm not familiar with any dbx driver for Firebird running under Delphi 7. You might try to change the UpdateMode to one of the other two options.Caye
I changed the updatemode but it made no difference. I don't think that this is the problem.Genna
R
2

Unable to find record. No key specified.

set select id, name, byteken, timeflag from scales where id = :p1

to

select id, name, byteken, timeflag from scales where id = 245

an existing id while designing.


to casts cast (constext as varchar (2048))..... If a column's definition is altered, existing CASTs to that column's type may become invalid

Arithmetic exception, numeric overflow, or string truncation

  1. String truncation It happens when the concatenated string doesn't fit the underlying CHAR or VARCHAR datatype size. If the result goes into a table column, perhaps it's a valid error. Or maybe you really need to increase the column size. Similar goes for intermediary values stored in stored procedure or trigger variables.

  2. Character transliteration failed This happens when you have data in database stored in one character set, but the transliteration to required character set fails. There are various points where character set transliteration occurs. There is an automatic one: Every piece of data you retrieve from database (via SELECT or otherwise) is transliterated from character set of database table's column to connection character set. If character sets are too different, there will be two translations: first from column charset to Unicode and then from Unicode to the connection charset. Also, you can request transliteration manually by CASTing the column to another charset, example: CAST(column_name AS varchar(100) character set WIN1251). The reason that transliteration can fail is that simply some characters don't exist in certain character sets. For example, WIN1252 doesn't contain any Cyrillic characters, so if you use connection charset WIN1252 and try to SELECT from a column with Cyrillic characters, you may get such error. In modern times, it is best to use Unicode or UTF8 in your applications and UTF8 connection character. And make sure you use at least Firebird 2.0, has UTF8 support.

  3. Wrong order of parameters when using DotNetFirebird The order in which Parameters are added to a FbCommand when using DotNetFirebird might cause the -303 exception with the hint "Arithmetic exception, numeric overflow, or string truncation". The order of the parameters has to fit the order of the params in the stored procedure - otherwise the exception will be thrown. Example (.NET, C#, DotNetFirebird (using FirebirdSql.Data.FirebirdClient;))

    FbCommand CMD = new FbCommand("TBLTEXT_ADDTEXT", cnn); CMD.Parameters.Add("TEXT1", FbDbType.VarChar, 600).Value = strText1; CMD.Parameters.Add("TEXT2", FbDbType.VarChar, 600).Value = strText2; CMD.CommandType = CommandType.StoredProcedure; CMD.ExecuteNonQuery(); If the order of the parameters inside the procedure "TBLTEXT_ADDTEXT" differ from the order in which you´re adding parameters to the FbCommand-Object, you´ll receive the -303 error.

4.

No'am Newman said But once the error message appears, it always appears, as if the database remembers that there is an error.

no remembers; the database is damaged !!!


As long as you are not able to change your database character-set and always experiment with dropping and adding fields to a damaged table, it's hard to solve the problem. 1. For every new test there must be an new database created (TIP: create one and copy them x times). 2. The field set with plain text not with Cyrillic characters stored in originally field; you can not see them but they are there. 3. set varchar(8191) and database PAGE_SIZE to 8192. The actual maximum VARCHAR length with UTF8 is 8191

CREATE DATABASE statement:

CREATE DATABASE localhost:mybase
  USER SYSDBA
  PASSWORD masterkey
  PAGE_SIZE 8192
  DEFAULT CHARACTER SET UTF8;
  SET NAMES ISO8859_1;

CREATE TABLE scales (
  ID ...,      
  byteken VARCHAR(8191) COLLATE DE_DE,
  ....

Collations

There is no default collation. So you should define a collation for every field that is to be used for sorting (ORDER BY) or comparing (UPPER):

You can also specify the collation with the ORDER BY clause:

ORDER BY LASTNAME COLLATE FR_CA, FIRSTNAME COLLATE FR_CA

or with the WHERE clause:

WHERE LASTNAME COLLATE FR_CA = :lastnametosearch

Unicode

Firebird 2.0. and above. Now there is the new UTF8 character set that correctly handles Unicode strings in UTF-8 format. The Unicode collation algorithm has been implemented so now you can use UPPER() and the new LOWER() function without the need to specify a collation.

Reefer answered 22/4, 2012 at 8:31 Comment(5)
Even if I pass the parameter as a string literal, as suggested above, I still get the 'EDatabase error: arithmetic exception, numeric overflow or string truncation' error message.Genna
Referring to your expanded answer: 1) I have removed the cast, making no difference. 2) The field is defined with length 2048, the record contains 832 characters at the moment, so there is no string overflow. 3) I added a new field to the table with a different character set - when I tried to access this field, I received an error message about being unable to transliterate the contents. As I don't receive this message with the given field, this is not the problem. 4) As there is only one parameter, it can hardly be in the wrong order.Genna
Is the client database set to UTF8 and the server also to UTF8. Create a new database with charset=UTF8;Reefer
@No'am Newman: As long as you are not able to change your database charakter-set and always experiment with dropping and adding fields to a damaged table, it's hard to solve the problem. 1. For every new test there must be an new database created. 2. The field set with plain text not with Cyrillic characters stored in originally field; you can not see them but they are there. 3. set varchar(8192) and database pagesize to 8192.Reefer
See my revision to the question, dated 25/04/12.Genna

© 2022 - 2024 — McMap. All rights reserved.