2010-10-22 4 views
3

Je voudrais capitaliser les noms correctement, ce qui signifie dans ce cas:Capitaliser noms correctement dans SQL

  • La première lettre est en majuscule.
  • La première lettre après un espace est en majuscule ('Van Helsing', pas 'Van Helsing')
  • La première lettre après un tableau de bord est capitalisé ('Johnson-Smith', pas 'Johnson-Smith')
  • Aucune autre lettre n'est en majuscule.

Les premières et dernières exigences sont faciles à manipuler:

CONCAT(LEFT(name, 1), LOWER(RIGHT(name, LENGTH(name) - 1))) 

Les autres sont plus difficiles. J'ai écrit une déclaration imbriqué-54 fois REPLACE (non à la main bien sûr, je Excel)

REPLACE(REPLACE(REPLACE(REPLACE(...,' b',' B'),'-b','-B'),' a',' A'),'-a','-A') 

mais je me sens comme il doit y avoir une solution plus élégante et maintenable. Des idées?

S'il y a une fonction intégrée qui est similaire mais pas identique à mes besoins, cela ira probablement bien.


Edit: Ce script ne fonctionne que sur les noms qui ont perdu leur capitalisation déjà, il n'y a donc pas de danger dans le mal-traitement des noms obscurs. Manipuler des apostrophes comme des espaces et des tirets serait bien, cependant. Un coup d'œil à travers les données actuelles montre que beaucoup (~ 30%) des noms ont au moins un de [- '].

+1

La « solution plus élégante » est de stocker les données dans le format que vous souhaitez commencer. Ou utilisez un script pour le sortir et le reformater. SQL n'est vraiment pas le bon outil pour cela. –

+0

Je devrais retirer les données et utiliser Perl, mais s'il y avait une bonne méthode en SQL je préférerais l'utiliser. – Charles

Répondre

2

Le code frustratedwithforms affiché ne fonctionne pas correctement ... il capitalise correctement le premier d derniers mots de la chaîne et supprime tout ce qui se trouve entre (s'il y en a> 2). Quelqu'un a posté une version corrigée à l'URL qu'il a posté ...

(Voir le post de Matt Cavanaugh le 15 mai 2009 à 15h52: http://dev.mysql.com/doc/refman/5.1/en/string-functions.html)

1

Ce ne sera pas joli, mais vous pouvez utiliser SUBSTRING_INDEX pour trouver le premier espace et le tiret, et mettre en majuscule conditionnellement tout ce qui réussit.

+0

Bonne pensée, +1 pour ça. – Charles

4

Qu'en est-il de "Van den Berg" (qui a un minuscule "d"). Qu'en est-il de "McDonald" ou "O'Reilly".

Il est généralement considéré comme une mauvaise idée de surévaluer les noms des personnes, car il y aura toujours un nom légitime qui viole votre validation.

Voir aussi ma réponse à une précédente question similaire ici: How to "Validate" Human Names in CakePHP?

+0

Il serait acceptable que "Van den Berg" soit remplacé par "Van Den Berg". Ce n'est pas un script qui fonctionnera sur tous les noms sauf un qui fonctionnera sur des noms qui sont actuellement en majuscules (pour diverses raisons). Nous aurons besoin d'une secrétaire ou d'une personne du même genre pour revoir les noms, mais un tel script devrait réduire considérablement le travail requis. – Charles

+2

Assez juste - c'est un assez bon argument. – Spudley

+1

Ma faute - j'aurais dû préciser cela au départ. Je l'ai édité dans la question maintenant. – Charles

1

Vous pouvez probablement utiliser une fonction définie par l'utilisateur, ce serait beaucoup plus facile à réutiliser.

+1

Depuis MySQL ne prend pas en charge REGEXP_REPLACE, voir cette question http://stackoverflow.com/questions/986826/how-to-do-a-regular-expression-replace-in-mysql pour une réponse très similaire, avec un utile look-looking pour vous aider à démarrer. – Spudley

1

Il semble que MySQL ne dispose pas d'une fonction INITCAP, mais je trouve le code pour un ici:

http://dev.mysql.com/doc/refman/5.1/en/string-functions.html

Et le code aussi:

DELIMITER $$ 
DROP FUNCTION IF EXISTS `initcap` $$ 
CREATE FUNCTION `initcap`(x char(30)) RETURNS char(30) CHARSET utf8 
BEGIN 
SET @str=''; 
SET @l_str=''; 
WHILE x REGEXP ' ' DO 
SELECT SUBSTRING_INDEX(x, ' ', 1) INTO @l_str; 
SELECT SUBSTRING(x, LOCATE(' ', x)+1) INTO x; 
SELECT CONCAT(@str, ' ', CONCAT(UPPER(SUBSTRING(@l_str,1,1)),LOWER(SUBSTRING(@l_str,2)))) INTO @str; 
END WHILE; 
RETURN LTRIM(CONCAT(@str, ' ', CONCAT(UPPER(SUBSTRING(x,1,1)),LOWER(SUBSTRING(x,2))))); 
END $$ 
DELIMITER ; 

Disclaimer: Je n » t écrire ce code, je ne l'ai même pas testé ...

Questions connexes