我是一个C程序我有一个函数,它接受一个域名参数:
void db_domains_query(char *name);
使用mysql_query()我测试域名是否存在于数据库中。如果不是这样,我插入新的域名:
...
char *query[400];
sprintf(query, "SELECT Id, DomainName FROM domains WHERE domainName LIKE '%s'", name);
if (mysql_query(con, query))
finish_with_error(con);
MYSQL_RES *result = mysql_store_result(con);
if (result == NULL)
finish_with_error(con);
MYSQL_ROW row;
if ((row = mysql_fetch_row(result)))
printf("Element exists : %s %s\n", row[0], row[1]);
else
printf("Element %s doesn't found\n", name);
// Then insert the new domain name ...
如果 name 仅包含“普通字符”,则此部分代码可以正常工作。但是,对于包含“特殊字符”的域名,查询似乎不正确,即使它们位于数据库中,例如:
Element exists : 100 undaben.de
Element ®here.com is not found.
name =§travel.us:Element §travel.us is not found.
表格的摘录:
+-----+--------------+
| id | domainname |
+-----+--------------+
| 100 | undaben.de |
| 162 | §travel.us |
| 197 | ®here.com |
+-----+--------------+
字段 domainname 的排序规则是utf8_unicode_ci。 那么如何将包含“特殊”域名的所有域名传递给mysql_query呢?
答案 0 :(得分:0)
我建议您避免使用C API,除非您有令人信服的理由使用它。 C ++ API更有用。
您正在查询字符串中嵌入参数。这有许多问题,包括安全风险。如果你坚持这种方法,为了防止参数搞乱你的查询问题,你需要确保一些事情:
sprintf
函数的输入时,您需要确保特殊字符(如©)也以UTF-8编码。 '
)。为此,您可以使用mysql_real_escape_string
中提到的 sql = "select count(*) from addresses where id = ?";
// Open Database
openDB(&conn);
// Allocate statement handler
stmt = mysql_stmt_init(conn);
if (stmt == NULL) {
print_error(conn, "Could not initialize statement handler");
return;
}
// Prepare the statement
if (mysql_stmt_prepare(stmt, sql, strlen(sql)) != 0) {
print_stmt_error(stmt, "Could not prepare statement");
return;
}
// Initialize the result column structures
memset (param, 0, sizeof (param)); /* zero the structures */
memset (result, 0, sizeof (result)); /* zero the structures */
// Init param structure
// Select
param[0].buffer_type = MYSQL_TYPE_LONG;
param[0].buffer = (void *) &myId;
param[0].is_unsigned = 0;
param[0].is_null = 0;
param[0].length = 0;
// Result
result[0].buffer_type = MYSQL_TYPE_LONG;
result[0].buffer = (void *) &myNumAddresses;
result[0].is_unsigned = 0;
result[0].is_null = &is_null[0];
result[0].length = 0;
// Bind param structure to statement
if (mysql_stmt_bind_param(stmt, param) != 0) {
print_stmt_error(stmt, "Could not bind parameters");
return;
}
// Bind result
if (mysql_stmt_bind_result(stmt, result) != 0) {
print_stmt_error(stmt, "Could not bind results");
return;
}
// Set bind parameters
myId = id;
// Execute!!
if (mysql_stmt_execute(stmt) != 0) {
print_stmt_error(stmt, "Could not execute statement");
return;
}
if (mysql_stmt_store_result(stmt) != 0) {
print_stmt_error(stmt, "Could not buffer result set");
return;
}
// Init data
(*numAddresses) = 0;
// Fetch
if(mysql_stmt_fetch (stmt) == 0){
(*numAddresses) = myNumAddresses;
}
// Deallocate result set
mysql_stmt_free_result(stmt); /* deallocate result set */
// Close the statement
mysql_stmt_close(stmt);
// Close Database
closeDB(conn);
功能。但是,您很可能正在使用准备好的声明来解决这些问题。您仍然需要确保输入数据编码与客户端连接的编码匹配,但其他所有内容都应该更容易处理。
我使用C API粘贴参数化查询的示例,其中包含预编译的语句(例如来自Efficiently escaping quotes in C before passing to mysql_query)。请注意,该示例适用于整数,而不是字符串,您需要适应您的用例。
eb labs cleanup-versions --num-to-leave=some_value
同样,如果你可以使用其他一些客户端库(比如C ++客户端),你的代码会更短,更易读。
答案 1 :(得分:0)
我的不好,因为@jjmontes提到似乎发送的字符串是在'latin1'
中编码的。
在执行查询之前使用函数mysql_set_character_set(conn, "utf8")
解决了这个问题。
现在,我将尝试使用预备语句而不是查询字符串。
再次感谢!