在MySQL中设置名称utf8?


110

我经常在使用MySQL的PHP​​脚本中看到类似的内容

query("SET NAMES utf8");   

我从来没有为任何项目都这样做,所以我对此有两个基本问题。

  1. 这仅是通过PDO完成吗?
  2. 如果不是PDO特定的事情,那么这样做的目的是什么?我意识到它正在为mysql设置编码,但是我的意思是,我从未使用过它,所以为什么要使用它?

4
由于SQL注入,应避免使用“ SET NAMES utf8”。有关详细信息,请参见php.net/manual/en/mysqlinfo.concepts.charset.php。
masakielastic

3
@masakielastic我看不到在哪里设置“设置名称utf8”会对SQL注入造成威胁?使用适当的MySQL API线程在哪里?
宽带

3
对不起,我很抱歉。请参阅ircmaxell的答案:stackoverflow.com/a/12118602/531320只要使用UTF-8,Althogh“设置名称”都没有问题,将来使用GBK或Big5(中文)或Shift_JIS(日语)的可能性是不可否认的。
masakielastic

Answers:


74

每当您要将数据发送到服务器时,如果字符中不能用纯ASCII表示的字符(如“ñ”或“ö”),都需要使用该属性。

如果MySQL实例未配置为默认情况下期望来自客户端连接的UTF-8编码(很多取决于您的位置和平台)。

如果您不了解Unicode的工作原理,请阅读http://www.joelonsoftware.com/articles/Unicode.html

阅读是否使用“ SET NAMES”来查看SET NAMES的替代方案以及其确切含义。


3
“ö”和“ñ”是扩展的ASCII。您还会需要SET NAMES UTF8它们吗?

2
我发现我经常不得不添加utf8_decode($ my_text);。在PHP中获取特殊的UTF-8字符,以便在从MySQL查询数据时正确显示在网站上。我的表和列在MySQL中设置为UTF-8,因此是否有必要?
NexusRex 2011年

1
@ @ Vinko Vrsalovic:不一定...我所有文件都放在utf8中,但是我以前的托管人已将mysql charset设置为latin1,因为我没有告诉mysql我在utf8中发送了chars(因此设置了名称utf8),因此将它们存储了在看起来他们的拉丁字符集和我所有的特殊字符(斯洛文尼亚CSZ)为超限被车-一件事:当你在phpMyAdmin进行搜索,你不会找到的结果,因为C是像等等
埃里克Čerpnjak

请注意,它还指定服务器用于将结果发送回客户端的字符集,因此在接收此数据时也需要使用此字符集,例如使用一条SELECT语句。
Leopoldo Sanczyk 2015年

@蒂姆 实际上没有“扩展ASCII”之类的东西。有很多不同的编码,都可以称为扩展ASCII(任何单字节字符集,前半部分与ASCII相同,并且有很多这样的编码)。
TRiG

43

手册

SET NAMES指示客户端将使用什么字符集将SQL语句发送到服务器。

更详细地讲((再一次从手册中免费提出):

SET NAMES指示客户端将使用什么字符集将SQL语句发送到服务器。因此,SET NAMES'cp1251'告诉服务器,“将来来自此客户端的传入消息使用字符集cp1251。” 它还指定服务器用于将结果发送回客户端的字符集。(例如,如果使用SELECT语句,它指示要用于列值的字符集。)


6
我爱你。刚刚度过了我的夜晚!
karim79 2012年

34

正确地进行编码确实很棘手-层太多了:

  • 浏览器
  • 的PHP
  • MySQL的

来自PHP的SQL命令“ SET CHARSET utf8”将确保客户端(PHP)可以在utf8中获取数据,无论它们如何存储在数据库中。当然,它们需要首先正确存储。

DDL定义与实际数据

为表/列定义的编码实际上并不意味着数据在该编码中。如果您碰巧将一个表定义为,utf8但存储为不同的编码,那么MySQL会将它们视为utf8,这会给您带来麻烦。这意味着您必须先解决此问题。

检查什么

您需要检查每层数据流的编码方式。

  • 检查HTTP标头,标头。
  • 检查请求主体中真正发送的内容。
  • 不要忘记,MySQL几乎到处都有编码:
    • 数据库
    • 桌子
    • 服务器整体
    • 客户
      确保到处都有合适的客户。

转换次数

如果您在例如中接收数据windows-1250,并且想要存储在中utf-8,则在存储之前使用此SQL:

SET NAMES 'cp1250';

如果您在DB中有数据windows-1250并且想要检索utf8,请使用:

SET CHARSET 'utf8';

少量注意事项:

  • 不要过于依赖“智能”工具来显示数据。例如,phpMyAdmin确实(在我使用它时在做)编码非常糟糕。而且它遍历所有层,因此很难找出。
  • 另外,Internet Explorer确实具有基于奇怪规则“猜测”编码的愚蠢行为。
  • 使用简单的编辑器,您可以在其中切换编码。我推荐MySQL Workbench。

19

此查询应在创建或更新数据库中数据的查询之前编写,该查询如下所示:

mysql_query("set names 'utf8'");

请注意,您应该在标头中编写要使用的编码,例如,如果您使用的是utf-8,请在标头中添加这样的编码,否则它将导致Internet Explorer出现问题

所以你的页面看起来像这样

<html>
    <head>
        <title>page title</title>
        <meta charset="UTF-8" />   
    </head>
    <body>
    <?php
            mysql_query("set names 'utf8'");   
            $sql = "INSERT * FROM ..... ";  
            mysql_query($sql);
    ?>    

    </body>
</html>

8
您不应使用PHP mysql库,而应使用MySQLi或PDO。
安德烈·费圭

很好的答案,谢谢你的例子。这是一个答案,可以帮助我形象地了解需要做的事情,并解决了我的问题!
GTS乔

1
最后一个标签应该是</ html>而不是<html>
GTS Joe

9

解决方案是

 $conn->set_charset("utf8");

5

而不是通过SQL查询来执行此操作,请使用php函数:mysqli :: set_charset mysqli_set_charset

Note:

This is the preferred way to change the charset. Using mysqli_query() to set it (such as SET NAMES utf8) is not recommended.

有关更多信息,请参见MySQL字符集概念部分。

http://www.php.net/manual/en/mysqli.set-charset.php


1

谢谢@all!

不要使用:query(“ SET NAMES utf8”); 这是安装程序的内容,而不是查询。在以setCharset()(或类似方法)开始的连接之后,将其正确放置

场地上的一些小东西:

状态:

  • mysql服务器默认会讲latin1
  • 您的Hole应用程式位于utf8中
  • 无需任何额外的连接(因此:latin1)(没有SET NAMES utf8 ...,没有set_charset()方法/功能)

只要mysql可以处理字符,就可以存储和读取数据。如果您查看数据库,您将已经看到其中有废话(例如,使用phpmyadmin)。

到现在为止这不是问题!(错误,但经常(在欧洲)有效。)

..除非可以正常工作的另一个客户端/程序或更改的库将读取/保存数据。那就麻烦大了!


0

不仅是PDO。如果SQL回答像'???? 符号,字符集的预设(希望UTF-8),真的建议:

if (!$mysqli->set_charset("utf8")) 
 { printf("Can't set utf8: %s\n", $mysqli->error); }

或通过程序样式 mysqli_set_charset($db,"utf8")

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.