데이터 베이스 MySQL 튜토리얼 深入理解mysql SET NAMES和mysql(i)_set_charset的区别

深入理解mysql SET NAMES和mysql(i)_set_charset的区别

Jun 07, 2016 pm 06:05 PM
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 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)   (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 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++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 Map과 기타 수집 프레임워크 비교: 장단점 분석 및 활용 시나리오 가이드 Java Map과 기타 수집 프레임워크 비교: 장단점 분석 및 활용 시나리오 가이드 Feb 19, 2024 pm 10:24 PM

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

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 메소드를 통해

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 유효 기간 설정 등과 같은 더 많은 다른 속성을 전달할 수도 있다는 것입니다.

Java 컬렉션 프레임워크에서 Map과 Set의 구현 및 차이점 Java 컬렉션 프레임워크에서 Map과 Set의 구현 및 차이점 Apr 12, 2024 pm 10:12 PM

Map과 Set의 차이점: 키-값과 고유성: Map은 키-값 쌍을 저장하고 Set은 고유한 요소를 저장합니다. Order: Map과 Set 중 HashMap과 HashSet은 순서가 없는 집합이고 LinkedHashMap과 LinkedHashSet은 순서가 있는 집합이며 TreeSet은 순서대로 정렬되어 있습니다. 변경 가능성: Map, LinkedHashMap 및 TreeSet은 변경 가능한 컬렉션이고 HashSet 및 LinkedHashSet은 변경 불가능한 컬렉션입니다. 목적: Map은 키-값 쌍 데이터에 사용되며, Set은 고유 요소 데이터에 사용됩니다.

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

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

See all articles