如何在mysqlclient中处理(转义)%符号(C库)

时间:2012-12-20 18:32:19

标签: php session session-cookies mysql

我正在使用mysqlclient,

在我的一个查询中,如下所示

sprintf (query, "select user from pcloud_session where id = '%s'", sid);

这里有一段时间,这个sid的%符号就像示例

一样
2Cq%yo4i-ZrizGGQGQ71eJQ0

但是当有这个%这个查询总是失败时,我想我必须逃避这个%,但是如何?

我尝试使用\和%%,但这两个都不起作用,请在这里帮助我

更新

当使用session.hash_bits_per_character = 6时,在php会话中,默认字符集包含一个始终为urlencoded的字符(逗号)(此处为%2C)。这导致cookie值中包含此%2C,但会话db使用逗号而不是它。关于解决这个问题的任何想法?...抱歉混淆

由于

3 个答案:

答案 0 :(得分:2)

无需在MySQL查询文本中转义文字'%'

如果您说查询“总是失败”,那么调用mysql_query函数是否会返回错误?它是返回SQL异常代码,还是只是不返回您期望的结果集(行)?

对于调试,我建议您在调用query后回显sprintf字符串的内容。我们希望字符串的内容为:

select user from pcloud_session where id = '2Cq%yo4i-ZrizGGQGQ71eJQ0'

我没有看到SQL构造有什么问题(假设id中存在pcloud_session列,并且是字符数据类型。即使id被定义为整数类型,该语句也不会通常抛出异常,字符串文字只会被解释为2的整数值。)

在sprintf的目标格式中包含'%'文字应该没有问题。并且应该没有问题,包括MySQL查询文本中的'%'文字。

(当然,我假设通过调用sid函数来填充mysql_real_escape_string。)


同样,我建议你在调用sprintf之后回复query的内容。我还建议您确保没有其他代码与该字符串的内容混淆,这是作为mysql_query函数的参数传递的实际字符串。 (如果您使用mysql_real_query功能,请确保传递正确的长度。)


更新

Oxi说:“它没有返回SQL Exception代码,它只是没有返回我期望的结果[set]。我确实打印了查询,它打印了%in。”

@Oxi

以下是一大堆可能有助于您追踪问题的问题。

您是否从mysql命令行客户端运行该查询文本的测试,并返回您期望的行吗?

id列是否定义为VARCHAR(或CHAR),长度为(至少)24个字符?列上的排序规则是否设置为不区分大小写,还是区分大小写?

show create table pcloud_session ;

(我没有看到任何会导致字符集翻译出现问题的字符,但如果您的应用程序与数据库charactarset编码不匹配,则可能是问题的根源。)

您是否使用针对该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编码表示的,但它不是任何标准编码,因为它包含'%'和' - '字符。

答案 1 :(得分:0)

如果您要在没有接口库的情况下在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 ++包装器将为您提供更多支持。

答案 2 :(得分:0)

你真的不应该自己逃避弦乐。最安全的选择是让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。