2012-11-05 26 views
13

Ho un database di grandi dimensioni in cui voglio eseguire una ricerca di stringhe di parti. L'utente inserirà i caratteri: JoeBloggs.Rimuovere i numeri dal server sql stringa

Per ragioni di argomenti, se nel database ho un nome Joe 23 Blo Ggs 4. Voglio rimuovere tutto nel nome diverso da A-Z.

Ho la funzione REPLACE(Name, ' ','') per rimuovere gli spazi e la funzione per scrivere in maiuscolo il nome.

Esiste un modo più efficiente e veloce, forse in base alla regex, per sostituire qualsiasi cosa diversa dalla A-Z. Non riesco a modificare i valori nel database.

Grazie in anticipo

+0

Si dice che non è possibile modificare i dati. Puoi aggiungere una colonna calcolata alla tabella esistente? Oppure aggiungi una nuova tabella con una chiave esterna e il tuo valore calcolato? – Laurence

+0

@Laurence - Sì, suppongo di poterlo fare, ma possiamo farlo in una tabella temporanea in una stored procedure? Se no, allora posso richiedere questa colonna calcolata, tutto ciò di cui ho bisogno è la funzione per fare la sostituzione. Grazie per la tua pronta risposta – CR41G14

+0

Non ti consiglio di usare espressioni regolari se le prestazioni sono importanti. Il modo in cui usi è ovvio ma comunque buono! – vyakhir

risposta

25

prima opzione -

È possibile annidate REPLACE() funzioni fino a 32 livelli di profondità. Funziona veloce.

REPLACE 
(REPLACE 
(REPLACE 
(REPLACE 
(REPLACE 
(REPLACE 
(REPLACE 
(REPLACE 
(REPLACE 
(REPLACE (@str, '0', ''), 
'1', ''), 
'2', ''), 
'3', ''), 
'4', ''), 
'5', ''), 
'6', ''), 
'7', ''), 
'8', ''), 
'9', '') 

seconda opzione - fare il contrario di -

Removing nonnumerical data out of a number + SQL

terza opzione - se si desidera utilizzare regeex

poi http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=27205

-1
Non

testato, ma puoi fare qualcosa del genere:

Create Function dbo.AlphasOnly(@s as varchar(max)) Returns varchar(max) As 
Begin 
    Declare @Pos int = 1 
    Declare @Ret varchar(max) = null 
    If @s Is Not Null 
    Begin 
    Set @Ret = '' 
    While @Pos <= Len(@s) 
    Begin 
     If SubString(@s, @Pos, 1) Like '[A-Za-z]' 
     Begin 
     Set @Ret = @Ret + SubString(@s, @Pos, 1) 
     End 
     Set @Pos = @Pos + 1 
    End 
    End 
    Return @Ret 
End 

La chiave è utilizzare questa colonna come colonna calcolata e indicizzarla. Non importa quanto velocemente si esegue questa funzione se il database deve eseguirlo su ogni riga della tabella di grandi dimensioni ogni volta che si esegue la query.

+0

soluzione molto lenta, veloce è richiesta – CR41G14

+0

Se si insistere nel fare 'Seleziona nome dal test dove dbo.AlphasOnly (name) = 'JoeBloggs'' allora questo sarà lento anche se la funzione impiega 0 volte. Paghi comunque il costo di leggere tutte le righe dal disco (assumendo quando diciamo che nella tabella grande si intende che il database non si adatta alla memoria). Per velocizzare è necessario trovare un modo per indicizzarlo, motivo per cui suggerisco una colonna calcolata. – Laurence

12

Questo funziona per me

CREATE Function [dbo].[RemoveNumericCharacters](@Temp VarChar(1000)) 
Returns VarChar(1000) 
AS 
Begin 

    Declare @NumRange as varchar(50) = '%[0-9]%' 
    While PatIndex(@NumRange, @Temp) > 0 
     Set @Temp = Stuff(@Temp, PatIndex(@NumRange, @Temp), 1, '') 

    Return @Temp 
End 

ed è possibile utilizzarlo in questo modo

SELECT dbo.[RemoveNumericCharacters](Name) FROM TARGET_TABLE 
0

Citando parte di @Jatin risposta con alcune modifiche,

uso questo nella vostra dichiarazione where :

SELECT * FROM .... etc. 
     Where 
     REPLACE 
     (REPLACE 
     (REPLACE 
     (REPLACE 
     (REPLACE 
     (REPLACE 
     (REPLACE 
     (REPLACE 
     (REPLACE 
     (REPLACE (Name, '0', ''), 
     '1', ''), 
     '2', ''), 
     '3', ''), 
     '4', ''), 
     '5', ''), 
     '6', ''), 
     '7', ''), 
     '8', ''), 
     '9', '') = P_SEARCH_KEY 
2

Un altro approccio con CTE ricorsiva ..

declare @string varchar(100) 
set @string ='te165st1230004616161616' 

;With cte 
as 
(
select @string as string,0 as n 
union all 
select cast(replace(string,n,'') as varchar(100)),n+1 
from cte 
where n<9 
) 
select top 1 string from cte 
order by n desc 


**Output:** 
    test 
0

Prova di seguito per la query. dove val è il nome della stringa o della colonna.

CASE WHEN PATINDEX('%[a-z]%', REVERSE(val)) > 1 
       THEN LEFT(val, LEN(val) - PATINDEX('%[a-z]%', REVERSE(val)) + 1) 
      ELSE '' END 
Problemi correlati