25

我有一个大型数据库,其中包含有<a>标签的记录,我想删除它们。当然,有一种方法是我创建一个 PHP 脚本来选择所有、使用strip_tags和更新数据库,但这需要很长时间。那么如何使用简单(或复杂)的 MySQL 查询来做到这一点?

4

9 回答 9

33

MySQL >= 5.5 提供 XML 函数来解决您的问题:

SELECT ExtractValue(field, '//text()') FROM table;

参考:https ://dev.mysql.com/doc/refman/5.5/en/xml-functions.html

于 2019-03-25T11:42:21.790 回答
27

干得好:

CREATE FUNCTION `strip_tags`($str text) RETURNS text
BEGIN
    DECLARE $start, $end INT DEFAULT 1;
    LOOP
        SET $start = LOCATE("<", $str, $start);
        IF (!$start) THEN RETURN $str; END IF;
        SET $end = LOCATE(">", $str, $start);
        IF (!$end) THEN SET $end = $start; END IF;
        SET $str = INSERT($str, $start, $end - $start + 1, "");
    END LOOP;
END;

我确保它会删除不匹配的左括号,因为它们很危险,尽管它会忽略任何未配对的右括号,因为它们是无害的。

mysql> select strip_tags('<span>hel<b>lo <a href="world">wo<>rld</a> <<x>again<.');
+----------------------------------------------------------------------+
| strip_tags('<span>hel<b>lo <a href="world">wo<>rld</a> <<x>again<.') |
+----------------------------------------------------------------------+
| hello world again.                                                   |
+----------------------------------------------------------------------+
1 row in set
于 2012-11-12T15:38:09.120 回答
6

我不相信仅在 MySQL 中有任何有效的方法可以做到这一点。

MySQL 确实有一个REPLACE()函数,但它只能替换常量字符串,不能替换模式。您可能会编写一个 MySQL 存储函数来搜索和替换标签,但此时您最好编写一个 PHP 脚本来完成这项工作。它可能不会那么快,但写起来可能会更快。

于 2011-10-04T22:00:07.970 回答
5

我正在传递这段代码,看起来与上面的非常相似。为我工作,希望它有帮助。

BEGIN
  DECLARE iStart, iEnd, iLength   INT;

  WHILE locate('<', Dirty) > 0 AND locate('>', Dirty, locate('<', Dirty)) > 0
  DO
    BEGIN
      SET iStart = locate('<', Dirty), iEnd = locate('>', Dirty, locate('<', Dirty));
      SET iLength = (iEnd - iStart) + 1;
      IF iLength > 0 THEN
        BEGIN
          SET Dirty = insert(Dirty, iStart, iLength, '');
        END;
      END IF;
    END;
  END WHILE;
  RETURN Dirty;
END
于 2012-11-12T15:51:56.773 回答
2

我只是扩展了答案@boann 以允许定位任何特定标签,以便我们可以用每个函数调用一个一个替换标签。您只需要传递标签参数,例如'a'替换所有打开/关闭锚标签。这回答了 OP 提出的问题,与接受的答案不同,后者去除了所有标签。

# MySQL function to programmatically replace out specified html tags from text/html fields

# run this to drop/update the stored function
DROP FUNCTION IF EXISTS `strip_tags`;

DELIMITER |

# function to nuke all opening and closing tags of type specified in argument 2
CREATE FUNCTION `strip_tags`($str text, $tag text) RETURNS text
BEGIN
    DECLARE $start, $end INT DEFAULT 1;
    SET $str = COALESCE($str, '');
    LOOP
        SET $start = LOCATE(CONCAT('<', $tag), $str, $start);
        IF (!$start) THEN RETURN $str; END IF;
        SET $end = LOCATE('>', $str, $start);
        IF (!$end) THEN SET $end = $start; END IF;
        SET $str = INSERT($str, $start, $end - $start + 1, '');
        SET $str = REPLACE($str, CONCAT('</', $tag, '>'), '');
    END LOOP;
END;

| DELIMITER ;

# test select to nuke all opening <a> tags
SELECT 
    STRIP_TAGS(description, 'a') AS stripped
FROM
    tmpcat;

# run update query to replace out all <a> tags
UPDATE tmpcat
SET 
    description = STRIP_TAGS(description, 'a');
于 2017-07-17T15:11:48.433 回答
1

我添加后 Boann 的作品SET $str = COALESCE($str, '');

从这篇文章

另请注意,您可能需要放置一个 SET $str = COALESCE($str, ''); 就在循环之前,否则空值可能会导致崩溃/永无止境的查询。– 汤姆 C 8 月 17 日 9:51

于 2015-11-11T15:43:14.087 回答
1

我为此使用lib_mysqludf_preg库和这样的正则表达式:

SELECT PREG_REPLACE('#<[^>]+>#',' ',cell) FROM table;

对于带有编码的 html 实体的行也这样做:

SELECT PREG_REPLACE('#&lt;.+?&gt;#',' ',cell) FROM table;

在某些情况下,这些可能会失败,但我没有遇到任何情况,而且它们的速度相当快。

于 2017-01-24T16:56:15.410 回答
1

兼容 MySQL 8+ 和 MariaDB 10.0.5+

从 app_cms_sections 中选择 REGEXP_REPLACE(body, '<[^>]*>+', '')

于 2018-05-15T14:25:27.950 回答
-2

REPLACE()效果很好。

微妙的方法:

 REPLACE(REPLACE(node.body,'<p>',''),'</p>','') as `post_content`

...而且不是那么微妙:(将字符串转换为 slug)

 LOWER(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(TRIM(node.title), ':', ''), 'é', 'e'), ')', ''), '(', ''), ',', ''), '\\', ''), '\/', ''), '\"', ''), '?', ''), '\'', ''), '&', ''), '!', ''), '.', ''), '–', ''), ' ', '-'), '--', '-'), '--', '-'), '’', '')) as `post_name`
于 2012-11-08T13:46:35.533 回答