mysqli_set_charset和SET NAMES使用抉择及优劣分析_PHP
最近公司组织了个PHP安全编程的培训, 其中涉及到一部分关于Mysql的”SET NAMES”和mysql_set_charset (mysqli_set_charset)的内容:
说到, 尽量使用mysqli_set_charset(mysqli:set_charset)而不是”SET NAMES”, 当然, 这个内容在PHP手册中也有叙及, 但是却没有解释为什么.
最近有好几个朋友问我这个问题, 到底为什么?
问的人多了, 我也就觉得可以写篇blog, 专门介绍下这部分的内容了.
首先, 很多人都不知道”SET NAMES”到底是做了什么,
我之前的文章深入MySQL字符集设置中, 曾经介绍过character_set_client/character_set_connection/character_set_results这三个MySQL的”环境变量”, 这里再简单介绍下,
这三个变量, 分别告诉MySQL服务器, 客户端的编码集, 在传输给MySQL服务器的时候的编码集, 以及期望MySQL返回的结果的编码集.
比如, 通过使用”SET NAMES utf8″, 就告诉服务器, 我用的是utf-8编码, 我希望你也给我返回utf-8编码的查询结果.
一般情况下, 使用”SET NAMES”就足够了, 也是可以保证正确的. 那么为什么手册又要说推荐使用mysqli_set_charset(PHP>=5.0.5)呢?
首先, 我们看看mysqli_set_charset到底做了什么(注意星号注释处, mysql_set_charset类似):
复制代码 代码如下:
//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)) {
//** 调用libmysql的对应函数
RETURN_FALSE;
}
RETURN_TRUE;
}
那mysql_set_character_set又做了什么呢?
复制代码 代码如下:
//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) (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) 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”以外, 还多做了一步:
复制代码 代码如下:
sprintf(buff, "SET NAMES %s", cs_name);
if (!mysql_real_query(mysql, buff, strlen(buff)))
{
mysql->charset= cs;
}
而对于mysql这个核心结构的成员charset又有什么作用呢?
这就要说说mysql_real_escape_string()了, 这个函数和mysql_escape_string的区别就是, 它会考虑”当前”字符集. 那么这个当前字符集从哪里来呢?
对了, 你猜的没错, 就是mysql->charset.
mysql_real_string在判断宽字符集的字符的时候, 就根据这个成员变量来分别采用不同的策略, 比如如果是utf-8, 那么就会采用libmysql/ctype-utf8.c.
看个实例, 默认mysql连接字符集是latin-1, (经典的5c问题):
复制代码 代码如下:
$db = mysql_connect('localhost:3737', 'root' ,'123456');
mysql_select_db("test");
$a = "\x91\x5c";//"慭"的gbk编码, 低字节为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));
?>
因为, “慭”的gbk编码低字节为5c, 也就是ascii中的”\”, 而因为除了mysql(i)_set_charset影响mysql->charset以外, 其他时刻mysql->charset都为默认值, 所以, 结果就是:
复制代码 代码如下:
$ php -f 5c.php
string(3) "慭\"
string(3) "慭\"
string(3) "慭\"
string(2) "慭"大家现在很清楚了吧?

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Interpretation der dynamischen SQL-Tags von MyBatis: Detaillierte Erläuterung der Verwendung von Set-Tags. MyBatis ist ein hervorragendes Persistenzschicht-Framework. Es bietet eine Fülle dynamischer SQL-Tags und kann Datenbankoperationsanweisungen flexibel erstellen. Unter anderem wird das Set-Tag zum Generieren der SET-Klausel in der UPDATE-Anweisung verwendet, die sehr häufig bei Aktualisierungsvorgängen verwendet wird. In diesem Artikel wird die Verwendung des Set-Tags in MyBatis ausführlich erläutert und seine Funktionalität anhand spezifischer Codebeispiele demonstriert. Was ist Set-Tag? Set-Tag wird in MyBati verwendet

Methoden zum Löschen von Elementen: 1. Verwenden Sie delete(), um das angegebene Element aus dem Set-Objekt zu löschen. Die Syntax lautet „setObj.delete(value);“ 2. Verwenden Sie clear(), um alle Elemente im Set-Objekt zu löschen Die Syntax lautet „setObj.delete(value);“ „setObj.clear();“.

Dieser Artikel basiert auf den Grundlagen von Python und stellt die Verwendung der Schlüsselwertspeicherstruktur dict vor. Es ist wichtig, ein unveränderliches Objekt als Schlüssel zu wählen ist eine Zeichenfolge.

Vorwort Es gibt zwei sehr ähnliche Methoden in der häufig verwendeten Auflistungsschnittstelle List in Java: Eset(intindex,Eelement);voidadd(intindex,Eelement); zwischen diesen beiden Methoden? Schauen wir uns als Nächstes die Unterschiede und Ähnlichkeiten zwischen diesen beiden Methoden in ArrayList an, unserer häufig verwendeten Sammlungsimplementierung. Schauen wir uns zunächst die Ähnlichkeiten zwischen diesen beiden Methoden in ArrayList an Sammlung, wie zum Beispiel das folgende Beispiel: #Fügen Sie ein F an der 2. Position der Sammlung ein. #Fügen Sie Listlist= über die Add-Methode ein

1. Überblick über das Map Collection Framework Das Map Collection Framework ist eine Schlüssel-Wert-Paar-Datenstruktur, die es Ihnen ermöglicht, Schlüssel zum Suchen und Speichern von Werten zu verwenden. Jeder Schlüssel in der Map ist einzigartig und kann nur einem Wert zugeordnet werden. Zu den gängigen Implementierungen im Kartensammlungs-Framework gehören HashMap, TreeMap und LinkedHashMap. 1.HashMapHashMap ist die am weitesten verbreitete Map-Implementierung in Java. Sie speichert Daten basierend auf Hash-Tabellen. HashMap bietet eine hervorragende Leistung und die zeitliche Komplexität von Such- und Einfügevorgängen beträgt O (1), garantiert jedoch nicht die Reihenfolge der Elemente. Democode: Mapmap=newHashMap

Die Set-Befehlssyntax SETkeyid[FIELDnamevalue...][EXseconds][NX|XX](OBJECTgeojson)|(POINTlatlonz)|(BOUNDSminlatminlonmaxlatmaxlon)|(HASHgeohash)|(STRINGvalue) Der Set-Befehl entspricht der Verwendung des Hash-Befehls In Redis handelt es sich ebenfalls um eine Kombination aus Schlüssel und ID. Der Unterschied besteht jedoch darin, dass der Set-Befehl von Tile38 auch weitere Attribute enthalten kann, z. B. das Anpassen des Feldes FIELD, das Festlegen des EX-Gültigkeitszeitraums usw

1.ListList ist eine geordnete Sammlung im Java-Sammlungsframework, die die Wiederholung von Elementen und den Zugriff auf Elemente über den Index ermöglicht. Zu den gängigen Implementierungsklassen von List gehören ArrayList, LinkedList und Vector. Im Folgenden wird gezeigt, wie ArrayList zum Speichern einer Reihe von Ganzzahlen verwendet wird: importjava.util.ArrayList;publicclassArrayListDemo{publicstaticvoidmain(String[]args){//Erstellen Sie ein ArrayList-Objekt ArrayListnumbers=newArr

Zu den üblichen Verwendungszwecken von Sets gehören das Erstellen eines Sets, das Hinzufügen von Elementen, das Löschen von Elementen, das Bestimmen, ob das Set leer ist, das Ermitteln der Größe des Sets, das Durchlaufen des Sets, das Suchen von Elementen und Set-Operationen. Detaillierte Einführung: 1. Erstellen Sie ein Set, Setset=newHashSet(); 2. Fügen Sie Elemente hinzu, set.add("java"); set.add("python");; 3. Elemente löschen, set.remove("java");
