从记录中删除HTML标记

时间:2010-04-13 08:12:39

标签: mysql

需要帮助才能形成MYSQL查询 来自具有波纹管内容的表一列

Row1 : this is first <a href='mytext.txt'>row</a> from the table

Row 2 : THis is the second row <img src ='mytext.jpg'> my image is there

Row 3 : <p>This is the Third row my mytext is there </p>

Row 4 : <p class='te_mytext'>This is the Third row my text is there </p>

这是表格行,我尝试将关键字搜索为“mytext”

我的查询是

SELECT * from table  WHERE colmn_name ` like '%mytext%' "

我将得到所有4行,但结果是错误的。我需要得到正确的输出,只有第3行。这一行只有内容中的mytext所有其他内容的原因不在于内容,而是mytext在所有行中

如何编写MySQL查询?

10 个答案:

答案 0 :(得分:42)

尝试这个解决方案:不是自己尝试,但显然它有效。

来源:http://forums.mysql.com/read.php?52,177343,177985#msg-177985

   SET GLOBAL log_bin_trust_function_creators=1;
DROP FUNCTION IF EXISTS fnStripTags;
DELIMITER |
CREATE FUNCTION fnStripTags( Dirty varchar(4000) )
RETURNS varchar(4000)
DETERMINISTIC 
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;
|
DELIMITER ;
SELECT fnStripTags('this <html>is <b>a test</b>, nothing more</html>');

答案 1 :(得分:22)

这是我对strip_tags函数的实现:

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

享受。

答案 2 :(得分:12)

如果您的内容始终以标记开头(&lt; body&gt;等)

试试这个:

SELECT * from table  WHERE colmn_name REGEXP  '>[^<]*mytext';

答案 3 :(得分:3)

将这些行添加到fnStripTags功能
SET Dirty = Insert( Dirty, iStart, iLength, '');之后

set Dirty = Replace(Dirty,'&nbsp;',''); #No space between & and nbsp;
set Dirty = Replace(Dirty,'\r','');
set Dirty = Replace(Dirty,'\n','');

答案 4 :(得分:2)

我认为没有必要有这种非凡的逻辑。它可以简化为...

-- set @StrRow = 'this is first <a href="mytext.txt">row</a> from the table';
-- set @StrRow = 'THis is the second row <img src ="mytext.jpg"> my image is there';
 set @StrRow = '<p>This is the Third row  my mytext is there  </p>';
-- set @StrRow = '<p class="te_mytext">This is the Third row  my text is there  </p>';

set @MyText = 'mytext';

select locate('<', @StrRow, locate(@MyText, @StrRow)) as '<', locate(@MyText, @StrRow) as MyText, locate('>', @StrRow, locate(@MyText, @StrRow)) as '>'
from xyz
 where
 locate('<', @StrRow, locate(@MyText, @StrRow)) > 0 and 
 locate('<', @StrRow, locate(@MyText, @StrRow)) < locate('>', @StrRow, locate(@MyText, @StrRow))

答案 5 :(得分:1)

我使用上面的strip_tags()(感谢Boann)和一个轻微的mod来摆脱重音字符的html代码等。像这样:

...BEGIN
    DECLARE $start, $end INT DEFAULT 1;
    SET $str = REPLACE($str, "&nbsp;", " ");
    SET $str = REPLACE($str, "&euro;", "€");
    SET $str = REPLACE($str, "&aacute;", "á");
    SET $str = REPLACE($str, "&eacute;", "é");
    SET $str = REPLACE($str, "&iacute;", "í");
    SET $str = REPLACE($str, "&oacute;", "ó");
    SET $str = REPLACE($str, "&uacute;", "ú");
LOOP...

答案 6 :(得分:1)

MySQL strip标签实现,允许您定位特定标签,以便我们可以在每个函数调用中逐个替换标签。您只需要传递标记参数,例如'a'替换所有打开/关闭锚标记。

# 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');

答案 7 :(得分:0)

这里需要正则表达式匹配,负前瞻断言:“mytext”后面没有结束标记。从8.0开始,MySQL仍不支持外观断言,但MariaDB确实如此。 MariaDB查询问题:

SELECT * FROM table WHERE column_name REGEXP 'mytext(?![^<>]*>)';

该问题的另一个解决方案是在匹配之前删除部分/全部标签。与REGEXP相比,它效率低下,但也有效。在从8.0开始的MySQL和从10.0.5开始的MariaDB中,有内置的REGEXP_REPLACE函数。 'strip_html'甚至是MariaDB相应文档page中的第一个示例。 MySQL / MariaDB查询这种方法:

SELECT * FROM table WHERE REGEXP_REPLACE (column_name, '<.+?>', '') LIKE '%mytext%';

除此之外,问题中的字符串会混合数据和表示。不应该定期搜索它们,因为这会浪费系统资源。

答案 8 :(得分:0)

扩展了Boann提供的strip_tags函数。现在,它可以用于保留或忽略标签之间的短语。注意在我的代码部分,即带有空标记的错误。为$ keep_phrase = false。

    CREATE FUNCTION strip_tags($str text, $tag text,$keep_phrase bool) 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;
            IF ($keep_phrase) THEN
                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, '>'), '');
            ELSE
                SET $end = LOCATE(CONCAT('</', $tag, '>'),$str,$start);
                IF (!$end) THEN 
                    SET $end = LOCATE('/>',$str,$start); 
                    SET $str = INSERT($str, $start, $end - $start + 2, '');
                ELSE 
                    SET $str = INSERT($str, $start, $end - $start 
                       + LENGTH(CONCAT('</', $tag, '>')), '');
                END IF;
            END IF;
        END LOOP;
    END //

要证明功能,

    SELECT strip_tags('<p>so<span id="x"> very</span> cool</p><p>so<span id="y"> very</span> cool</p>','span',true);
    <p>so very cool</p><p>so very cool</p>

    SELECT strip_tags('<p>so<span id="x"> very</span> cool</p><p>so<span id="y"> very</span> cool</p>','span',false);
    <p>so cool</p><p>so cool</p>

不支持$ keep_phrase = false的空元素,请参阅:

    SELECT strip_tags('<p>so<span id="x"> very</span> cool</p><span/><p>so<span id="y"> very</span> cool</p>','span',false);
    <p>so cool</p> cool</p>

答案 9 :(得分:-2)

你无法解析SQL查询中的HTML,这没有任何意义。也许你可以只保留表格的特殊搜索版本,并删除所有HTML,但你必须使用一些外部处理才能做到这一点。