mysql - цитировать номера или нет? - PullRequest
45 голосов
/ 21 июля 2011

Например - я создаю базу данных и таблицу из 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');

Итак - в этих примерах я выбрал строку с помощью строки , которая фактически сохранена как INT в MySQL, а затем я вставил строку встолбец INT.

Я не совсем понимаю, почему это работает так, как работает здесь.Почему в столбец INT допускается вставка строки?

Могу ли я вставить все типы данных Mysql в виде строк?

Стандартно ли это поведение в разных СУБД?

спасибо!

Ответы [ 8 ]

61 голосов
/ 22 июля 2011

MySQL во многом похож на PHP и будет автоматически преобразовывать типы данных как можно лучше.Поскольку вы работаете с полем int (слева), он попытается также прозрачно преобразовать правую часть аргумента в int, поэтому '9' просто становится 9.

Строго говоря, кавычки не нужны и вынуждают MySQL выполнять преобразование / преобразование типов, поэтому это тратит немного процессорного времени.На практике, если вы не выполняете операцию размером с Google, такие издержки преобразования будут микроскопически малы.

8 голосов
/ 22 июля 2016

Вы никогда не должны заключать в кавычки цифры.Для этого есть веская причина.

Настоящая проблема сводится к приведению типов.Когда вы помещаете числа в кавычки, они обрабатываются как строка, и MySQL должен преобразовать их в число, прежде чем он сможет выполнить запрос.Хотя это может занять небольшое количество времени, реальные проблемы начинают возникать, когда MySQL плохо выполняет преобразование вашей строки.Например, MySQL преобразует базовые строки, такие как «123», в целое число 123, но преобразует некоторые большие числа, например «18015376320243459», в число с плавающей запятой.Поскольку с плавающей запятой можно округлить, ваши запросы могут возвращать противоречивые результаты. Узнайте больше о приведении типов здесь .В зависимости от аппаратного и программного обеспечения вашего сервера, эти результаты могут отличаться.MySQL объясняет это.

Если вы беспокоитесь о SQL-инъекциях, всегда сначала проверяйте значение и используйте PHP, чтобы убрать любые не числа.Для этого вы можете использовать preg_replace: preg_replace("/[^0-9]/", "", $string)

Кроме того, если вы пишете SQL-запросы с кавычками, они не будут работать в базах данных, таких как PostgreSQL или Oracle.

3 голосов
/ 23 апреля 2013

Отметьте это, вы можете лучше понять ...

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 голосов
/ 22 июля 2011

AFAIK это стандартно, но считается плохой практикой, потому что
- использование его в предложении WHERE не позволит оптимизатору использовать индексы (план объяснения должен показать это)
- база данных должна сделать дополнительную работу для преобразования строки в число
- если вы используете это для чисел с плавающей точкой ('9,4'), у вас возникнут проблемы, если клиент и сервер используют разные языковые настройки (9,4 против 9,4)

Короче говоря: не делай этого (но YMMV) * ​​1006 *

3 голосов
/ 22 июля 2011

Это не стандартное поведение.

Для MySQL 5.5. это режим SQL по умолчанию

mysql> select @@sql_mode;
+------------+
| @@sql_mode |
+------------+
|            |
+------------+
1 row in set (0.00 sec)

ANSI и TRADITIONAL используются более строго Oracle и PostgreSQL. Режимы SQL Разрешения MySQL должны быть установлены ЕСЛИ И ТОЛЬКО ЕСЛИ вы хотите сделать SQL более ANSI-совместимым. В противном случае вам не нужно ничего трогать. Я никогда этого не делал.

1 голос
/ 22 июля 2011

Вам не нужно указывать цифры, но это всегда хорошая привычка, если вы делаете это последовательно.

0 голосов
/ 12 февраля 2019

Это зависит от типа столбца! если вы запустите

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

в mysql / maria-db вы получите все записи, где username НЕДЕЙСТВИТЕЛЕН.

Всегда заключайте в кавычки значения, если столбец имеет тип string (char, varchar, ...), иначе вы получите неожиданные результаты!

0 голосов
/ 14 июня 2014

Проблема, скажем, в том, что у нас есть таблица с именем users, в которой есть столбец с именем current_balance типа FLOAT, если вы выполните этот запрос:

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

Поле current_balance будет обновлено до 231608, потому что MySQL сделал округление, аналогично, если вы попробуете этот запрос:

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

Поле current_balance будет обновлено до 231609

...