web-dev-qa-db-fra.com

Quel est l'équivalent requête MySQL de PHP strip_tags?

J'ai une grande base de données qui contient des enregistrements qui ont des balises <a> et je voudrais les supprimer. Bien sûr, il existe la méthode par laquelle je crée un script PHP qui sélectionne tout, utilise strip_tags et met à jour la base de données, mais cela prend beaucoup de temps. Alors, comment puis-je faire cela avec une requête MySQL simple (ou compliquée)?

16
faq

Je ne crois pas qu'il existe un moyen efficace de faire cela dans MySQL uniquement.

MySQL a une fonction REPLACE(), mais il ne peut remplacer que des chaînes constantes, pas des modèles. Vous pouvez éventuellement écrire une fonction stockée dans MySQL pour rechercher et remplacer les balises, mais à ce stade, il est probablement préférable d'écrire un script PHP pour effectuer le travail. Ce n'est peut-être pas assezaussi rapide, mais il sera probablement plus rapide d'écrire.

6
duskwuff

Voici:

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;

Je me suis assuré qu'il supprime les crochets d'ouverture incompatibles car ils sont dangereux, même s'il ignore les crochets de fermeture non appariés car ils sont inoffensifs.

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
17
Boann

Je transmets ce code, semble très similaire à ce qui précède. Travaillé pour moi, espérons que cela aide.

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
5
elit3x

Les travaux de Boann une fois que j'ai ajouté SET $str = COALESCE($str, '');.

à partir de ce post :

Il convient également de noter que vous souhaiterez peut-être placer SET $ str = COALESCE ($ str, ''); Juste avant la boucle, sinon les valeurs null risquent de provoquer une interrogation de fermeture crash/jamais . - Tom C 17 août à 9h51

1
Scott2B

J'utilise la bibliothèque lib_mysqludf_preg pour cela et une expression rationnelle comme celle-ci:

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

Cela a également été le cas pour les lignes contenant des entités HTML codées:

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

Il y a probablement des cas où ceux-ci pourraient échouer mais je n'en ai pas rencontré et ils sont raisonnablement rapides.

1
billynoah

Compatible avec MySQL 8+ et MariaDB 10.0.5+

SELECT REGEXP_REPLACE (body, '<[^>] *> +', '') FROM app_cms_sections

0
Gene Kelly

Je viens d'élargir la réponse @boann pour autoriser le ciblage de toute balise spécifique afin que nous puissions remplacer les balises une par une à chaque appel de fonction. Il vous suffit de passer le paramètre tag, par exemple. 'a' pour remplacer toutes les balises d'ancrage d'ouverture/de fermeture. Cela répond à la question posée par OP, contrairement à la réponse acceptée, qui supprime TOUTES les balises.

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