Что такое эквивалент запроса MySQL для strip_tags?

У меня есть большая база данных, содержащая записи, в которых есть теги <a>, и я хотел бы удалить их. Конечно, есть метод, в котором я создаю PHP скрипт, который выбирает все, использует strip_tags и обновляет базу данных, но это занимает много времени. Итак, как я могу сделать это с помощью простого (или сложного) запроса MySQL?

Ответы

Ответ 1

Я не считаю, что есть эффективный способ сделать это только в MySQL.

MySQL имеет функцию REPLACE(), но она может заменять только постоянные строки, а не шаблоны. Вы могли бы написать хранимую функцию MySQL для поиска и замены тегов, но в этот момент вам, вероятно, лучше написать PHP скрипт, чтобы выполнить эту работу. Это может быть не так быстро, но, вероятно, быстрее писать.

Ответ 2

Здесь вы идете:

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

Ответ 3

Я передаю этот код, кажется очень похожим на выше. Работал для меня, надеюсь, что это поможет.

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

Ответ 4

Boann работает, когда я добавил SET $str = COALESCE($str, '');.

из этого сообщения :

Также следует отметить, что вы можете поставить SET $str = COALESCE ($ str, ''); как раз перед циклом в противном случае нулевые значения могут привести к сбою/никогда завершение запроса. - Том С 17 августа в 9:51

Ответ 5

Я использую lib_mysqludf_preg для этого и регулярное выражение:

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

Также ему понравилось это для строк, которые с кодированными объектами html:

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

Есть, вероятно, случаи, когда они могут потерпеть неудачу, но я не сталкивался с ними, и они достаточно быстры.

Ответ 6

Я просто расширил ответ @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');

Ответ 7

REPLACE() работает очень хорошо.

Тонкий подход:

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

... и не так тонко: (Преобразование строк в пули)

 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`