J'ai une table MySQL où toutes les données dans une colonne ont été entrées en MAJUSCULE, mais je dois les convertir en cas de titre, avec reconnaissance des "petits mots" qui s'apparentent au script Daring Fireball Title Case .
J'ai trouvé cette excellente solution pour transformer des chaînes en minuscules, mais la fonction Case Title semble avoir été omise de ma version de MySQL. Existe-t-il une manière élégante de procéder?
Courtiser! Je ne suis pas du tout à l'aise avec SQL; Voici la méthode qui a fonctionné pour moi:
Recherchez et remplacez chaque instance de:
INSERT INTO `Table` (`Col1`, `Col2`, `Etc`, ...) VALUES
avec les bonnes valeurs en minuscules.
UPDATE table SET colname=LOWER(colname);
pour réinitialiser les valeurs en minuscules des colonnes qui doivent être en minuscules.La raison pour laquelle je n'ai pas essayé d'utiliser Textmate auparavant était que je ne pouvais pas comprendre comment convertir une seule colonne en Case Titre sans ruiner les autres données, mais cette méthode semble fonctionner. Merci pour vos conseils et votre soutien!
Modifier
Eureka! Littéralement ma première fonction SQL. Aucune garantie offerte. Sauvegardez vos données avant de les utiliser. :)
Définissez d'abord la fonction suivante:
DROP FUNCTION IF EXISTS lowerword;
SET GLOBAL log_bin_trust_function_creators=TRUE;
DELIMITER |
CREATE FUNCTION lowerword( str VARCHAR(128), Word VARCHAR(5) )
RETURNS VARCHAR(128)
DETERMINISTIC
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE loc INT;
SET loc = LOCATE(CONCAT(Word,' '), str, 2);
IF loc > 1 THEN
WHILE i <= LENGTH (str) AND loc <> 0 DO
SET str = INSERT(str,loc,LENGTH(Word),LCASE(Word));
SET i = loc+LENGTH(Word);
SET loc = LOCATE(CONCAT(Word,' '), str, i);
END WHILE;
END IF;
RETURN str;
END;
|
DELIMITER ;
Cela réduira toutes les occurrences de Word dans str.
Définissez ensuite cette fonction propre modifiée:
DROP FUNCTION IF EXISTS tcase;
SET GLOBAL log_bin_trust_function_creators=TRUE;
DELIMITER |
CREATE FUNCTION tcase( str VARCHAR(128) )
RETURNS VARCHAR(128)
DETERMINISTIC
BEGIN
DECLARE c CHAR(1);
DECLARE s VARCHAR(128);
DECLARE i INT DEFAULT 1;
DECLARE bool INT DEFAULT 1;
DECLARE punct CHAR(17) DEFAULT ' ()[]{},.-_!@;:?/';
SET s = LCASE( str );
WHILE i <= LENGTH( str ) DO
BEGIN
SET c = SUBSTRING( s, i, 1 );
IF LOCATE( c, punct ) > 0 THEN
SET bool = 1;
ELSEIF bool=1 THEN
BEGIN
IF c >= 'a' AND c <= 'z' THEN
BEGIN
SET s = CONCAT(LEFT(s,i-1),UCASE(c),SUBSTRING(s,i+1));
SET bool = 0;
END;
ELSEIF c >= '0' AND c <= '9' THEN
SET bool = 0;
END IF;
END;
END IF;
SET i = i+1;
END;
END WHILE;
SET s = lowerword(s, 'A');
SET s = lowerword(s, 'An');
SET s = lowerword(s, 'And');
SET s = lowerword(s, 'As');
SET s = lowerword(s, 'At');
SET s = lowerword(s, 'But');
SET s = lowerword(s, 'By');
SET s = lowerword(s, 'For');
SET s = lowerword(s, 'If');
SET s = lowerword(s, 'In');
SET s = lowerword(s, 'Of');
SET s = lowerword(s, 'On');
SET s = lowerword(s, 'Or');
SET s = lowerword(s, 'The');
SET s = lowerword(s, 'To');
SET s = lowerword(s, 'Via');
RETURN s;
END;
|
DELIMITER ;
Utilisation
Vérifiez que cela fonctionne comme prévu:
SELECT tcase(title) FROM table;
Utilise le:
UPDATE table SET title = tcase(title);
Source: http://www.artfulsoftware.com/infotree/queries.php?&bw=1070#122
umm quelque chose comme ça peut fonctionner
UPDATE table_name SET `col_name`= CONCAT( UPPER( SUBSTRING( `col_name`, 1, 1 ) ) , LOWER( SUBSTRING( `col_name` FROM 2 ) ) );
Si vous avez besoin d'ajouter des acronymes personnalisés et d'autres modèles de capitalisation personnalisés dans le mélange, j'ai généralisé la réponse de hobodave:
DELIMITER |
CREATE FUNCTION replaceword( str VARCHAR(128), Word VARCHAR(128) )
RETURNS VARCHAR(128)
DETERMINISTIC
BEGIN
DECLARE loc INT;
DECLARE punct CHAR(27) DEFAULT ' ()[]{},.-_!@;:?/''"#$%^&*<>';
DECLARE lowerWord VARCHAR(128);
DECLARE lowerStr VARCHAR(128);
IF LENGTH(Word) = 0 THEN
RETURN str;
END IF;
SET lowerWord = LOWER(Word);
SET lowerStr = LOWER(str);
SET loc = LOCATE(lowerWord, lowerStr, 1);
WHILE loc > 0 DO
IF loc = 1 OR LOCATE(SUBSTRING(str, loc-1, 1), punct) > 0 THEN
IF loc+LENGTH(Word) > LENGTH(str) OR LOCATE(SUBSTRING(str, loc+LENGTH(Word), 1), punct) > 0 THEN
SET str = INSERT(str,loc,LENGTH(Word),Word);
END IF;
END IF;
SET loc = LOCATE(lowerWord, lowerStr, loc+LENGTH(Word));
END WHILE;
RETURN str;
END;
|
DELIMITER ;
DELIMITER |
CREATE FUNCTION tcase( str VARCHAR(128) )
RETURNS VARCHAR(128)
DETERMINISTIC
BEGIN
DECLARE c CHAR(1);
DECLARE s VARCHAR(128);
DECLARE i INT DEFAULT 1;
DECLARE bool INT DEFAULT 1;
DECLARE punct CHAR(27) DEFAULT ' ()[]{},.-_!@;:?/''"#$%^&*<>';
SET s = LCASE( str );
WHILE i <= LENGTH( str ) DO
BEGIN
SET c = SUBSTRING( s, i, 1 );
IF LOCATE( c, punct ) > 0 THEN
SET bool = 1;
ELSEIF bool=1 THEN
BEGIN
IF c >= 'a' AND c <= 'z' THEN
BEGIN
SET s = CONCAT(LEFT(s,i-1),UCASE(c),SUBSTRING(s,i+1));
SET bool = 0;
END;
ELSEIF c >= '0' AND c <= '9' THEN
SET bool = 0;
END IF;
END;
END IF;
SET i = i+1;
END;
END WHILE;
SET s = replaceword(s, 'a');
SET s = replaceword(s, 'an');
SET s = replaceword(s, 'and');
SET s = replaceword(s, 'as');
SET s = replaceword(s, 'at');
SET s = replaceword(s, 'but');
SET s = replaceword(s, 'by');
SET s = replaceword(s, 'for');
SET s = replaceword(s, 'if');
SET s = replaceword(s, 'in');
SET s = replaceword(s, 'n');
SET s = replaceword(s, 'of');
SET s = replaceword(s, 'on');
SET s = replaceword(s, 'or');
SET s = replaceword(s, 'the');
SET s = replaceword(s, 'to');
SET s = replaceword(s, 'via');
SET s = replaceword(s, 'RSS');
SET s = replaceword(s, 'URL');
SET s = replaceword(s, 'PHP');
SET s = replaceword(s, 'SQL');
SET s = replaceword(s, 'OPML');
SET s = replaceword(s, 'DHTML');
SET s = replaceword(s, 'CSV');
SET s = replaceword(s, 'iCal');
SET s = replaceword(s, 'XML');
SET s = replaceword(s, 'PDF');
SET c = SUBSTRING( s, 1, 1 );
IF c >= 'a' AND c <= 'z' THEN
SET s = CONCAT(UCASE(c),SUBSTRING(s,2));
END IF;
RETURN s;
END;
|
DELIMITER ;
Il consiste essentiellement en une fonction de remplacement de mots insensible à la casse et une fonction pour mettre en majuscule la première lettre de chaque mot et effectuer des transformations pour des mots spécifiques.
J'espère que c'est utile à quelqu'un.
Ma solution pour un cas simple et approprié:
CREATE FUNCTION `proper_case`(str varchar(128)) RETURNS varchar(128)
BEGIN
DECLARE n, pos INT DEFAULT 1;
DECLARE sub, proper VARCHAR(128) DEFAULT '';
if length(trim(str)) > 0 then
WHILE pos > 0 DO
set pos = locate(' ',trim(str),n);
if pos = 0 then
set sub = lower(trim(substr(trim(str),n)));
else
set sub = lower(trim(substr(trim(str),n,pos-n)));
end if;
set proper = concat_ws(' ', proper, concat(upper(left(sub,1)),substr(sub,2)));
set n = pos + 1;
END WHILE;
end if;
RETURN trim(proper);
END
Utilisez-le comme:
SELECT proper_case("JOHN DOE");
Production:
John Doe
J'ai utilisé quelque chose comme ça
UPDATE `tablename`
SET `fieldname` = CONCAT(UCASE(SUBSTRING(`fieldname`,1,1)),'', LCASE(SUBSTRING(`fieldname`,2,LENGTH(`fieldname`))))
Remarque: Cela ne convertira que le premier caractère en majuscules. et le reste de la valeur en minuscules.
Cela fonctionne pour moi dans My SQL 5.0
DELIMITER |
CREATE FUNCTION CamelCase(str VARCHAR(8000))
RETURNS VARCHAR(8000)
BEGIN
DECLARE result VARCHAR(8000);
SET str = CONCAT(' ',str,' ');
SET result = '';
WHILE LENGTH(str) > 1 DO
SET str = SUBSTR(str,INSTR(str,' ')+1,LENGTH(str));
SET result = CONCAT(result,UPPER(LEFT(str,1)), LOWER(SUBSTR(str,2,INSTR(str,' ') - 1)) ) ;
SET str = SUBSTR(str,INSTR(str,' '),LENGTH(str));
END WHILE;
RETURN result;
END
|
DELIMITER ;
Celui-ci fonctionne pour moi.
UPDATE `suburbs`
SET title2 = CONCAT_WS(' ',
CONCAT(UPPER(LEFT(SUBSTRING_INDEX(title, ' ',1),1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',1),2))),
CONCAT(UPPER(MID(SUBSTRING_INDEX(title, ' ',2),LENGTH(SUBSTRING_INDEX(title, ' ',1)) + 2, 1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',2),3 + LENGTH(SUBSTRING_INDEX(title, ' ',1))))),
CONCAT(UPPER(MID(SUBSTRING_INDEX(title, ' ',3),LENGTH(SUBSTRING_INDEX(title, ' ',2)) + 2, 1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',3),3 + LENGTH(SUBSTRING_INDEX(title, ' ',2))))),
CONCAT(UPPER(MID(SUBSTRING_INDEX(title, ' ',4),LENGTH(SUBSTRING_INDEX(title, ' ',3)) + 2, 1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',4),3 + LENGTH(SUBSTRING_INDEX(title, ' ',3))))),
CONCAT(UPPER(MID(SUBSTRING_INDEX(title, ' ',5),LENGTH(SUBSTRING_INDEX(title, ' ',4)) + 2, 1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',5),3 + LENGTH(SUBSTRING_INDEX(title, ' ',4))))),
CONCAT(UPPER(MID(SUBSTRING_INDEX(title, ' ',6),LENGTH(SUBSTRING_INDEX(title, ' ',5)) + 2, 1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',6),3 + LENGTH(SUBSTRING_INDEX(title, ' ',5))))),
CONCAT(UPPER(MID(SUBSTRING_INDEX(title, ' ',7),LENGTH(SUBSTRING_INDEX(title, ' ',6)) + 2, 1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',7),3 + LENGTH(SUBSTRING_INDEX(title, ' ',6))))),
CONCAT(UPPER(MID(SUBSTRING_INDEX(title, ' ',8),LENGTH(SUBSTRING_INDEX(title, ' ',7)) + 2, 1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',8),3 + LENGTH(SUBSTRING_INDEX(title, ' ',7))))),
CONCAT(UPPER(MID(SUBSTRING_INDEX(title, ' ',9),LENGTH(SUBSTRING_INDEX(title, ' ',8)) + 2, 1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',9),3 + LENGTH(SUBSTRING_INDEX(title, ' ',8))))),
CONCAT(UPPER(MID(SUBSTRING_INDEX(title, ' ',10),LENGTH(SUBSTRING_INDEX(title, ' ',9)) + 2, 1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',10),3 + LENGTH(SUBSTRING_INDEX(title, ' ',9))))),
CONCAT(UPPER(MID(SUBSTRING_INDEX(title, ' ',11),LENGTH(SUBSTRING_INDEX(title, ' ',10)) + 2, 1)), LOWER(MID(SUBSTRING_INDEX(title, ' ',11),3 + LENGTH(SUBSTRING_INDEX(title, ' ',10))))))
WHERE 1
vous pouvez le faire avec concat (), substring () et length () mais je ne peux que le voir fonctionner pour un seul mot. Y a-t-il une raison spécifique pour laquelle vous ne pouvez pas faire cela dans le code de votre application, au lieu de mysql?
Le cas définitif pour rechercher une telle fonction est dans le documentation .
Malheureusement, vous avez les fonctions LOWER () et UPPER (), mais pas de casse de titre. Votre meilleur pari serait de déclarer votre propre fonction qui se divise en espaces, ignore vos petits mots et fait un UPPER sur le premier caractère de chaque mot restant.
La réponse dépendra du type de données dans la colonne, c'est-à-dire des noms de personnes, des noms de lieux, des titres de livres, etc. Si vous recherchez une solution SQL, je le ferais en plusieurs mises à jour, par exemple: