$q=2; ① $sql="select * from user where id ='".$q."'"; ② $sql="select * from user where id ='$q'"; ③ $sql="select * from user where id =$q";
以上三条语句执行效果是一样的 ①②里面$q是字符串型的吧 ③的$q是整型 我这样理解不知道对不对
user表里的id字段设置的是int 为何查询的时候是字符串型的也能查出来呢
菜鸟在此谢过
走同样的路,发现不同的人生
这个不只是作为主键会产生问题,作为其他索引键也会有类似问题。 int型索引字段,查询时加”,不会导致查询时不使用索引, 而字符换类型字段,查询不加”,却会导致查询时不适用索引, 而且还有一点是如果没有这个单引号,Innodb的存储引擎表的查询都会因为无索引可以,而上升为表级锁定
找到一篇介绍这个文章:http://www.zendstudio.net/archives/single-quotes-or-no-single-quotes-in-sql-query/
@江湖大虾仁 的答案是说插入数据时候,数据类型的问题,这个和MySQL的严格模式也有关系,严格模式下对语法要求更严格,那时候就不是warning了。
在查询条件里的单引号问题,这个主要考虑是不是影响使用索引,上面引文里说的很明白,对int无所谓的,但是对char就有区别了。
int
char
注:没有测试严格模式下查询语句中 int 字段值加不加单引号 会不会报错。
严格模式
针对 @R.ming 的回答我更新下。我想表达的是mysql在类型不同的情况下他会自动进行类型转换,这不光是在数据插入的时候才会做,在数据更新、查询和删除的时候都会这么做。
老规矩,上例子。(重点是最后一个select)
mysql> create table temp(a varchar(10)); Query OK, 0 rows affected (0.01 sec) mysql> insert into temp values('a'); Query OK, 1 row affected (0.01 sec) mysql> insert into temp values('1'); Query OK, 1 row affected (0.00 sec) mysql> select * from temp where a = 1; +------+ | a | +------+ | 1 | +------+ 1 row in set, 1 warning (0.01 sec) mysql> select * from temp where a = 0; +------+ | a | +------+ | a | +------+ 1 row in set, 1 warning (0.00 sec)
反对公子的答案,这个和php无关,对于php来说这三条sql语句都只是普通的字符串而已。楼主这个问题是因为mysql他做了兼容处理。对于字段是int类型的,如果你传入字符串(无论是在select, insert 还是 update),他会尝试转为数字的(类似于php中的intval)。具体可以看下面贴的这个例子。
另外,如果在诸如postgresql之类的数据库上,这种类型不符是会抛错误的。
p.s. 由于mysql的这种特性,一般推荐无论是否是字符串类型,全部加上单引号以降低sql注入的风险。← 不是说加了单引号就无法注入了,降低而已。 再p.s. 更推荐prepared statement
mysql> create table temp (k int); Query OK, 0 rows affected (0.02 sec) mysql> desc temp; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | k | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ 1 row in set (0.04 sec) mysql> insert into temp values(1),(2),(3),('a'); Query OK, 4 rows affected, 1 warning (0.01 sec) Records: 4 Duplicates: 0 Warnings: 1 mysql> select * from temp; +------+ | k | +------+ | 1 | | 2 | | 3 | | 0 | +------+ 4 rows in set (0.00 sec) mysql> update temp set k = 'a' where k = 1; Query OK, 1 row affected, 1 warning (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 1 mysql> update temp set k = '20' where k = 2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update temp set k = '30a' where k = 3; Query OK, 1 row affected, 1 warning (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 1 mysql> select * from temp; +------+ | k | +------+ | 0 | | 20 | | 30 | | 0 | +------+ 4 rows in set (0.00 sec)
PHP里面数据库读取是不分字段类型的,这个好像被很多大神吐槽过了。
mysql下直接执行下面两条语句效果一样,是数据库的原因,跟PHP没有关系虽然PHP本身是弱类型。select * from user where id ='1';select * from user where id =1;
select * from user where id ='1';
select * from user where id =1;
找到一篇介绍这个文章:
http://www.zendstudio.net/archives/single-quotes-or-no-single-quotes-in-sql-query/
@江湖大虾仁 的答案是说插入数据时候,数据类型的问题,这个和MySQL的严格模式也有关系,严格模式下对语法要求更严格,那时候就不是warning了。
在查询条件里的单引号问题,这个主要考虑是不是影响使用索引,上面引文里说的很明白,对
int
无所谓的,但是对char
就有区别了。注:没有测试
严格模式
下查询语句中int
字段值加不加单引号 会不会报错。针对 @R.ming 的回答我更新下。我想表达的是mysql在类型不同的情况下他会自动进行类型转换,这不光是在数据插入的时候才会做,在数据更新、查询和删除的时候都会这么做。
老规矩,上例子。(重点是最后一个select)
反对公子的答案,这个和php无关,对于php来说这三条sql语句都只是普通的字符串而已。楼主这个问题是因为mysql他做了兼容处理。对于字段是int类型的,如果你传入字符串(无论是在select, insert 还是 update),他会尝试转为数字的(类似于php中的intval)。具体可以看下面贴的这个例子。
另外,如果在诸如postgresql之类的数据库上,这种类型不符是会抛错误的。
p.s. 由于mysql的这种特性,一般推荐无论是否是字符串类型,全部加上单引号以降低sql注入的风险。← 不是说加了单引号就无法注入了,降低而已。
再p.s. 更推荐prepared statement
PHP里面数据库读取是不分字段类型的,这个好像被很多大神吐槽过了。
mysql下直接执行下面两条语句效果一样,是数据库的原因,跟PHP没有关系虽然PHP本身是弱类型。
select * from user where id ='1';
select * from user where id =1;