我正在使用dbExpress组件(Delphi7)编写一个数据库程序。通过以下组件从数据库中检索数据: TSQLDataSet -> TDataSetProvider -> TClientDataSet -> TDatasource -> TDBEdit。到目前为止,该表单工作正常。TSQLDataset中的查询是
select id, name, byteken, timeflag from scales where id = :p1我向数据库表中添加了一个大的(2048) varchar字段;当我将这个字段添加到上面的查询(并将TDBMemo或TDBRichEdit连接到TDatasource)时,当我试图编辑新文本字段中的值时,我会收到以下消息
Unable to find record. No key specified.当表单上没有TDBMemo时(但是在查询中使用varchar字段),我会得到相同的错误。一旦我从查询中移除varchar字段,一切就会再次正常工作。
造成这个问题的原因是什么?
====更多信息====
我现在已经在表单中定义了持久字段。包含表键的字段将其提供程序标志设置为pfInUpdate、pfInWhere、pfInKey,而所有其他字段的标志都为pfInUpdate、pfInWhere。这不能解决问题。
持久字段是在客户端数据集中定义的。当我在TSQLDataSet上定义它们时,不会出现关于“未指定键”的错误消息。这个程序仍然会发出这个错误消息(我之前没有提到):
EDatabase error: arithmetic exception, numeric overflow or string truncation大字符串字段在“显示宽度”和“大小”中具有正确的值。
====更多信息====
我重写了表单以使用非数据感知组件。一个查询从数据库中检索数据(使用与我在TSQLDataSet中使用的完全相同的查询字符串);然后将数据传输到控件。用户按下表单上的OK按钮后,数据将通过执行更新或插入的另一个查询传递回数据库。由于这样做是正确的,我不知道数据感知组件有什么问题。
====又一段信息====
我在堆栈溢出上发现了this question,这似乎解决了一个类似的问题。我将查询更改为
select id, name, name, byteken, timeflag,
cast (constext as varchar (2048)) as fconstext
from scales
where id = :p1并将dbMemo的数据字段设置为“fconstext”。在将文本添加到dbMemo之后,“applyupdate”调用将失败,下面的消息如下
column unknown 'fconstext'尽管存在一个使用该名称创建的持久字段。
我不知道这是否有帮助,还是只是把水弄脏了。
====更多信息,4月23日====
我从数据库表中删除了字段,然后将其添加回来。只要输入有问题的数据字段的字符串小于260个字符,编写的程序就能正常工作。我一次添加了10个字符,没有问题,直到字符串长度为256。然后,我添加了一些字符(不计),试图保存-并得到了错误。从这一点开始,尝试再添加一个字符就会导致错误消息(它出现在clientdataset的'applyupdates‘方法中)。
最初,该字段包含832个字符,因此我可以成功存储的字符数量没有硬性限制。但是,一旦出现错误消息,它总是会出现,就好像数据库记得有错误一样。
====更多信息,4月24日====
再次,我从数据库中删除了字段,然后将其添加回去;字符集是WIN1251,原因我现在还不清楚(我不需要西里尔字符)。我可以使用数据感知控件输入的最大字符数似乎大约为280个,而不管字段本身是如何定义的。
从那以后,我开始在实际程序中使用非数据感知控件,我可以向您保证,这个限制并不存在。因此,我相当肯定,问题并不是因为字符大小不匹配,正如有人所建议的那样。不要忘记,我使用的是Delphi 7,它没有unicode字符串。我认为其中一个组件中有一个bug,但由于我使用的是旧版本,我想问题已经解决了,但没有在我使用的版本中解决。
====希望最终编辑,25/04/12 ====
按照蚊子的建议,我创建了一个新的数据库,它的默认字符集是WIN1252 (UTF-8没有作为选择出现,而且我的程序也不是unicode)。在这个干净的数据库中,我定义了一个表,在这个表中,'constext‘字符串的字符集也被定义为WIN1252。我运行了有问题的表单的数据感知版本,并且能够没有问题地输入文本(目前超过1700个字符)。
因此,问题似乎是通过为数据库定义一个字符集和为该字段定义一个字符集而产生的。我不知道如何回溯数据库的默认字符集定义为什么,所以我无法确认这一点。
现在,我遇到了一个小问题:定义一个新的数据库(有50+表)并从原始数据库复制数据。由于这个数据库服务于客户的旗舰产品,我对此有所警惕.
发布于 2012-04-22 08:31:04
找不到记录。没有指定密钥。
设置select id,name,byteken,name标志,其中id = :p1
至
从id = 245的天平中选择id、name、byteken、name标志
在设计过程中存在的id。
.=‘casts 2’>转换(强制转换为varchar (2048年))如果更改了列的定义,则对该列类型的现有转换可能变得无效
算术异常、数字溢出或字符串截断
FbCommand CMD = new ( "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();如果过程”TBLTEXT_ADDTEXT“中的参数顺序与向FbCommand-对象重新添加参数的顺序不同,则将收到-303错误。
4.
No. Newman说,但是一旦错误消息出现,它就会出现,就好像数据库记得有错误一样。
没有记忆,数据库被破坏了!
只要您不能更改数据库字符集,并且总是尝试将字段删除并添加到损坏的表中,就很难解决这个问题。1.对于每一个新的测试,都必须创建一个新的数据库(提示:创建一个数据库并将其复制x次)。2.使用纯文本设置的字段,而不是存储在原始字段中的西里尔字符;您看不到它们,但它们在那里。3.将varchar(8191)和数据库PAGE_SIZE设置为8192。使用UTF8的实际最大VARCHAR长度为8191
创建数据库语句:
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,
....排序规则
没有默认的排序规则。因此,您应该为用于排序(ORDER )或比较(上)的每个字段定义一个排序规则:
还可以使用ORDER子句指定排序规则:
ORDER BY LASTNAME COLLATE FR_CA, FIRSTNAME COLLATE FR_CA或加上WHERE条款:
WHERE LASTNAME COLLATE FR_CA = :lastnametosearchUnicode
Firebird 2.0上面也有。现在有了新的UTF8字符集,它正确地处理UTF-8格式的Unicode字符串。Unicode排序算法已经实现,因此现在您可以使用和新的LOWER()函数,而无需指定排序规则.。
发布于 2012-04-12 12:36:34
检查提供程序的UpdateMode属性。如果将其设置为upWhereChanged或upWhereKeyOnly,则需要数据库表中的一个键才能正常工作。
https://stackoverflow.com/questions/10122073
复制相似问题