当使用thinkORM DB工作时,单表没问题,只要有别名就会将条件变成字符
workerman/webman-framework:2.1.2
webman/think-orm:2.1.6
$res = Db::table('user')->where('uid',1)->fetchSql()->find();
print_r($res);
SELECT * FROM user
WHERE uid
= 1 LIMIT 1
$res = Db::table('user')->alias('a')->where('a.uid', 1)->fetchSql()->find();
print_r($res);
SELECT * FROM user
a
WHERE a
.uid
= '1' LIMIT 1
加了别名条件就会从整数变成字符,但是联表肯定需要用别名,变成字符可能会导致索引失效。
sql语句不会强行cast, 将他转成字符串的在获取结果集之后
你看下执行的SQL语句,不要看php的结果
12 Prepare SHOW FULL COLUMNS FROM
user
12 Execute SHOW FULL COLUMNS FROM
user
12 Prepare SELECT FROM
user
WHEREuid
= ? LIMIT 112 Close stmt
12 Prepare SELECT FROM
user
WHEREuid
= ? LIMIT 112 Execute SELECT FROM
user
WHEREuid
= 1 LIMIT 112 Prepare SELECT FROM
user
a
WHEREa
.uid
= ? LIMIT 112 Close stmt
12 Execute SELECT * FROM
user
a
WHEREa
.uid
= '1' LIMIT 1打开通用日志,看到的是这样,是真实转成字符了。
你用在mysql里用explain一下这个sql语句就明白了
int类型字段的查询条件会隐式转换成数字,所以值是否时字符串无影响,如果该字段有索引,会走索引,所以以下是等价的
char类型则不一样,以下不是等价的
结论是,转成字符串,更多是为了处理char类型时的差异
就是这个隐式转换,一般情况下是正常的,只是我在查慢SQL时,复杂的SQL联表查询,他走的索引不对,然后我就试着将这些条件是int的,全部改成了int,然后索引对了。查询时间从3秒多降到了0.几秒。所以我才想着要怎么改这个。现在我的解决办法是拆SQL,也降下来了。
然后我试了laravel的数据库操作组件,他就是正常的,你传数字就是数字,传字符就是字符。旧项目是没办法了,新项目大概率是会换成laravel的组件。
多连表查询并且多个聚合索引, 我一般都会手动指定/强制指定索引
直接写视图.
实际上在使用主键检索的时候,mysql会自己转换参数,默认走的还是主键索引,至于其他字段就不好说了~
简单的查询是没问题的,字符和数字没区别,复杂点的就出问题了,一个表有多个复合索引,然后就容易出问题。
因为我也不是所有的都这样,遇到问题SQL拿出来explain一下,才发现不对,然后当时试着将其他复杂一些的SQL explain一下,又是正常的。所以我也慒。
不好解决就加强制索引
其实我印象中是直接执行SQL语句会导致全字符串类型;但是使用预编译的语句就会是本来的类型