6

dbExpress コンポーネント (Delphi 7) を使用して、データベース プログラムに取り組んでいます。データは、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] に設定されています。これでは問題は解決しません。

永続フィールドは clientdataset で定義されました。TSQLDataSet でそれらを定義すると、「キーが指定されていません」というエラー メッセージは表示されません。プログラムはまだこのエラー メッセージを表示します (これについては前に触れませんでした)。

EDatabase error: arithmetic exception, numeric overflow or string truncation

大きな文字列フィールドには、'displaywidth' と 'size' の正しい値があります。

==== さらに詳しい情報 ====

非データ認識コンポーネントを使用するようにフォームを書き直しました。1 つのクエリでデータベースからデータを取得します (TSQLDataSet で使用しているものとまったく同じクエリ文字列を使用)。その後、データはコントロールに転送されます。ユーザーがフォームの [OK] ボタンを押すと、更新または挿入を実行する別のクエリを介してデータがデータベースに戻されます。これは正しく機能するため、データ認識コンポーネントの問題が何であるかはわかりません。

==== さらに別の情報スニペット ====

同様の問題に対処しているように見えるスタックオーバーフローでこの質問を見つけました。クエリを次のように変更しました

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

dbMemo のデータフィールドを「fconstext」に設定します。テキストを dbMemo に追加した後、「applyupdates」呼び出しが次のメッセージで失敗するようになりました

column unknown 'fconstext'

その名前で作成された永続フィールドがあるという事実にもかかわらず。

これが助けになるのか、単に水を濁らせるのかはわかりません。

==== 詳細情報、4 月 23 日 ====

データベース テーブルからフィールドを削除し、再度追加しました。問題のあるデータ フィールドに入力される文字列が約 260 文字未満である限り、書かれたプログラムは問題なく動作します。文字列の長さが256になるまで、一度に10文字を問題なく数回追加しました。次に、さらに文字を追加し(数えずに)、保存しようとしましたが、エラーが発生しました。この時点から、さらに1 文字追加しようとすると、エラー メッセージが表示されます (これは clientdataset の「applyupdates」メソッドで表示されます)。

もともと、フィールドには 832 文字が含まれていたため、正常に保存できる文字数に厳密な制限はありません。しかし、エラー メッセージが表示されると、あたかもデータベースがエラーがあることを記憶しているかのように、常に表示されます。

==== 詳細情報、4 月 24 日 ====

もう一度、データベースからフィールドを削除してから追加し直しました。文字セットは WIN1251 ですが、理由は今のところわかりません (キリル文字は必要ありません)。フィールド自体の定義方法に関係なく、データベース対応コントロールを使用して入力できる最大文字数は約 280 のようです。

その後、この問題が発生する実際のプログラムで非データ認識コントロールを使用するようになりましたが、この制限が存在しないことを保証できます。したがって、提案されているように、問題が文字サイズの不一致によるものではないことはかなり確信しています。Unicode 文字列を持たない Delphi 7 を使用していることを忘れないでください。コンポーネントの1つにバグがあると思いますが、古いバージョンを使用しているため、問題は解決されていると思いますが、使用しているバージョンでは解決されていません。

==== できれば最終編集、25/04/12 ====

蚊のアドバイスに従って、デフォルトの文字セットが WIN1252 の新しいデータベースを作成しました (UTF-8 は選択肢として表示されず、とにかく私のプログラムは Unicode ではありません)。このクリーンなデータベースで、'constext' 文字列の文字セットも WIN1252 として定義された 1 つのテーブルを定義しました。問題のあるフォームのデータベース対応バージョンを実行したところ、問題なくテキストを入力できました (現在 1700 文字以上)。

したがって、データベース用に 1 つの文字セットを定義し、フィールド用に 1 つの文字セットを定義することによって、問題が発生したように思われます。データベースのデフォルトの文字セットがどのように定義されているかを振り返って確認する方法がわからないため、これを確認できません。

新しいデータベース (50 以上のテーブルがあります) を定義し、元のデータベースからデータをコピーするという小さな問題があります。このデータベースは顧客の主力製品にサービスを提供するため、これを行うには少し警戒しています....

4

2 に答える 2

2

UpdateModeプロバイダのプロパティを確認してください。に設定されている場合、upWhereChangedまたはupWhereKeyOnly正しく機能するためにデータベース テーブルにキーが必要な場合。

于 2012-04-12T12:36:34.970 に答える
1

レコードが見つかりません。キーが指定されていません。

id = :p1 のスケールから選択した id、name、byteken、timeflag を設定します

id = 245 のスケールから id、name、byteken、timeflag を選択します

設計中の既存の ID。


to casts cast (context as varchar (2048))..... 列の定義が変更された場合、その列の型に対する既存の CAST が無効になる可能性があります

算術例外、数値オーバーフロー、または文字列の切り捨て

  1. 文字列の切り捨て 連結された文字列が、基礎となる CHAR または VARCHAR データ型のサイズに適合しない場合に発生します。結果がテーブルの列に入る場合、おそらくそれは有効なエラーです。または、列のサイズを大きくする必要があるかもしれません。ストアド プロシージャまたはトリガー変数に格納されている中間値についても同様です。

  2. 文字変換の失敗 これは、データベース内のデータが 1 つの文字セットで保存されているが、必要な文字セットへの文字変換が失敗した場合に発生します。文字セットの音訳が発生するポイントはさまざまです。自動のものがあります。データベースから (SELECT またはその他の方法で) 取得したすべてのデータは、データベーステーブルの列の文字セットから接続文字セットに音訳されます。文字セットがあまりにも異なる場合は、最初に列文字セットから Unicode へ、次に Unicode から接続文字セットへの 2 つの変換が行われます。また、列を別の文字セットにキャストすることにより、手動で文字変換を要求することもできます。例: CAST(column_name AS varchar(100) character set WIN1251)。 理由文字変換が失敗する可能性があるのは、特定の文字セットに一部の文字が存在しないということです。たとえば、WIN1252 にはキリル文字が含まれていないため、接続文字セット WIN1252 を使用してキリル文字を含む列から SELECT しようとすると、このようなエラーが発生する可能性があります。現代では、アプリケーションで Unicode または UTF8 を使用し、UTF8 接続文字を使用するのが最善です。そして、少なくともFirebird 2.0を使用し、UTF8 をサポートしていることを確認してください。

  3. DotNetFirebird 使用時のパラメーター の順序の誤り DotNetFirebird の使用時にパラメーターが FbCommand に追加される順序により、「算術例外、数値オーバーフロー、または文字列の切り捨て」というヒントで -303 例外が発生する場合があります。パラメーターの順序は、ストアド プロシージャ内のパラメーターの順序と一致する必要があります。そうでない場合、例外がスローされます。例 (.NET、C#、DotNetFirebird (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(); プロシージャ「TBLTEXT_ADDTEXT」内のパラメータの順序が、FbCommand-Object にパラメータを追加する順序と異なる場合、-303 エラーが発生します。

4.

No'am Newman 氏は言いましたが、一度エラー メッセージが表示されると、あたかもデータベースがエラーがあることを記憶しているかのように、常に表示されます。

覚えていません。データベースが破損しています!!!


データベースの文字セットを変更できず、破損したテーブルにフィールドを削除したり追加したりすることを常に試している限り、問題を解決するのは困難です。1. 新しいテストごとに、新しいデータベースを作成する必要があります (ヒント: データベースを作成して x 回コピーします)。2.元のフィールドに格納されているキリル文字ではなく、プレーン テキストで設定されたフィールド。あなたはそれらを見ることができませんが、彼らはそこにいます。3. varchar(8191) とデータベースの PAGE_SIZE を 8192 に設定します。UTF8 での実際の VARCHAR の最大長は 8191 です。

CREATE DATABASE ステートメント:

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 BY) または比較 (UPPER) に使用されるすべてのフィールドに対して照合を定義する必要があります。

ORDER BY 句を使用して照合を指定することもできます。

ORDER BY LASTNAME COLLATE FR_CA, FIRSTNAME COLLATE FR_CA

または WHERE 句を使用:

WHERE LASTNAME COLLATE FR_CA = :lastnametosearch

ユニコード

ファイアバード2.0。以上。現在、UTF-8 形式の Unicode 文字列を正しく処理する新しい UTF8 文字セットがあります。Unicode 照合アルゴリズムが実装されたため、照合を指定しなくてもUPPER() および新しい LOWER() 関数を使用できるようになりました。

于 2012-04-22T08:31:04.177 に答える