백엔드 개발 PHP 튜토리얼 mysqli_set_charset和SET NAMES使用抉择及优劣分析_php实例

mysqli_set_charset和SET NAMES使用抉择及优劣分析_php实例

May 17, 2016 am 09:07 AM
charset set

最近公司组织了个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) "慭"大家现在很清楚了吧?
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

MyBatis 동적 SQL 태그의 Set 태그 기능에 대한 자세한 설명 MyBatis 동적 SQL 태그의 Set 태그 기능에 대한 자세한 설명 Feb 26, 2024 pm 07:48 PM

MyBatis 동적 SQL 태그 해석: Set 태그 사용법에 대한 자세한 설명 MyBatis는 풍부한 동적 SQL 태그를 제공하고 데이터베이스 작업 명령문을 유연하게 구성할 수 있는 탁월한 지속성 계층 프레임워크입니다. 그 중 Set 태그는 업데이트 작업에서 매우 일반적으로 사용되는 UPDATE 문에서 SET 절을 생성하는 데 사용됩니다. 이 기사에서는 MyBatis에서 Set 태그의 사용법을 자세히 설명하고 특정 코드 예제를 통해 해당 기능을 보여줍니다. Set 태그란 무엇입니까? Set 태그는 MyBati에서 사용됩니다.

자바스크립트에서 세트의 요소를 삭제하는 방법 자바스크립트에서 세트의 요소를 삭제하는 방법 Jan 12, 2022 am 10:56 AM

요소를 삭제하는 방법: 1. Set 객체에서 지정된 요소를 삭제하려면 delete()를 사용합니다. 구문은 "setObj.delete(value);"입니다. 2. Clear()를 사용하여 Set 객체의 모든 요소를 ​​삭제합니다. 구문은 "setObj.delete(value);" "setObj.clear();"입니다.

Python 프로그래밍에서 dict 및 set의 일반적인 사용 목록 Python 프로그래밍에서 dict 및 set의 일반적인 사용 목록 Jul 25, 2023 pm 04:52 PM

이 글은 Python의 기초를 바탕으로 dict와 set을 사용하는 방법을 소개합니다. 키-값 저장 구조를 사용하는 dict는 Python에서 가장 일반적으로 사용되는 키로 불변 객체를 선택하는 것이 중요합니다. 문자열입니다.

Java List의 set 메소드와 add 메소드의 차이점은 무엇입니까? Java List의 set 메소드와 add 메소드의 차이점은 무엇입니까? Apr 19, 2023 pm 07:49 PM

머리말 Java에서 일반적으로 사용되는 컬렉션 인터페이스 List에는 두 가지 매우 유사한 메서드가 있습니다. Eset(intindex,Eelement); voidadd(intindex,Eelement); 이 두 메서드는 모두 컬렉션의 지정된 위치에 지정된 요소를 삽입합니다. 차이점은 무엇입니까? 이 두 가지 방법 중? 다음으로, 일반적으로 사용되는 컬렉션 구현인 ArrayList를 통해 이 두 메서드 간의 차이점과 유사점을 살펴보겠습니다. 먼저 ArrayList에서 이 두 메서드 간의 유사점을 살펴보겠습니다. 예: #컬렉션의 두 번째 위치에 F를 삽입합니다. #Insert Listlist= add 메소드를 통해

Java Map과 기타 수집 프레임워크 비교: 장단점 분석 및 활용 시나리오 가이드 Java Map과 기타 수집 프레임워크 비교: 장단점 분석 및 활용 시나리오 가이드 Feb 19, 2024 pm 10:24 PM

1. 맵 수집 프레임워크 개요 맵 수집 프레임워크는 키를 사용하여 값을 찾고 저장할 수 있는 키-값 쌍 데이터 구조입니다. 맵의 각 키는 고유하며 하나의 값에만 연결될 수 있습니다. Map 컬렉션 프레임워크의 일반적인 구현에는 HashMap, TreeMap 및 LinkedHashMap이 포함됩니다. 1.HashMapHashMap은 Java에서 가장 널리 사용되는 Map 구현으로 해시 테이블을 기반으로 데이터를 저장합니다. HashMap은 성능이 뛰어나며 검색 및 삽입 작업의 시간 복잡도는 O(1)이지만 요소의 순서를 보장하지는 않습니다. 데모 코드: Mapmap=newHashMap

Springboot 통합 타일 클라이언트의 Set 명령을 구현하는 방법 Springboot 통합 타일 클라이언트의 Set 명령을 구현하는 방법 May 19, 2023 pm 01:37 PM

set 명령 구문 SETkeyid[FIELDnamevalue...][EXseconds][NX|XX](OBJECTgeojson)|(POINTlatlonz)|(BOUNDSminlatminlonmaxlatmaxlon)|(HASHgeohash)|(STRINGvalue) set 명령은 hash 명령 사용과 동일합니다. redis에서도 키와 ID의 조합이지만 차이점은 Tile38의 set 명령이 FIELD 필드 사용자 정의, EX 유효 기간 설정 등과 같은 더 많은 다른 속성을 전달할 수도 있다는 것입니다.

집합의 일반적인 용도 집합의 일반적인 용도 Oct 24, 2023 am 11:25 AM

집합의 일반적인 용도에는 집합 만들기, 요소 추가, 요소 삭제, 집합이 비어 있는지 확인, 집합 크기 가져오기, 집합 순회, 요소 찾기 및 집합 작업이 포함됩니다. 자세한 소개: 1. 세트 생성, Setset=newHashSet() 2. 요소 추가, set.add("java"); set.add("python");; 3. set.remove("java") 등의 요소를 삭제합니다.

PHP SPL 데이터 구조: 애플리케이션 성능을 향상시키는 비밀 PHP SPL 데이터 구조: 애플리케이션 성능을 향상시키는 비밀 Feb 19, 2024 pm 11:12 PM

SPL 데이터 구조의 개념 PHPSPL(표준 PHP 라이브러리)에는 PHP의 기본 데이터 유형을 향상시키도록 설계된 일련의 데이터 구조와 반복자 클래스가 포함되어 있습니다. 이러한 구조는 다양한 데이터를 효율적으로 저장 및 조작하고 일관된 인터페이스와 유연한 반복 메커니즘을 제공하도록 최적화되었습니다. 핵심 SPL 데이터 구조 SPL 라이브러리는 다음을 포함한 다양한 데이터 구조를 제공합니다. LinkedList: 빠른 삽입, 삭제 및 검색을 허용하는 이중 연결 목록입니다. 스택: 스택 작업을 위한 LIFO(후입선출) 데이터 구조입니다. 대기열: 대기열 작업을 위한 FIFO(선입선출) 데이터 구조입니다. 맵: 효율적인 키 조회 및 데이터 저장을 제공하는 키-값 쌍 모음입니다. 세트: 고유한 값 수집, 빠른 멤버 조회 및 수집 지원

See all articles