MySQL在卷曲(智能)引号上窒息

时间:2009-08-23 15:56:33

标签: php mysql quotes smart-quotes

我正在从表单中将一些数据插入数据库。我正在使用addslashes来转义文本(也尝试了mysql_real_escape_string,结果相同)。

常规报价已转义,但其他一些报价则没有。例如,字符串:

  

荷马的血液成为萌新啤酒的秘密成分。

转换为:

  

荷马的血液成为萌新啤酒的秘密成分。

我不认为卷曲引用不会转义,但只有这个文本插入到数据库中:

  

荷马的血液成为萌的秘密成分

所以PHP认为卷曲的引用很好,但MySQL正在丢失字符串。 MySQL虽然没有给出任何错误。

2 个答案:

答案 0 :(得分:7)

我会查找Web界面中使用的字符编码与数据库级别使用的字符编码之间的不匹配。例如,如果您的Web界面使用UTF-8,并且您的数据库使用latin1的默认MySQL编码,那么您需要使用DEFAULT CHARSET=utf8设置表。

顺便使用mysql_real_escape_string()或mysqli。 addslashes() 足以防止SQL注入。

答案 1 :(得分:7)

在Moe中的'是示例字符串中唯一的字符,如果该字符串是latin1编码但您的mysql服务器需要utf8,则该字符无效。

简单演示:

<?php
function foo($s) {
    echo 'len=', strlen($s), ' ';
  for($i=0; $i<strlen($s); $i++) {
    printf('%02X ', ord($s[$i]));
  }
  echo "\n";
}

 // my file is latin1 encoded and so is the string literal
foo('Moe’s');
// now try it with an utf8 encoded string
foo( utf8_encode('Moe’s') );

打印

len = 5 4D 6F 65 92 73
len = 6 4D 6F 65 C2 92 73

因此问题是:你是否以“错误”编码的方式提供了mysql服务器? 每个连接都有一个连接字符集,mysql服务器希望你的客户端(php脚本)发送在该字符集中编码的数据。您可以找到连接字符集的内容

SHOW VARIABLES LIKE '%character%'

喜欢

$mysql = mysql_connect('..', '..', '..') or die(mysql_error());
mysql_select_db('..', $mysql) or die(mysql_error());

$query = "SHOW VARIABLES like '%character%'";
$result = mysql_query($query, $mysql) or die(__LINE__.mysql_error());
while( false!==($row=mysql_fetch_array($result, MYSQL_ASSOC)) ) {
  echo join(', ', $row), "\n";
}

这应该打印类似

character_set_client, utf8
character_set_connection, utf8
character_set_database, latin1
character_set_filesystem, binary
character_set_results, utf8
character_set_server, utf8
character_set_system, utf8

character_set_connection, utf8表示“我的”连接字符集是utf8,即mysql服务器需要来自客户端(php)的utf8编码字符。什么是“你的”连接字符集?

然后看一下参数字符串的实际编码,即如果你有

$foo = mysql_real_escape_string($_POST['foo'], $mysql);

替换

echo '<div>Debug hex($_POST[foo])=';
for($i=0; $i<strlen($s); $i++) {
    printf('%02X ', ord($_POST['foo'][$i]));
}
echo "</div>\n";
$foo = mysql_real_escape_string($_POST['foo'], $mysql);

并检查输入字符串的实际编码是什么。它是打印92还是C2 92?