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_ciutf8_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 在特殊字符处截断字符串的主要内容,如果未能解决你的问题,请参考以下文章

java 如何对中英文和符号数字混合的字符串进行截取,其中包含各种括号( ( [ < >] ) )?

正则表达式没有在特殊字符处获得整个链接

如何向SQL中插入含@、#等特殊字符的字符串

PHP怎样过滤中文状态下特殊字符(比如标点符号)?

如何在mysql数据库中鎒moji特殊字符

使用 MySQL 选择时截断字符串