首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >dbExpress/无指定密钥

dbExpress/无指定密钥
EN

Stack Overflow用户
提问于 2012-04-12 10:49:02
回答 2查看 3.9K关注 0票数 6

我正在使用dbExpress组件(Delphi7)编写一个数据库程序。通过以下组件从数据库中检索数据: TSQLDataSet -> TDataSetProvider -> TClientDataSet -> TDatasource -> TDBEdit。到目前为止,该表单工作正常。TSQLDataset中的查询是

代码语言:javascript
复制
select id, name, byteken, timeflag from scales where id = :p1

我向数据库表中添加了一个大的(2048) varchar字段;当我将这个字段添加到上面的查询(并将TDBMemo或TDBRichEdit连接到TDatasource)时,当我试图编辑新文本字段中的值时,我会收到以下消息

代码语言:javascript
复制
Unable to find record. No key specified.

当表单上没有TDBMemo时(但是在查询中使用varchar字段),我会得到相同的错误。一旦我从查询中移除varchar字段,一切就会再次正常工作。

造成这个问题的原因是什么?

====更多信息====

我现在已经在表单中定义了持久字段。包含表键的字段将其提供程序标志设置为pfInUpdate、pfInWhere、pfInKey,而所有其他字段的标志都为pfInUpdate、pfInWhere。这不能解决问题。

持久字段是在客户端数据集中定义的。当我在TSQLDataSet上定义它们时,不会出现关于“未指定键”的错误消息。这个程序仍然会发出这个错误消息(我之前没有提到):

代码语言:javascript
复制
EDatabase error: arithmetic exception, numeric overflow or string truncation

大字符串字段在“显示宽度”和“大小”中具有正确的值。

====更多信息====

我重写了表单以使用非数据感知组件。一个查询从数据库中检索数据(使用与我在TSQLDataSet中使用的完全相同的查询字符串);然后将数据传输到控件。用户按下表单上的OK按钮后,数据将通过执行更新或插入的另一个查询传递回数据库。由于这样做是正确的,我不知道数据感知组件有什么问题。

====又一段信息====

我在堆栈溢出上发现了this question,这似乎解决了一个类似的问题。我将查询更改为

代码语言:javascript
复制
select id, name, name, byteken, timeflag, 
cast (constext as varchar (2048)) as fconstext
from scales
where id = :p1

并将dbMemo的数据字段设置为“fconstext”。在将文本添加到dbMemo之后,“applyupdate”调用将失败,下面的消息如下

代码语言:javascript
复制
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+表)并从原始数据库复制数据。由于这个数据库服务于客户的旗舰产品,我对此有所警惕.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-22 08:31:04

找不到记录。没有指定密钥。

设置select id,name,byteken,name标志,其中id = :p1

从id = 245的天平中选择id、name、byteken、name标志

在设计过程中存在的id。

.=‘casts 2’>转换(强制转换为varchar (2048年))如果更改了列的定义,则对该列类型的现有转换可能变得无效

算术异常、数字溢出或字符串截断

  1. String截断当级联字符串不符合底层CHAR或VARCHAR数据类型大小时发生。如果结果进入表列,则可能是一个有效的错误。或者您确实需要增加列的大小。存储在存储过程中的中间值或触发器音译失败的也是如此--当您将数据库中的数据存储在一个字符集中时,就会发生这种情况,但是对所需字符集的音译失败。字符集音译有不同的地方。有一个自动的:从数据库(通过SELECT或其他方式)检索的每一个数据都是从数据库表的列的字符集的到连接字符集的音译。如果字符集太不一样,将有两个翻译:首先从列字符集到Unicode,然后从Unicode到连接字符集。另外,您可以通过CASTing手动将列转写到另一个字符集,例如: CAST(column_name AS varchar(100)字符集WIN1251)。音译失败的原因是某些字符在某些字符集中不存在。例如,WIN1252不包含任何西里尔字符,所以如果使用连接字符集WIN1252并尝试从带有西里尔字符的列中进行选择,则可能会出现这样的错误。在现代,最好在应用程序和UTF8连接字符中使用Unicode或UTF8。并确保至少使用support.
  2. Wrong 2.0,在使用DotNetFirebird时具有UTF8 DotNetFirebird顺序参数-使用DotNetFirebird时将参数添加到FbCommand的顺序可能会导致-303异常,并提示为“算术异常、数字溢出或字符串截断”。参数的顺序必须符合存储过程中参数的顺序,否则将引发异常。示例(.NET、C#、DotNetFirebird (使用FirebirdSql.Data.FirebirdClient;)

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

创建数据库语句:

代码语言:javascript
复制
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子句指定排序规则:

代码语言:javascript
复制
ORDER BY LASTNAME COLLATE FR_CA, FIRSTNAME COLLATE FR_CA

或加上WHERE条款:

代码语言:javascript
复制
WHERE LASTNAME COLLATE FR_CA = :lastnametosearch

Unicode

Firebird 2.0上面也有。现在有了新的UTF8字符集,它正确地处理UTF-8格式的Unicode字符串。Unicode排序算法已经实现,因此现在您可以使用和新的LOWER()函数,而无需指定排序规则.。

票数 1
EN

Stack Overflow用户

发布于 2012-04-12 12:36:34

检查提供程序的UpdateMode属性。如果将其设置为upWhereChangedupWhereKeyOnly,则需要数据库表中的一个键才能正常工作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10122073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档