在O'Reilly出版阅读“高性能MySQL的”,我在下面的是否使用“组名称”
另一种常见的垃圾查询跌跌撞撞的SET NAMES UTF8,这是错误的方式(不改变 客户端库的字符集; 只影响服务器)。
我有点困惑,因为我曾经在每个脚本的顶部放置了“SET NAMES utf8”,让db知道我的查询是utf8编码的。
任何人都可以评论上述报价,或者更正式地说,您的建议/最佳实践是什么,以确保我的数据库工作流程能够识别unicode。
我的目标语言是php和python,如果这是相关的。
在O'Reilly出版阅读“高性能MySQL的”,我在下面的是否使用“组名称”
另一种常见的垃圾查询跌跌撞撞的SET NAMES UTF8,这是错误的方式(不改变 客户端库的字符集; 只影响服务器)。
我有点困惑,因为我曾经在每个脚本的顶部放置了“SET NAMES utf8”,让db知道我的查询是utf8编码的。
任何人都可以评论上述报价,或者更正式地说,您的建议/最佳实践是什么,以确保我的数据库工作流程能够识别unicode。
我的目标语言是php和python,如果这是相关的。
mysql_set_charset()
创建将是一种选择的连接 - 但一个选项仅限于ext/mysql
。对于ext/mysqli
它是mysqli_set_charset
和PDO
::mysql
您需要指定连接参数。
由于使用此函数会导致MySQL API调用,因此应该认为它比发出查询要快得多。
在性能方面,确保脚本和MySQL服务器之间基于UTF-8通信的最快方法是正确设置MySQL服务器。由于SET NAMES x
是equivalent到
SET character_set_client = x;
SET character_set_results = x;
SET character_set_connection = x;
而SET character_set_connection = x
内部还执行SET collation_connection = <<default_collation_of_character_set_x>>
你也可以在你的my.ini/cnf
设置these server variables静态。
请注意其他应用程序在同一个MySQL服务器实例上运行并需要其他字符集时可能出现的问题。
不确定py,但php现在有mysql_set_charset
,这表示这是“不推荐使用mysql_query()更改charset [和]来执行SET NAMES的首选方法。”请注意,该功能是为MySQL 5.0.7引入的,因此它不适用于早期版本。
mysql_set_charset('utf8', $link);
其中$链接是mysql_connect
// The key is the "charset=utf8" part.
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
$dbh = new PDO($dsn, 'user', 'pass');
这个答案对PHP的PDO库的重视,因为它是如此的普遍。
简要提醒 - mysql是一个客户端 - 服务器体系结构。这很重要,因为不仅有mysql服务器在那里有实际的数据库,而且还有单独的mysql客户端驱动程序,这是与mysql服务器交谈的东西(它们是独立的实体)。你可以有点说,MySQL客户端和pdo混合在一起。
当你使用set names utf8
时,你发出一个标准的sql查询到mysql。尽管sql查询确实通过了pdo,然后通过了mysql客户端库,然后最终到达了mysql服务器,但是只有mysql服务器解析并解释了该sql查询。这很重要,因为mysql服务器不会向pdo发送任何消息,或者mysql客户端让它知道字符集和编码已更改,所以pdo完全不了解它发生的事实。
它没有这样做,因为客户端库不能正确处理字符串,如果它是不知道目前的字符集是非常重要的。如果客户端不知道正确的字符集,大多数常见操作都可以正常工作,但不会出现字符串转义的情况,如PDO::quote。你可能会认为你不需要担心这样的手工原始字符串转义,因为你使用准备好的语句,但事实是,绝大多数的PDO:MySQL用户在不知不觉中使用emulated prepared statements,因为它已经为PDO的默认设置:MySQL的驱动程序现在很长一段时间。模拟的预准备语句不使用由mysql api提供的真实本地mysql准备语句;相反,php的所有值相当于调用PDO::quote()
,并且str_replacing你的占位符的引用值。
因为你不能正确转义的字符串,除非你知道你正在使用的字符集,如果你已经通过集名称更改为某些字符集,这些模拟预处理语句很容易受到SQL注入。无论sql注入的可能性如何,如果您使用用于不同字符集的转义方案,仍然可能会破坏字符串。
对于PDO MySQL驱动程序,当您连接,通过specifying it in the DSN可以指定字符集。如果你这样做,客户端库和服务器都会知道字符集。
// The key is the "charset=utf8" part.
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
$dbh = new PDO($dsn, 'user', 'pass');
但是不当的字符串转义是不是唯一的问题。例如,您也可能在使用PDO::bindColumn时遇到问题,因为列名被指定为字符串,所以编码也很重要。例如列名为ütube
(注意变音符号),并且您通过设置名称从latin
切换到utf8
,然后尝试使用$stmt->bindColumn('ütube', $var);
而ütube
是utf8编码的字符串,因为您的php文件是utf8编码的。它不会工作,你需要将字符串编码为latin1变体......现在你有各种疯狂的事情发生。
现在(2014年9月)PDO是将PHP与数据库连接起来的最新且最稳健的方式,我认为这个答案应该被接受。 – rogeriopradoj
你最终实现了什么技术? –