web-dev-qa-db-ja.com

mysql-数字を引用するかどうか

たとえば、cliからデータベースとテーブルを作成し、いくつかのデータを挿入します。

CREATE DATABASE testdb CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
USE testdb;
CREATE TABLE test (id INT, str VARCHAR(100)) TYPE=innodb CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
INSERT INTO test VALUES (9, 'some string');

今、私はこれを行うことができ、これらの例は動作します(そのため、引用符は見た目に影響を与えません):

SELECT * FROM test WHERE id = '9';
INSERT INTO test VALUES ('11', 'some string');

したがって、これらの例では、実際にはmysqlにINTとして保存されているstringで行を選択し、その後、INTである列にstringを挿入しました。

これがここで動作する方法で動作する理由はよくわかりません。 INT列に文字列を挿入できるのはなぜですか?

すべてのMysqlデータ型を文字列として挿入できますか?

この動作は異なるRDBMS全体で標準ですか?

ありがとう!

45
Stann

MySQLはPHPに非常によく似ており、データ型を可能な限り自動変換します。 intフィールド(左側)を使用しているため、引数の右側も透過的にintに変換しようとするため、'9'9になります。

厳密に言えば、引用符は不要であり、MySQLに型キャスト/変換を強制するため、CPU時間を少し無駄にします。実際には、Googleサイズの操作を実行している場合を除き、このような変換のオーバーヘッドは微視的に小さくなります。

61
Marc B

数字を引用符で囲まないでください。これには正当な理由があります。

本当の問題は、型キャストにあります。引用符の中に数字を入れると、文字列として扱われ、MySQLはクエリを実行する前に数字に変換する必要があります。これには少し時間がかかりますが、MySQLが文字列の変換をうまく行っていない場合に実際の問題が発生し始めます。たとえば、MySQLは '123'などの基本的な文字列を整数123に変換しますが、 '18015376320243459'などのいくつかの大きな数値を浮動小数点に変換します。浮動小数点は丸められるため、クエリは一貫性のない結果を返す場合があります。 型キャストの詳細はこちら 。サーバーのハードウェアとソフトウェアに応じて、これらの結果は異なります。 MySQLはこれを説明します。

SQLインジェクションが心配な場合は、必ず最初に値を確認し、PHPを使用して非数字を取り除きます。これにはpreg_replaceを使用できます。preg_replace("/[^0-9]/", "", $string)

さらに、引用符を使用してSQLクエリを記述した場合、PostgreSQLやOracleなどのデータベースでは機能しません。

8
Sean

これを確認して、あなたはよりよく理解することができます...

mysql> EXPLAIN SELECT COUNT(1) FROM test_no WHERE varchar_num=0000194701461220130201115347;
+----+-------------+------------------------+-------+-------------------+-------------------+---------+------+---------+--------------------------+
| id | select_type | table                  | type  | possible_keys     | key                  | key_len | ref  | rows    | Extra                    |
+----+-------------+------------------------+-------+-------------------+-------------------+---------+------+---------+--------------------------+
|  1 | SIMPLE      | test_no | index | Uniq_idx_varchar_num | Uniq_idx_varchar_num | 63      | NULL | 3126240 | Using where; Using index |
+----+-------------+------------------------+-------+-------------------+-------------------+---------+------+---------+--------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT COUNT(1) FROM test_no WHERE varchar_num='0000194701461220130201115347';
+----+-------------+------------------------+-------+-------------------+-------------------+---------+-------+------+-------------+
| id | select_type | table                  | type  | possible_keys     | key               | key_len | ref   | rows | Extra       |
+----+-------------+------------------------+-------+-------------------+-------------------+---------+-------+------+-------------+
|  1 | SIMPLE      | test_no | const | Uniq_idx_varchar_num | Uniq_idx_varchar_num | 63      | const |    1 | Using index |
+----+-------------+------------------------+-------+-------------------+-------------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

mysql>
mysql>
mysql> SELECT COUNT(1) FROM test_no WHERE varchar_num=0000194701461220130201115347;
+----------+
| COUNT(1) |
+----------+
|        1 |
+----------+
1 row in set, 1 warning (7.94 sec)

mysql> SELECT COUNT(1) FROM test_no WHERE varchar_num='0000194701461220130201115347';
+----------+
| COUNT(1) |
+----------+
|        1 |
+----------+
1 row in set (0.00 sec)
3

知る限りそれは標準ですが、それは悪い習慣と見なされます
-WHERE句でこれを使用すると、オプティマイザーがインデックスを使用できなくなります(説明計画はそれを示す必要があります)
-データベースは、文字列を数値に変換するために追加の作業を行う必要があります
-浮動小数点数( '9.4')にこれを使用している場合、クライアントとサーバーで異なる言語設定を使用すると問題が発生します(9.4対9,4)

要するに、やらないでください(ただしYMMV)

3
Frank Schmitt

数字を引用する必要はありませんが、一貫性があるため、引用することは常に良い習慣です。

1
Anush

列のタイプに依存します!あなたが走ったら

SELECT * FROM `users` WHERE `username` = 0;

mysql/maria-dbでは、username IS NOT NULL。

列が文字列型(char、varchar、...)の場合は、常に値を引用してください。そうしないと、予期しない結果が発生します。

0
pine3ree

問題は、このクエリを実行する場合、usersというテーブルがあり、タイプFLOATのcurrent_balanceという列があるとしましょう。

UPDATE `users` SET `current_balance`='231608.09' WHERE `user_id`=9;

MySQLが丸めを行ったため、current_balanceフィールドは231608に更新されます。これは、次のクエリを試す場合も同様です。

UPDATE `users` SET `current_balance`='231608.55' WHERE `user_id`=9;

Current_balanceフィールドは231609に更新されます

0
Tamer