Esegui regex (sostituisci) in una query SQL

Qual è il modo migliore per sostituire tutto ‘& lt’ con < in una data colonna del database? In pratica esegui s/&lt[^;]/</gi

Gli appunti:

  • deve funzionare in MS SQL Server 2000
  • Deve essere ripetibile (e non finire con <;;;;;;;;; )

È richiesto un po ‘di hacking, ma possiamo farlo con LIKE , PATINDEX , LEFT AND RIGHT e la buona vecchia concatenazione di stringhe.

 create table test ( id int identity(1, 1) not null, val varchar(25) not null ) insert into test values ('< <- ok, &lt <- nok') while 1 = 1 begin update test set val = left(val, patindex('%&lt[^;]%', val) - 1) + '<' + right(val, len(val) - patindex('%&lt[^;]%', val) - 2) from test where val like '%&lt[^;]%' IF @@ROWCOUNT = 0 BREAK end select * from test 

Migliore è che questa versione di SQL Server sia agnostica e dovrebbe funzionare bene.

Penso che questo può essere fatto molto più pulito se si usano diversi STUFF 🙂

 create table test ( id int identity(1, 1) not null, val varchar(25) not null ) insert into test values ('< <- ok, &lt <- nok') WHILE 1 = 1 BEGIN UPDATE test SET val = STUFF( val , PATINDEX('%&lt[^;]%', val) + 3 , 0 , ';' ) FROM test WHERE val LIKE '%&lt[^;]%' IF @@ROWCOUNT = 0 BREAK END select * from test 

Che ne dite di:

  UPDATE tableName SET columName = REPLACE(columName , '&lt', '<') WHERE columnName LIKE '%lt%' AND columnName NOT LIKE '%lt;%' 

Modificare:

Ho appena realizzato che ignorerò le colonne parzialmente corrette < stringhe.

In tal caso puoi ignorare la seconda parte della clausola where e chiamarla in seguito:

  UPDATE tableName SET columName = REPLACE(columName , '<;', '<') 

Questo articolo spiega come creare una semplice funzione Regex Replace che puoi usare in SQL 2000 (e nel 2005 con un semplice tweak) che può aiutarti.

Se il sapore regex di MSSQL supporta il lookahead negativo, quello sarebbe il modo giusto di avvicinarsi a questo.

 s/&lt(?!;)/</gi 

catturerà tutte le istanze di & lt che non sono seguite da a ; (anche se sono seguiti da nulla, che [^;] mancherebbe) e non cattura il seguente non- ; personaggio come parte della partita, eliminando il problema menzionato nei commenti sulla domanda originale di quel personaggio che si perde nella sostituzione.

Sfortunatamente, non uso MSSQL, quindi non ho idea se supporta lookahead negativo o no …

Molto specifico per questo modello, ma ho fatto in modo simile a questo in passato:

REPLACE(REPLACE(columName, '<', '&lt'), '&lt', '<')

esempio più ampio (codifica caratteri che possono essere inappropriati in un attributo TITLE)

 REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( columName -- Remove existing encoding: , '&', '&') , '"', '"') , ''', '''') -- Reinstate/Encode: , '&', '&') -- Encode: , '"', '"') , '''', ''') , ' ', '%20') , '<', '%3C') , '>', '%3E') , '/', '%2F') , '\', '%5C')