我正在使用mysqlclient,
在我的一个查询中,如下所示
sprintf (query, "select user from pcloud_session where id = '%s'", sid);
在这里,有时这个边带有%符号,就像例子
2Cq%yo4i-ZrizGGQGQ71eJQ0
但是当有这个%时,这个查询总是失败,我想我必须转义这个%,但是怎么转义呢?
我尝试了'和%%,但这两个都不工作,请帮助我这里
更新:
使用session时。hash_bits_per_character = 6,在php会话中,默认的字符集包含一个字符(逗号),该字符将始终被urlencoded(这里是%2C)。这导致cookie值中有%2C,但会话数据库中有一个逗号代替它。有什么办法解决这个问题吗?很抱歉造成混乱
谢谢
MySQL查询文本中不需要转义文字'%'
当你说查询"总是失败",它是调用mysql_query
函数返回一个错误吗?它是否返回SQL异常代码,或者它只是不返回您期望的结果集(行)?
为了调试,我建议在调用sprintf
后,回显query
字符串的内容。我们期望字符串的内容是:
select user from pcloud_session where id = '2Cq%yo4i-ZrizGGQGQ71eJQ0'
和我没有看到任何错误的SQL结构(假设id
列存在于pcloud_session
和字符数据类型。即使id被定义为整数类型,该语句通常也不会抛出异常,字符串字面值只会被解释为2的整数值。
在sprint的目标格式中包含'%'字面值应该没有问题。在MySQL查询文本中包含'%'文字应该没有问题。
(当然,我假设sid
是由对mysql_real_escape_string
函数的调用填充的)
再次,我建议您在调用sprintf之后回显query
的内容。我还建议您确保没有其他代码与该字符串的内容混淆,这是作为参数传递给mysql_query
函数的实际字符串。(如果您使用的是mysql_real_query
函数,那么请确保您传递的长度是正确的。)
更新
Oxi说:"它没有返回SQL异常代码,它只是没有返回我期望的结果[集]。"我确实打印了查询,它打印了%。"
@ ox
这里有一大堆问题可以帮助你找到问题。
您是否从mysql命令行客户端运行该查询文本的测试,并且返回您期望的行?
是id
列定义为VARCHAR(或CHAR)的长度(至少)24个字符?列上的排序设置为不区分大小写还是区分大小写?
show create table pcloud_session ;
(我没有看到任何会导致字符集转换问题的字符,尽管如果应用程序不匹配数据库字符集编码,这可能是问题的根源。)
您是否对id列使用LIKE谓词测试过查询?
SELECT id, user FROM pcloud_session WHERE id LIKE '2Cq'%yo4i-%' ESCAPE ''''
ORDER BY id LIMIT 10 ;
SELECT id, user FROM pcloud_session WHERE id LIKE '2Cq%'
ORDER BY id LIMIT 10 ;
当您期望一行时,您是否没有返回行?返回的行是否太多,或者得到的行是否与预期的行不同?
对于id
列来说,这是一个奇怪的值。起初,它看起来几乎像是用base-64编码表示的值,但它不是任何标准编码,因为它包含'%'和'-'字符。
如果您打算在没有接口库的情况下在C中执行此操作,则必须使用mysql_real_escape_string
来执行正确的SQL转义。
在MySQL内部使用'% inside of a string, though, as the only context in which it has meaning is either directly in
printf type functions or as an argument to
LIKE '不应该有任何本质上的错误。
这被证明是非常烦人的,但这是绝对必要的。这将使你的代码更加复杂,这就是为什么在C中使用低级MySQL通常是一个坏主意。c++包装器将为您提供更多的支持。
您真的不应该自己转义字符串。最安全的选择是让MySQL API为你处理它。
对于最大长度为n的字符串,首先分配一个长度为2*n+1的字符串:
int sidLength = strlen(sid);
// worst-case, we need to escape every character, plus a byte for the ASCIIZ
int maxSafeSidLength = sidLength * 2 + 1;
char *safeSid = malloc(maxSafeSidLength);
// copy "sid" to "safeSid", escaping as appropriate
mysql_real_escape_string(mysql, safeSid, sid, sidLength);
// build the query
// ...
free(safeSid);
在dev.mysql.com的mysql_real_escape_string
页面上有一个更长的例子,其中他们构建了整个查询字符串,但上述方法应该适用于为sprintf提供safeSid。