Speaking of this, try to use mysqli_set_charset (mysqli: set_charset) instead of "set names". Of course, this content is also described in the PHP manual, but it does not explain why.
Recently, several friends asked me this question. Why?
When there are too many people to ask, I think I can write a blog to introduce this part of content.
First, many people do not know what "set names" is,
In my previous articles, I went deep into MySQL Character Set settings and introduced the "environment variables" of character_set_client/character_set_connection/character_set_results,
These three variables respectively tell the MySQL server, the client's replica set, the replica set when it is transmitted to the MySQL server, and the replica set that expects the results returned by MySQL.
For example, by using "set names utf8", I will tell the server that I am using UTF-8 encoding. I hope you will also return the UTF-8 encoding query results to me.
Generally, it is enough to use "set names" to ensure the correctness. Why does the manual recommend mysqli_set_charset (PHP> = 5.0.5?
First, let's take a look at what mysqli_set_charset has done (note that mysql_set_charset is similar to the asterisk annotation ):
Copy codeThe Code is as follows:
// 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 )){
// ** Call the corresponding libmysql Function
RETURN_FALSE;
}
RETURN_TRUE;
}
What does mysql_set_character_set do?
Copy codeThe Code is as follows:
// Mysql-5.1.30-SRC/libmysql/client. c, line 3166:
Int STDCALL mysql_set_character_set (MYSQL * mysql, const char * cs_name)
{
Struct charset_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;
}
}
// The following content is omitted
We can see that in addition to "set names", mysqli_set_charset has done one more step:
Copy codeThe Code is as follows:
Sprintf (buff, "set names % s", cs_name );
If (! Mysql_real_query (mysql, buff, strlen (buff )))
{
Mysql-> charset = cs;
}
What is the role of charset, a member of the mysql core structure?
This tells us about mysql_real_escape_string (). The difference between this function and mysql_escape_string is that it considers the "current" character set. Where can this current character set come from?
By the way, you guessed it was mysql-> charset.
Mysql_real_string in the determination of wide Character Set characters, according to the member variables to adopt different policies, for example, if it is UTF-8, then libmysql/ctype-utf8.c will be used.
Check the instance. The default mysql connection character set is latin-1 (Classic 5c problem ):
Copy codeThe Code is as follows:
<? Php
$ Db = mysql_connect ('localhost: 100', 'root', '123 ');
Mysql_select_db ("test ");
$ A = "\ x91 \ x5c"; // gbk encoding for "bytes". The low byte is 5c, that is, "\" in ascii "\"
Var_dump (addslashes ($ ));
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 ));
?>
Because the gbk encoding of "bytes" is low-byte 5c, that is, "\" in ascii, And because mysql (I) _ set_charset affects mysql-> charset, the default value is mysql> charset at other times. Therefore, the result is:
Copy codeThe Code is as follows:
$ Php-f 5c. php
String (3) "bytes \"
String (3) "bytes \"
String (3) "bytes \"
String (2) "success"
Do you know it now?