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)?
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.
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
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
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
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('#<.+?>#',' ',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.
Compatible avec MySQL 8+ et MariaDB 10.0.5+
SELECT REGEXP_REPLACE (body, '<[^>] *> +', '') FROM app_cms_sections
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');