溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何正確的使用mysqli_set_charset和SET NAMES

發(fā)布時(shí)間:2021-02-04 16:57:47 來源:億速云 閱讀:356 作者:Leah 欄目:開發(fā)技術(shù)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)如何正確的使用mysqli_set_charset和SET NAMES,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

 代碼如下:


//php-5.2.11-SRC/ext/mysqli/mysqli_nonapi.c line 342
PHP_FUNCTION(mysqli_set_charset)
{
MY_MYSQL*mysql;
zval*mysql_link;
char *cs_name = NULL;
unsigned int len;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis()
, "Os", &mysql_link, mysqli_link_class_entry, &cs_name, &len) == FAILURE) {
return;
}
MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link"
, MYSQLI_STATUS_VALID);
if (mysql_set_character_set(mysql->mysql, cs_name)) {
//** 調(diào)用libmysql的對(duì)應(yīng)函數(shù)
RETURN_FALSE;
}
RETURN_TRUE;
}


那mysql_set_character_set又做了什么呢?

復(fù)制代碼 代碼如下:


//mysql-5.1.30-SRC/libmysql/client.c, line 3166:
int STDCALLmysql_set_character_set(MYSQL*mysql, const char *cs_name)
{
structcharset_info_st *cs;
const char *save_csdir= charsets_dir;
if (mysql->options.charset_dir)
charsets_dir= mysql->options.charset_dir;
if (strlen(cs_name) < MY_CS_NAME_SIZE &&
(cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
{
char buff[MY_CS_NAME_SIZE + 10];
charsets_dir= save_csdir;
/* Skip execution of "SET NAMES" for pre-4.1 servers */
if (mysql_get_server_version(mysql) < 40100)
return 0;
sprintf(buff, "SET NAMES %s", cs_name);
if (!mysql_real_query(mysql, buff, strlen(buff)))
{
mysql->charset= cs;
}
}
//以下省略


我們可以看到, mysqli_set_charset除了做了”SET NAMES”以外, 還多做了一步:

復(fù)制代碼 代碼如下:


sprintf(buff, "SET NAMES %s", cs_name);
if (!mysql_real_query(mysql, buff, strlen(buff)))
{
mysql->charset= cs;
}


而對(duì)于mysql這個(gè)核心結(jié)構(gòu)的成員charset又有什么作用呢?
這就要說說mysql_real_escape_string()了, 這個(gè)函數(shù)和mysql_escape_string的區(qū)別就是, 它會(huì)考慮”當(dāng)前”字符集. 那么這個(gè)當(dāng)前字符集從哪里來呢?
對(duì)了, 你猜的沒錯(cuò), 就是mysql->charset.
mysql_real_string在判斷寬字符集的字符的時(shí)候, 就根據(jù)這個(gè)成員變量來分別采用不同的策略, 比如如果是utf-8, 那么就會(huì)采用libmysql/ctype-utf8.c.
看個(gè)實(shí)例, 默認(rèn)mysql連接字符集是latin-1, (經(jīng)典的5c問題):

復(fù)制代碼 代碼如下:


<?php
$db = mysql_connect('localhost:3737', 'root' ,'123456');
mysql_select_db("test");
$a = "\x91\x5c";//"慭"的gbk編碼, 低字節(jié)為5c, 也就是ascii中的"\"
var_dump(addslashes($a));
var_dump(mysql_real_escape_string($a, $db));
mysql_query("set names gbk");
var_dump(mysql_real_escape_string($a, $db));
mysql_set_charset("gbk");
var_dump(mysql_real_escape_string($a, $db));
?>


因?yàn)? “慭”的gbk編碼低字節(jié)為5c, 也就是ascii中的”\”, 而因?yàn)槌薽ysql(i)_set_charset影響mysql->charset以外, 其他時(shí)刻mysql->charset都為默認(rèn)值, 所以, 結(jié)果就是:

復(fù)制代碼 代碼如下:


$ php -f 5c.php
string(3) "慭\"
string(3) "慭\"
string(3) "慭\"
string(2) "慭"大家現(xiàn)在很清楚了吧?

上述就是小編為大家分享的如何正確的使用mysqli_set_charset和SET NAMES了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI