如何从string中删除所有非字母数字字符?

我正在比较string的例程,但为了更好的效率,我需要删除所有不是字母或数字的字符。

我现在使用多个REPLACE函数,但也许有一个更快,更好的解决scheme?

这些答案都没有为我工作。 我必须创造我自己的称为alphanum的function,剥夺了我的字符:

 DROP FUNCTION IF EXISTS alphanum; DELIMITER | CREATE FUNCTION alphanum( str CHAR(32) ) RETURNS CHAR(16) BEGIN DECLARE i, len SMALLINT DEFAULT 1; DECLARE ret CHAR(32) DEFAULT ''; DECLARE c CHAR(1); SET len = CHAR_LENGTH( str ); REPEAT BEGIN SET c = MID( str, i, 1 ); IF c REGEXP '[[:alnum:]]' THEN SET ret=CONCAT(ret,c); END IF; SET i = i + 1; END; UNTIL i > len END REPEAT; RETURN ret; END | DELIMITER ; 

现在我可以这样做:

 select 'This works finally!', alphanum('This works finally!'); 

我得到:

 +---------------------+---------------------------------+ | This works finally! | alphanum('This works finally!') | +---------------------+---------------------------------+ | This works finally! | Thisworksfinally | +---------------------+---------------------------------+ 1 row in set (0.00 sec) 

欢呼!

从性能的angular度来看,(假设你读得比你写得多)

我认为最好的方法是预先计算并存储一个已删除的列的版本,这样你就可以减less变换。

然后,您可以在新列上放置索引,并让数据库为您完成工作。

 SELECT teststring REGEXP '[[:alnum:]]+'; SELECT * FROM testtable WHERE test REGEXP '[[:alnum:]]+'; 

请参阅: http : //dev.mysql.com/doc/refman/5.1/en/regexp.html
向下滚动到以下部分: [:character_class:]

如果你想操纵string,最快的方法是使用str_udf,参见:
https://github.com/hholzgra/mysql-udf-regexp

我写了这个UDF,但是我刚刚开始修改特殊字符,并转换为较低的值。 但是你可以更新这个function

 DELIMITER // DROP FUNCTION IF EXISTS DELETE_DOUBLE_SPACES// CREATE FUNCTION DELETE_DOUBLE_SPACES ( title VARCHAR(250) ) RETURNS VARCHAR(250) DETERMINISTIC BEGIN DECLARE result VARCHAR(250); SET result = REPLACE( title, ' ', ' ' ); WHILE (result <> title) DO SET title = result; SET result = REPLACE( title, ' ', ' ' ); END WHILE; RETURN result; END// DROP FUNCTION IF EXISTS LFILTER// CREATE FUNCTION LFILTER ( title VARCHAR(250) ) RETURNS VARCHAR(250) DETERMINISTIC BEGIN WHILE (1=1) DO IF( ASCII(title) BETWEEN ASCII('a') AND ASCII('z') OR ASCII(title) BETWEEN ASCII('A') AND ASCII('Z') OR ASCII(title) BETWEEN ASCII('0') AND ASCII('9') ) THEN SET title = LOWER( title ); SET title = REPLACE( REPLACE( REPLACE( title, CHAR(10), ' ' ), CHAR(13), ' ' ) , CHAR(9), ' ' ); SET title = DELETE_DOUBLE_SPACES( title ); RETURN title; ELSE SET title = SUBSTRING( title, 2 ); END IF; END WHILE; END// DELIMITER ; SELECT LFILTER(' !@#$%^&*()_+1a b'); 

你也可以使用正则expression式,但是需要安装MySql扩展

我能够find(和使用)最快的方式是convert()。

从Doc。 CONVERT()与USING用于在不同字符集之间转换数据。

例:

 convert(string USING ascii) 

在你的情况下,正确的字符集将是自定义的

来自Doc。 CONVERT()USINGforms从4.1.0开始提供 。

请注意,像“或”这样的字符被MySQL视为alpha。 最好使用像这样的东西:

如果在“a”和“z”之间或c在“a”和“z”之间或c在“0”和“9”之间或c =“ – ”则

根据Ryan Shillington的回答 ,修改后可处理超过255个字符的string,并保留原始string的空格。

仅供参考,最终还是会lower(str)

我用这个来比较string:

 DROP FUNCTION IF EXISTS spacealphanum; DELIMITER $$ CREATE FUNCTION `spacealphanum`( str TEXT ) RETURNS TEXT CHARSET utf8 BEGIN DECLARE i, len SMALLINT DEFAULT 1; DECLARE ret TEXT DEFAULT ''; DECLARE c CHAR(1); SET len = CHAR_LENGTH( str ); REPEAT BEGIN SET c = MID( str, i, 1 ); IF c REGEXP '[[:alnum:]]' THEN SET ret=CONCAT(ret,c); ELSEIF c = ' ' THEN SET ret=CONCAT(ret," "); END IF; SET i = i + 1; END; UNTIL i > len END REPEAT; SET ret = lower(ret); RETURN ret; END $$ DELIMITER ; 

拉丁文和西里尔文字符的直接和战斗解决scheme:

 DELIMITER // CREATE FUNCTION `remove_non_numeric_and_letters`(input TEXT) RETURNS TEXT BEGIN DECLARE output TEXT DEFAULT ''; DECLARE iterator INT DEFAULT 1; WHILE iterator < (LENGTH(input) + 1) DO IF SUBSTRING(input, iterator, 1) IN ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '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', 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', 'а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я') THEN SET output = CONCAT(output, SUBSTRING(input, iterator, 1)); END IF; SET iterator = iterator + 1; END WHILE; RETURN output; END // DELIMITER ; 

用法:

 -- outputs "hello12356" SELECT remove_non_numeric_and_letters('hello - 12356-привет ""]') 

我有一个类似的问题,试图匹配我们的数据库中的姓氏略有不同。 例如,有时人们input“麦当劳”,“麦当劳”,“圣约翰”和“圣约翰”的同名人名。

我没有试图转换Mysql数据,而是通过创build一个函数(在PHP中)来解决这个问题,该函数需要一个string并创build一个只有alpha的正则expression式:

 function alpha_only_regex($str) { $alpha_only = str_split(preg_replace('/[^AZ]/i', '', $str)); return '^[^a-zA-Z]*'.implode('[^a-zA-Z]*', $alpha_only).'[^a-zA-Z]*$'; } 

现在我可以用这样的查询来search数据库:

 $lastname_regex = alpha_only_regex($lastname); $query = "SELECT * FROM my_table WHERE lastname REGEXP '$lastname_regex'; 

到目前为止,唯一可以比其他答案简单的方法是确定列的全部特殊字符,即当前正在使用的所有特殊字符,然后按顺序replace所有这些字符,例如

 update pages set slug = lower(replace(replace(replace(replace(name, ' ', ''), '-', ''), '.', ''), '&', '')); # replacing just space, -, ., & only 

这只对一组已知的数据是可取的,否则对于某些特殊字符而言,使用黑名单方法而不是白名单方法是微不足道的。

显然,最简单的方法是由于缺乏强大的内置白名单(例如,通过正则expression式replace)来预先validationsql以外的数据。

可能是一个愚蠢的build议与其他人相比:

 if(!preg_match("/^[a-zA-Z0-9]$/",$string)){ $sortedString=preg_replace("/^[a-zA-Z0-9]+$/","",$string); } 

我只需要在一个过程中只获得一个string的字母字符,并且做到了:

 SET @source = "whatever you want"; SET @target = ''; SET @i = 1; SET @len = LENGTH(@source); WHILE @i <= @len DO SET @char = SUBSTRING(@source, @i, 1); IF ((ORD(@char) >= 65 && ORD(@char) <= 90) || (ORD(@char) >= 97 && ORD(@char) <= 122)) THEN SET @target = CONCAT(@target, @char); END IF; SET @i = @i + 1; END WHILE; 

我尝试了一些解决scheme,但在最后使用replace 。 我的数据集是零件号码,我相当清楚会发生什么。 但为了理智,我使用PHP来构build长查询:

 $dirty = array(' ', '-', '.', ',', ':', '?', '/', '!', '&', '@'); $query = 'part_no'; foreach ($dirty as $dirt) { $query = "replace($query,'$dirt','')"; } echo $query; 

这输出了我曾经头疼的东西:

 replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(part_no,' ',''),'-',''),'.',''),',',''),':',''),'?',''),'/',''),'!',''),'&',''),'@','') 

这可以通过在另一个答案中发布的正则expression式replace函数来完成。 (这可能不是最有效的解决办法,而且可能看起来有点矫枉过正,但被certificate是一种“瑞士军刀”,可能因其他原因而有用)。

在动作中可以看到删除所有非字母数字字符: SQL Fiddle演示 。

SQL (为简洁起见,不包括函数代码)

 SELECT txt, reg_replace(txt, '[^a-zA-Z0-9]+', '', TRUE, 0, 0 ) AS `reg_replaced` FROM test; 

如果你使用的PHP然后….

 try{ $con = new PDO ("mysql:host=localhost;dbname=dbasename","root",""); } catch(PDOException $e){ echo "error".$e-getMessage(); } $select = $con->prepare("SELECT * FROM table"); $select->setFetchMode(PDO::FETCH_ASSOC); $select->execute(); while($data=$select->fetch()){ $id = $data['id']; $column = $data['column']; $column = preg_replace("/[^a-zA-Z0-9]+/", " ", $column); //remove all special characters $update = $con->prepare("UPDATE table SET column=:column WHERE id='$id'"); $update->bindParam(':column', $column ); $update->execute(); // echo $column."<br>"; } 

alphanum函数(自我回答)有一个bug,但我不知道为什么。 对于文本“CAS合成器75W140 1L”返回“cassyntls75W1401”,从最后“L”是缺less一些如何。

现在我用

 delimiter // DROP FUNCTION IF EXISTS alphanum // CREATE FUNCTION alphanum(prm_strInput varchar(255)) RETURNS VARCHAR(255) DETERMINISTIC BEGIN DECLARE i INT DEFAULT 1; DECLARE v_char VARCHAR(1); DECLARE v_parseStr VARCHAR(255) DEFAULT ' '; WHILE (i <= LENGTH(prm_strInput) ) DO SET v_char = SUBSTR(prm_strInput,i,1); IF v_char REGEXP '^[A-Za-z0-9]+$' THEN SET v_parseStr = CONCAT(v_parseStr,v_char); END IF; SET i = i + 1; END WHILE; RETURN trim(v_parseStr); END // 

(在谷歌find)