MySQL 在特殊字符处截断字符串
Posted
技术标签:
【中文标题】MySQL 在特殊字符处截断字符串【英文标题】:MySQL cuts off string at special chars 【发布时间】:2010-11-25 18:38:07 【问题描述】:我正在尝试使用 php 将远程 POST 数据(iSnare 发送的文章)插入 mysql。数据成功来自远程 POST 发送者,我可以毫无问题地将其写入纯文本文件。
不幸的是,在将其插入 MySQL 时,MySQL 会在特殊字符处截断字符串(文章)。我尝试了很多东西,但仍然没有成功!
我试过了:
使用mysql_real_escape_string()
转义字符
使用htmlentities()
和htmlspecialchars()
(与每个参数..)
在执行其他所有操作之前向 MySQL 发送 SET NAMES utf8
查询
所有表和列均采用 UTF-8 编码和 utf8_general_ci
(也尝试将 utf8_unicode_ci
和 utf8_bin
作为排序规则)
将所有 PHP 文件保存为 UTF-8
我仍然找不到解决方案。如果有人能帮我解决这个问题,我将非常感激。
这是我的表格定义和 PHP 代码:
PHP
function guvenlik_sql($x)
// Cleans inputs agains sql injection
return mysql_real_escape_string(htmlentities(stripslashes($x)), ENT_QUOTES);
// Check if data really comes from an Isnare.com server (Address hidden)
if ($_SERVER['REMOTE_ADDR'] == $isnareIP || $_SERVER['REMOTE_ADDR'] == "xxx.xxx.xxx.xxx")
$title = guvenlik_sql($_POST["article_title"]);
$first_name = guvenlik_sql($_POST["article_author"]);
$description = guvenlik_sql($_POST["article_summary"]);
$category = guvenlik_sql($_POST["article_category"]);
$article = guvenlik_sql($_REQUEST["article_body_text"]);
$article_html = guvenlik_sql($_POST["article_body_html"]);
$resource_box = guvenlik_sql($_POST["article_bio_text"]);
$resource_box_html = guvenlik_sql($_POST["article_bio_html"]);
$keywords = guvenlik_sql($_POST["article_keywords"]);
$email = guvenlik_sql($_POST["article_email"]);
$fp = fopen('test.txt', 'a');
fwrite($fp, $title."\n");
fwrite($fp, $article."\n\n\n\n");
fclose($fp);
mysql_query("INSERT INTO articles " .
"(" .
"first_name, " .
"email, " .
"title, " .
"description, " .
"article, " .
"article_html, " .
"category, " .
"resource_box, " .
"resource_box_html, " .
"keywords, " .
"distributor, " .
"distributor_host" .
") VALUES (" .
"'$first_name', " .
"'$email', " .
"'$title', " .
"'$description', " .
"'$article', " .
"'$article_html', " .
"'$category', " .
"'$resource_box', " .
"'$resource_box_html', " .
"'$keywords', " .
"'$isnare', " .
"'$_SERVER['REMOTE_ADDR']', " .
")") or die(mysql_error());
//end if security
表定义
CREATE TABLE `articles` (
`article_ID` int(11) NOT NULL auto_increment,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NOT NULL,
`email` varchar(100) NOT NULL,
`password` varchar(100) NOT NULL,
`author_url` varchar(255) NOT NULL,
`company_name` varchar(100) NOT NULL,
`address1` varchar(100) NOT NULL,
`address2` varchar(100) NOT NULL,
`state_2digit` varchar(100) NOT NULL,
`state` varchar(100) NOT NULL,
`zip_code` varchar(100) NOT NULL,
`country` varchar(100) NOT NULL,
`phone` varchar(100) NOT NULL,
`newsletter` varchar(100) NOT NULL,
`title` varchar(255) NOT NULL,
`description` text NOT NULL,
`article` longtext NOT NULL,
`article_html` longtext NOT NULL,
`category` varchar(100) NOT NULL,
`cat` varchar(100) NOT NULL,
`resource_box` text NOT NULL,
`resource_box_html` longtext NOT NULL,
`keywords` varchar(255) NOT NULL,
`publish_date` timestamp NOT NULL default CURRENT_TIMESTAMP,
`distributor` varchar(255) NOT NULL default '',
`distributor_host` varchar(255) NOT NULL,
PRIMARY KEY (`article_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC
【问题讨论】:
如果您发布被截断的字符串以及由“SHOW CREATE TABLE tblname”定义的表定义,将会非常有帮助。 做一个更好的问题描述,发送的POST数据是什么?有什么特别之处?涉及哪些编码? iSnare 使用什么编码? 而且有问题的 PHP 代码也很好。也许您是手动构建 SQL 查询字符串而不是使用参数,这使您容易受到 SQL 注入攻击。 @zombat: 字符串放在这里很长,但它不会只删除一个特殊字符,有时是撇号,有时是特殊引号,我猜它们是从 Apple Mac 或 Word 文件中复制的.. @Vinko:POST 数据是一篇随机文章,它可以是任何东西。特殊字符也不是特定的,这会使事情变得更难。我询问了对 iSnare 的编码,但不幸的是他们没有回复,所以我也不知道,但我对所有内容(数据库、列、数据库连接、php 脚本等)都使用 UTF8。我希望对大家有所帮助.. . 【参考方案1】:答案很晚,但我在我们的一个旧项目中遇到了这个问题。事实证明,MySql 有自己的 UTF8“实现”。它无法保存由超过 3 个字节组成的字符(如表情符号等)。有时它会抛出错误(就像在这个问题"Incorrect string value" when trying to insert UTF-8 into MySQL via JDBC? 中一样),有时它只是切断字符串。
解决方案是从 utf8 切换到 utf8mb4,如上面链接的问题中所述,或者确保在保存之前切断所有长字符。
我知道这是一个老问题,但随着我们使用越来越多的表情符号,这可能会出现在一些较旧的应用程序中。希望它可以帮助某人。
【讨论】:
【参考方案2】:使用mysqli_set_charset
为我节省了一天的时间:
$conn = new mysqli($host, $username, $password, $database);
mysqli_set_charset($conn, 'utf8');
【讨论】:
【参考方案3】:刚刚解决了一个类似的问题。我的问题是我试图将 Latin-1 编码数据插入 UTF-8 编码表。仔细检查数据的编码 - 您可能会从输入中获取非 UTF-8 数据。
【讨论】:
【参考方案4】:我刚刚处理了同样的情况,条目在应该是特殊字符(ä、ö、è 等)的地方被切断了。我所有的文件都是 UTF8 编码的,连接是 UTF8 编码的,表排序规则是 UTF8 的,但条目仍然被切断。
我的解决方案是:更多的 UTF 编码! :) 在可以包含特殊字符的条目上使用utf8_encode()
。
mysql_query("INSERT INTO articles (first_name, email, title, description, article, article_html, category, resource_box, resource_box_html, keywords, distributor, distributor_host) values (
'" . utf8_encode($first_name) . "',
'" . $email . "',
'" . utf8_encode($title) . "',
'" . utf8_encode($description) . "',
// etc
【讨论】:
请注意,如果您对已经 utf8 编码的数据进行 utf8 编码,则会产生垃圾。 好吧,您不是对数据进行双重编码。您将数据转换为 UTF-8,以存储在 UTF-8 数据库中。因此,您只需修改数据的形状以匹配容器。正方形不适合三角形;)【参考方案5】:对于那些可能有同样问题并且之前的答案没有帮助的人,我得到了另一个建议:检查内容类型!应该是这样的:
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
我遇到了和 Donald 一样的问题 - 这就是 MAGIC :)(我没想到一开始处理文件的同事没有正确设置它......)
【讨论】:
很抱歉试图提供帮助!我刚刚解决了这个关于我自己的问题的问题。为了寻找答案,我来到了这个页面,因为可能有很多人可能会发现自己处于我的境地,我想分享这个。如果您在对任何事情进行竞争后给出一些建议,那就太好了——尤其是当您拥有如此令人印象深刻的声誉时。发布这种 cmets 会阻止读者尝试这个的任何意图,我重复 - 它对我有用! P.S.:你在投票时签名的方式很有趣——你可以利用这段时间提供建议!【参考方案6】:1) 将您生成的 sql 字符串放入一个变量中,并将其写入一个文件,然后再将其发送到 MySQL(这样您就可以准确查看发送的内容)
2) mysqld 有一个设置“max_allowed_packet
”,我认为它会切断长查询。
3) 你将ENT_QUOTES
传递给mysql_real_escape_string()
。我认为您的意思是将其传递给 htmlentities()
【讨论】:
【参考方案7】:您确定字符串没有因为超出列定义允许的长度而被截断吗?
问题也可能是数据已成功存储在数据库中,但您用于显示数据库数据的应用程序截断了显示的字符串。这主要发生在基于 Windows 的应用程序中包含空字符的字符串中,因为 Windows 控件在内部使用以空字符结尾的字符串。
【讨论】:
不,我的专栏是长文本,数据只是一篇文章,甚至没有接近极限。数据也没有存储成功,它也损坏了..【参考方案8】:“Set names utf8”只设置表名和列名的字符集,内容字符集也必须使用“set character set utf8”。
【讨论】:
已经这样做了,还是不行。我在数据库连接部分做的是; mysql_query("SET NAMES 'utf8'"); mysql_query("SET NAMES 'utf8' COLLATE 'utf8_unicode_ci'"); mysql_query("SET CHARACTER SET utf8"); mysql_query("SET COLLATION_CONNECTION = 'utf8_unicode_ci'");以上是关于MySQL 在特殊字符处截断字符串的主要内容,如果未能解决你的问题,请参考以下文章