在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
你最終實現了什麼技術? –