MySQL的 – 报价号码或不?

例如 – 我从cli创build数据库和表,并插入一些数据:

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'); 

所以 – 在这些例子中,我select了一个string ,实际上存储为INT的string ,然后我插入一个string是一个INT列。

我不明白为什么这个工作方式在这里工作。 为什么允许将string插入到INT列中?

我可以将所有Mysql数据types作为string插入吗?

这是不同RDBMS的行为标准吗?

谢谢!

MySQL和PHP很像,它会尽可能地自动转换数据types。 既然你正在处理一个int字段(左边),它会尝试透明地将右边的参数转换为int,所以'9'就变成了9

严格来说,引号是不必要的,并强制MySQL进行types转换,所以浪费了一些CPU时间。 在实践中,除非您正在运行Google大小的操作,否则这种转换开销将变得微不足道。

你不应该把数字引号。 这是有道理的。

真正的问题归结为types转换。 当你把数字放在引号内时,它被视为一个string,MySQL必须把它转换成一个数字才能执行查询。 虽然这可能需要很短的时间,但是当MySQL没有很好地转换string时,真正的问题就开始出现了。 例如,MySQL会将“123”这样的基本string转换为整数123,但会将一些较大的数字(如“18015376320243459”)转换为浮点数。 由于浮点可以四舍五入,您的查询可能会返回不一致的结果。 详细了解这里的types转换 。 这取决于您的服务器硬件和软件,这些结果会有所不同。 MySQL解释了这一点。

如果您担心SQL注入,请务必首先检查值,并使用PHP去除任何非数字。 您可以使用preg_replace:preg_replace(“/ [^ 0-9] /”,“”,$ string)

另外,如果你用引号编写你的SQL查询,他们将不能在像PostgreSQL或Oracle这样的数据库上工作。

AFAIK这是标准的,但它被认为是不好的做法,因为
– 在WHERE子句中使用它将阻止优化器使用索引(解释计划应该显示)
– 数据库必须做额外的工作才能将string转换为数字
– 如果你使用浮点数字('9.4'),如果客户端和服务器使用不同的语言设置(9.4对9,4)

总之:不要这样做(但是YMMV)

这不是标准的行为。

对于MySQL 5.5。 这是默认的SQL模式

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

Oracle和PostgreSQL更严格地使用ANSI和TRADITIONAL。 MySQL允许的SQL模式必须设置为 IF和ONLY如果要使SQL更符合ANSI标准。 否则,你不必碰东西。 我从来没有这样做过。

你不需要引用数字,但是如果你这样做是一致的话,这总是一个好习惯。

检查这个,你可以更好地理解…

 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) 

问题是,假设我们有一个名为users的表,它有一个名为current_balance的FLOATtypes的列,如果你运行这个查询:

 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