1. 問題の説明 root@mysqldb 22:12: [xucl]> テーブル t1\G の作成を表示します ************************** 1. 行 **************************** 表: t1 テーブルの作成: CREATE TABLE `t1` ( `id` varchar(255) デフォルト NULL ) エンジン=InnoDB デフォルト文字セット=utf8 セット内の 1 行 (0.00 秒) root@mysqldb 22:19: [xucl]> t1 から * を選択します。 +--------------------+ |id| +--------------------+ | 204027026112927605 | | 204027026112927603 | | 2040270261129276 | | 2040270261129275 | | 100 | | 101 | +--------------------+ セット内の 6 行 (0.00 秒) 奇妙な現象: root@mysqldb 22:19: [xucl]> id=204027026112927603 の t1 から * を選択します。 +--------------------+ |id| +--------------------+ | 204027026112927605 | | 204027026112927603 | +--------------------+ セット内の 2 行 (0.00 秒) 640?wx_fmt=jpeg 一体全体、204027026112927603 を確認したのに、なぜ 204027026112927605 も出てきたのでしょうか? 2. ソースコードの説明 コールスタックの関係は次のとおりです。 JOIN::exec()は実行エントリポイントであり、Arg_comparator::compare_real()は等価判定関数であり、以下のように定義される。 int Arg_comparator::compare_real() { /* Bug#2338のもう一つの症状を修正。「Volatile」は次のように指示します。 gccは80ビットIntel FPUレジスタからdouble値をフラッシュする前に 比較を実行します。 */ 揮発性ダブル val1、val2; val1 = (*a)->val_real(); if (!(*a)->null_value) { val2 = (*b)->val_real(); if (!(*b)->null_value) { (set_null)の場合 所有者->null_value = 0; val1 < val2 の場合は -1 を返します。 val1 == val2 の場合は 0 を返します。 1 を返します。 } } (set_null)の場合 所有者->null_value = 1; -1 を返します。 } 比較手順を下図に示します。t1 テーブルの id 列が行ごとに読み取られ、val1 に格納されます。定数 204027026112927603 がキャッシュに存在し、その型は double (2.0402702611292762E+17) です。したがって、値が val2 に渡された後、val2=2.0402702611292762E+17 になります。 1行目までスキャンすると、204027026112927605をdouleに変換すると2.0402702611292762e17となり、等式が成立し、適格行であると判定され、スキャンが続行されます。同様に、204027026112927603も条件を満たしています。 文字列型数値から倍精度型数値への変換がオーバーフローするかどうかを検出するにはどうすればよいでしょうか。ここでテストしたところ、数値が16桁を超えると、倍精度型への変換は正確ではなくなりました。たとえば、20402702611292711は、20402702611292712と表現されます(図のval1に示すように) MySQL 文字列を double に変換するための定義関数は次のとおりです。 { char buf[DTOA_BUFF_SIZE]; ダブル解像度; DBUG_ASSERT(end != NULL && ((str != NULL && *end != NULL) || (str == NULL && *end == NULL)) && エラー != NULL); res = my_strtod_int(str、end、error、buf、sizeof(buf)); 戻り値 (*error == 0) ? res : (res < 0 ? -DBL_MAX : DBL_MAX); } 実際の変換関数 my_strtod_int は dtoa.c にあります (複雑すぎるので、コメントを投稿してください) /* IEEE 算術マシン用の strtod。 このstrtodは入力された10進数に最も近い機械数を返します。 文字列(またはerrnoをEOVERFLOWに設定)。同点の場合はIEEEラウンドイーブンで決着する。 ルール。 ウィリアム・D・クリンガーの論文「浮動小数点数の読み方」に大まかに触発されて 「ポイント番号を正確に示す」[Proc. ACM SIGPLAN '90、pp. 92-101]。 変更点: 1. 必要なのは IEEE のみです (IEEE ダブル拡張ではありません)。 2. 浮動小数点演算で済むケース クリンガーは失敗しました -- d * 10^n を計算しているとき 小さな整数dと整数nが大きすぎる場合は 22(kが最大となる整数)よりはるかに大きい 10^kを正確に表現できる場合、 1回の丸めだけで (d*10^k) * 10^(ek) を計算します。 3. バイナリを少しずつ調整するのではなく その結果、難しいケースでは浮動小数点を使用する。 調整を決定するための算術 1ビット;本当に難しい場合にのみ、 2番目の残差を計算します。 4. 3. のため、10の累乗の大きな表は必要ありません。 10の倍数(例えば10^kの小さな表) (0 <= k <= 22)。 */ この場合、オーバーフローが発生しない場合をテストしてみましょう。 root@mysqldb 23:30: [xucl]> id=2040270261129276 の t1 から * を選択します。 +------------------+ |id| +------------------+ | 2040270261129276 | +------------------+ セット内の 1 行 (0.00 秒) root@mysqldb 23:30: [xucl]> id=101 の場合、t1 から * を選択します。 +------+ |id| +------+ | 101 | +------+ セット内の 1 行 (0.00 秒) 結果は予想通りであり、この場合、正しい書き方は次のようになります。 root@mysqldb 22:19: [xucl]> id='204027026112927603' の t1 から * を選択します。 +--------------------+ |id| +--------------------+ | 204027026112927603 | +--------------------+ セット内の1行(0.01秒) 結論 暗黙的な型変換は避けてください。暗黙的な変換には、主に、一貫性のないフィールド型、in パラメータ内の複数の型、一貫性のない文字セット型または校正ルールなどが含まれます。 暗黙的な型変換により、インデックスが使用できなくなったり、クエリ結果が不正確になったりする可能性があるため、使用時には慎重に識別する必要があります。 フィールドを定義するときは、数値型を int または bigint として定義することをお勧めします。テーブルがリンクされている場合、関連付けられているフィールドは同じ型、文字セット、および照合ルールを維持する必要があります。 最後に、暗黙的な型変換についての公式サイトの説明を掲載しておきます。
要約する 上記は、編集者が紹介したMySQLの暗黙的な変換です。皆様のお役に立てれば幸いです。ご質問がある場合は、メッセージを残してください。編集者がすぐに返信します。また、123WORDPRESS.COM ウェブサイトをサポートしてくださっている皆様にも感謝申し上げます。 以下もご興味があるかもしれません:
|
<<: Centos7のシステム言語を簡体字中国語に変更する方法
目次sakilaをインストールするインデックススキャンソートテーブル構造インデックススキャンをソート...
目次元に戻すログUNDOログの生成と破棄UNDOログの保存元に戻すログ機能トランザクションの原子性の...
この記事では、主に html + css を使用してサラウンド リフレクション ローディング エフェ...
目次イベント駆動型とパブリッシュ・サブスクライブ型ブラウザの JavaScript ではイベント駆動...
# VMware ハードディスクの起動優先順位を調整するステップ 1: 電源をオンにすると、BIOS...
この記事では、MySQL のデータ型とフィールド属性について説明します。ご参考までに、詳細は以下の通...
目次1. 概要1. スカイウォーキング入門2. スカイウォーキング建築3. スカイウォーキングはどの...
折りたたみ表示の複数行テキストコンポーネント複数行のテキスト コンポーネントを折りたたんで表示し、展...
MySQL5.7.21のインストールとパスワード設定のチュートリアルは次のとおりです。公式リファレン...
ある日、内部結合を含む SQL ステートメントの実行速度はそれほど遅くはない (0.1 ~ 0.2)...
MySQL は、コミュニティ エディション (コミュニティ サーバー) とエンタープライズ エディシ...
HTML タグには、ページのタイトルを処理するための特別なタグがあります。これらは h1、h2、h3...
1. 分割スクリプト (splitNginxLog.sh) を作成します。 * この例では、ログ分割...
トレーニングのための一連のプロジェクト反応+ts内容は少ないですが、フックのカプセル化、ts ジェネ...
1. Baidu Eslint Ruleプラグインをインストールする npm i -D eslint...