2011-10-04 12 views
15

Ho un database di grandi dimensioni che contiene record contenenti tag <a> e vorrei rimuoverli. Ovviamente c'è il metodo in cui creo uno script PHP che seleziona tutto, utilizza strip_tags e aggiorna il database, ma questo richiede molto tempo. Quindi, come posso farlo con una semplice (o complicata) query MySQL?Qual è l'equivalente della query MySQL di strip_tags di PHP?

risposta

4

Non credo che ci sia un modo efficiente per farlo solo in MySQL.

MySQL ha una funzione REPLACE(), ma può sostituire solo stringhe costanti, non modelli. Potresti scrivere una funzione memorizzata MySQL per cercare e sostituire i tag, ma a quel punto probabilmente stai meglio scrivendo uno script PHP per fare il lavoro. Potrebbe non essere piuttosto come veloce, ma probabilmente sarà più veloce da scrivere.

+0

sì, probabilmente hai ragione :( – faq

-1

REPLACE() funziona abbastanza bene.

L'approccio sottile:

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

... e non così sottile: (Conversione di stringhe in lumache)

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` 
16

Qui si va:

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; 

ho fatto certo rimuove le parentesi aperte non corrispondenti perché sono pericolose, anche se ignora le parentesi di chiusura non appaiate perché sono innocue.

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 
+0

non ha funzionato per me, MySQL ha detto: Documentazione # 1064 - Hai un errore nella sintassi SQL, controllare il manuale che corrisponde alla versione del server MySQL per la sintassi corretta vicino a '' at line 3 – mahen3d

+4

'delimitatore // CREA strip_tags function ($ str testo) Restituisce testo BEGIN DECLARE $ start, $ fine INT dI DEFAULT 1; LOOP SET $ start = LOCALIZZARE ("<", $ str, $ start); IF (! $ Start) THEN RETURN $ str; FINISCI SE; SET $ end = LOCATE (">", $ str, $ start); IF (! $ End) THEN SET $ end = $ start; FINISCI SE; SET $ str = INSERT ($ str, $ start, $ end - $ start + 1, ""); END LOOP; END // delimitatore; ' – nzn

+0

FUNZIONE GOCCIA SE ESISTE strip_tags; DELIMITER | CREATE FUNCTION strip_tags ($ str text) RETURNS testo BEGIN DECLARE $ start, $ end INT DEFAULT 1; LOOP SET $ start = LOCATE ("<", $ str, $ start); IF (! $ Start) THEN RETURN $ str; FINISCI SE; SET $ end = LOCATE (">", $ str, $ start); IF (! $ End) THEN SET $ end = $ start; FINISCI SE; SET $ str = INSERT ($ str, $ start, $ end - $ start + 1, ""); FINE LOOP; END; | DELIMITER; – IRvanFauziE

5

Sto passando questo codice, sembra molto simile a quanto sopra. Ha funzionato per me, spero che aiuti.

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 
+2

Ho fatto un piccolo benchmark approssimativo su 5000 (~ 20mb) vari campioni di testo semplice/html (descrizioni dei lavori raschiati). L'output del tuo esempio è esattamente lo stesso di Boann, tuttavia il tuo codice impiega circa 32 anni per essere elaborato e i soli 7 di Boann fanno ** la soluzione di Boann 4.5 volte più veloce **. Sto solo mettendo questo qui per riferimento futuro se qualcuno affronterà lo stesso dilemma come ho fatto io. Grazie a tutti e due ragazzi. –

1

I lavori di Boann una volta ho aggiunto SET $str = COALESCE($str, '');.

da questo post:

Inoltre da notare, si consiglia di mettere un SET $ str = COALESCE ($ str, ''); appena prima del ciclo, altrimenti i valori nulli possono causare un'interruzione/mai query finale. - Tom C 17 agosto a 9:51

1

sto usando la libreria lib_mysqludf_preg per questo e una regex come questo:

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

Inoltre lo ha fatto in questo modo per le righe che con entità HTML codificati:

Ci sono probabilmente casi in cui questi potrebbero fallire ma non ne ho incontrato nessuno e sono ragionevolmente veloci.

0

Ho appena esteso la risposta @boann per consentire la destinazione di qualsiasi tag specifico in modo che possiamo sostituire i tag uno per uno con ciascuna chiamata di funzione. Hai solo bisogno di passare il parametro tag, ad es. 'a' per sostituire tutte le etichette di ancoraggio di apertura/chiusura. Questo risponde alla domanda posta da OP, a differenza della risposta accettata, che elimina TUTTI i tag.

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