代码之家  ›  专栏  ›  技术社区  ›  user187291

是否使用“设置名称”

  •  56
  • user187291  · 技术社区  · 15 年前

    在阅读O'Reilly的“高性能MySQL”时,我偶然发现了以下几点

    设置了另一个常见的垃圾查询 命名为utf8,这是错误的 无论如何都要做(它不会改变 客户端库的字符集;它 只影响服务器)。

    我有点困惑,因为我曾经在每个脚本的顶部加上“set names utf8”,让数据库知道我的查询是utf8编码的。

    任何人都可以对上述引用进行评论,或者更正式地说,您有什么建议/最佳实践来确保我的数据库工作流支持Unicode。

    如果相关的话,我的目标语言是PHP和Python。

    3 回复  |  直到 6 年前
        1
  •  30
  •   hakre Alister Bulman    12 年前

    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>> 你也可以设置 these server variables 在你的静态 my.ini/cnf .

    请注意在同一个MySQL服务器实例上运行的其他应用程序可能存在问题,并且需要一些其他字符集。

        2
  •  25
  •   goat    6 年前

    TLDR

    // 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 ,向MySQL发出标准的SQL查询。当SQL查询通过pdo,然后通过mysql客户机库,最后到达mysql服务器时,只有mysql服务器解析和解释该SQL查询。这很重要,因为mysql服务器不会向pdo或mysql客户机发送任何消息,让它知道字符集和编码已经更改,所以mysql客户机和pdo都完全不知道发生了这种情况。

    不要这样做很重要,因为如果客户端库不知道当前的字符集,它就不能正确地处理字符串。大多数常见的操作在客户机不知道正确的字符集的情况下都可以正常工作,但字符串转义是不可能的,例如 PDO::quote . 您可能认为不需要担心这种手动的原始字符串转义,因为您使用的是准备好的语句,但事实是PDO的绝大多数用户:MySQL用户在不知情的情况下使用 emulated prepared statements 因为它已经是pdo:mysql驱动程序的默认设置很长时间了。模拟的准备语句不使用mysql api提供的真正的本机mysql准备语句;相反,php执行与调用 PDO::quote() 在所有的值上,并用引用的值来替换所有的占位符。

    由于除非您知道正在使用的字符集,否则无法正确转义字符串,如果您通过 set names . 不管SQL注入的可能性如何,如果使用针对不同字符集的转义方案,仍然可以中断字符串。

    对于pdo mysql驱动程序,可以通过以下方式指定连接时的字符集: specifying it in the DSN . 如果您这样做,客户机库和服务器都将知道字符集,因此事情将按它们应该的方式工作。

    //键是“charset=utf8”部分。
    $dsn='mysql:host=localhost;dbname=testdb;charset=utf8';
    $dbh=新PDO($dsn,'user'、'pass');
    

    但字符串转义不当并不是唯一的问题。例如,您也可能在使用中遇到问题 PDO::bindColumn 因为列名被指定为字符串,所以编码也很重要。例如,一个名为 ütube (注意umlaut),然后从 latin utf8 通过设置名称,然后尝试 $stmt->bindColumn('ütube', $var); 具有 γ射线管 是一个utf8编码的字符串,因为您的PHP文件是utf8编码的。它不起作用,你需要把字符串编码成拉丁语变体…现在你有各种各样的疯狂。

        3
  •  9
  •   typeoneerror    15 年前

    对py不确定,但是php有 mysql_set_charset 现在,它指出这是“不建议使用mysql_query()更改字符集[和]以执行集名称的首选方法”。注意,该函数是为mysql 5.0.7引入的,因此它不适用于早期版本。

    mysql_set_charset('utf8', $link);
    

    其中$link是用创建的连接 mysql_connect