在连接上调用SET NAMES 等同于调用set_charset,前提是您既不调用get_charset 也不调用mysql_real_escape_string(和朋友)。
当您调用set_charset 时,PHP 会做两件事。首先,它在连接上调用SET NAMES。其次,它会记住您设置的字符集。该状态信息稍后仅用于get_charset 和mysql_real_escape_string(和朋友)函数。因此,如果你不使用这些函数,那么你可以考虑两个等价的。
让我们走源:
- Userland 函数
mysql_set_charset 和 mysqli_set_charset 调用...
- 引擎函数
mysql_set_character_set调用...
-
引擎宏mysqlnd_set_character_set,其定义为:
#define mysqlnd_set_character_set(conn, cs) \
((conn)->data)->m->set_charset((conn)->data, (cs)))
并扩展到...
-
MYSQLND_METHOD(mysqlnd_conn_data, set_charset) 其中contains 如下代码(编号供讨论,这些不是实际的源代码行号):
1 if (PASS == conn->m->local_tx_start(conn, this_func)) {
2 char * query;
3 size_t query_len = mnd_sprintf(&query, 0, "SET NAMES %s", csname);
4
5 if (FAIL == (ret = conn->m->query(conn, query, query_len))) {
6 php_error_docref(NULL, E_WARNING, "Error executing query");
7 } else if (conn->error_info->error_no) {
8 ret = FAIL;
9 } else {
10 conn->charset = charset;
11 }
12 mnd_sprintf_free(query);
13
14 conn->m->local_tx_end(conn, this_func, ret);
15 }
如您所见,PHP 在连接本身上调用SET NAMES(第 3 行)。 PHP 还跟踪刚刚设置的字符集(第 10 行)。 cmets 进一步讨论了conn->charset 会发生什么,但我只想说它最终只出现在get_charset 和mysql_real_escape_string(和朋友)中。
因此,如果您不关心此状态,并且您同意既不使用 get_charset 也不使用 mysql_real_escape_string,那么您可以在连接本身上调用 SET NAMES 而不会产生不良影响。
顺便说一句,我从来没有这样做过,但看起来用-DPHP_DEBUG=1 编译PHP 可以通过各种DBG 宏进行大量调试。这对于查看您的代码如何通过此块可能很有用。