61 votes

Moyen le plus rapide de supprimer les caractères non numériques d'un VARCHAR dans SQL Server

Je suis en train d'écrire un utilitaire d'importation qui est à l'aide des numéros de téléphone comme clé unique au sein de l'importation.

J'ai besoin de vérifier que le numéro de téléphone n'existe pas déjà dans ma DB. Le problème est que les numéros de téléphone dans la base de données pourrait avoir des choses comme les tirets et les parenthèses et peut-être d'autres choses. J'ai écrit une fonction pour supprimer ces choses, le problème est qu'il est lent et avec des milliers d'enregistrements dans ma DB et des milliers de dossiers à importer à la fois, ce processus peut être exagérément lente. J'ai déjà fait la colonne des numéros de téléphone d'un index.

J'ai essayé d'utiliser le script de ce post:
http://stackoverflow.com/questions/52315/t-sql-trim-nbsp-and-other-non-alphanumeric-characters

Mais ça n'a pas l'accélérer tout.

Est-il un moyen plus rapide pour supprimer des caractères non numériques? Quelque chose qui peut bien performer lors de 10 000 à 100 000 enregistrements doivent être comparées.

Tout ce qui est fait doit effectuer rapidement.

Mise à jour
Compte tenu de ce que les gens ont répondu, je pense que je vais avoir à nettoyer les champs avant de me exécuter l'utilitaire d'importation.

Pour répondre à la question de ce que je suis en train d'écrire l'utilitaire d'importation, c'est une application en C#. Je suis la comparaison de type BIGINT BIGINT maintenant, sans avoir besoin de modifier DB données et je prends quand même un gain de performance avec un très petit ensemble de données (environ 2000 dossiers).

Pourrait comparer de type BIGINT BIGINT être ralentir les choses?

J'ai optimisé le code côté de mon application autant que je le peux (supprimé regexes, retiré inutile DB appels). Bien que je ne peux pas isoler SQL comme la source du problème, je me sens toujours comme il est.

103voto

David Coster Points 670

J'ai vu cette solution avec le code T-SQL et PATINDEX. Je l'aime :-)

 CREATE Function [fnRemoveNonNumericCharacters](@strText VARCHAR(1000))
RETURNS VARCHAR(1000)
AS
BEGIN
    WHILE PATINDEX('%[^0-9]%', @strText) > 0
    BEGIN
        SET @strText = STUFF(@strText, PATINDEX('%[^0-9]%', @strText), 1, '')
    END
    RETURN @strText
END
 

37voto

Brainwater Points 31

replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(string,'a',"),'b',"),'c',"),'d',"),'e',"),'f',"),'g',"),'h',"),'i',"),'j',"),'k',"),'l',"),'m',"),'n',"),'o',"),'p',"),'q',"),'r',"),'s',"),'t',"),'u',"),'v',"),'w',"),'x',"),'y',"),'z',"),'A',"),'B',"),'C',"),'D',"),'E',"),'F',"),'G',"),'H',"),'I',"),'J',"),'K',"),'L',"),'M',"),'N',"),'O',"),'P',"),'Q',"),'R',"),'S',"),'T',"),'U',"),'V',"),'W',"),'X',"),'Y',"),'Z',")*1 COMME une chaîne de caractères,

:)

16voto

Scott Nichols Points 3366

Je peut mal comprendre, mais vous avez deux ensembles de données pour supprimer les chaînes à partir de l'un pour les données en cours dans la base de données et puis un nouveau jeu à chaque fois que vous importez.

Pour mettre à jour les enregistrements existants, je voudrais juste utiliser SQL, qu'une seule fois.

Toutefois, SQL n'est pas optimisé pour ce genre d'opération, puisque vous avez dit que vous écrivez un utilitaire d'importation, je ferais les mises à jour dans le contexte de l'utilitaire d'importation de lui-même, pas en SQL. Ce serait beaucoup mieux la performance sage. Ce que vous écrivez l'utilité?

Aussi, je suis peut-être complètement à l'incompréhension du processus, donc je m'excuse si l'extérieur de la base.

Edit:
Pour la première mise à jour, si vous utilisez SQL Server 2005, vous pouvez essayer une fonction CLR. Voici un rapide à l'aide de regex. Pas sûr de savoir comment les performances de comparer, je n'ai jamais utilisé moi-même, sauf pour un test rapide maintenant.

using System;  
using System.Data;  
using System.Text.RegularExpressions;  
using System.Data.SqlClient;  
using System.Data.SqlTypes;  
using Microsoft.SqlServer.Server;  

public partial class UserDefinedFunctions  
{  
    [Microsoft.SqlServer.Server.SqlFunction]  
    public static SqlString StripNonNumeric(SqlString input)  
    {  
    	Regex regEx = new Regex(@"\D");  
    	return regEx.Replace(input.Value, "");  
    }  
};

Après il est déployé, à la mise à jour que vous pouvez simplement utiliser:

UPDATE table SET phoneNumber = dbo.StripNonNumeric(phoneNumber)

16voto

Tom Points 104

Si vous ne souhaitez pas créer de fonction ou si vous n'avez besoin que d'un seul appel en ligne dans T-SQL, vous pouvez essayer:

 set @Phone = REPLACE(REPLACE(REPLACE(REPLACE(@Phone,'(',''),' ',''),'-',''),')','')
 

Bien sûr, cela est spécifique à la suppression du formatage du numéro de téléphone, pas à un générique pour supprimer tous les caractères spéciaux de la fonction chaîne.

10voto

AdamE Points 31

Fonction simple:

 CREATE FUNCTION [dbo].[RemoveAlphaCharacters](@InputString VARCHAR(1000))
RETURNS VARCHAR(1000)
AS
BEGIN
  WHILE PATINDEX('%[^0-9]%',@InputString)>0
        SET @InputString = STUFF(@InputString,PATINDEX('%[^0-9]%',@InputString),1,'')     
  RETURN @InputString
END

GO
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X