欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

MySQL:从字符串中提取数字、英文字符和中文字符

最编程 2024-04-23 08:09:51
...

在进行字符串处理时,常常需要提取其中某一类型的字符,有时候需要提取其中的数字,有时需要提取其中的英文字符,而有时候则需要提取其中的中文字符。

这里利用正则匹配,实现了该功能。

废话少说,直接上码:

DELIMITER $$
 
DROP FUNCTION IF EXISTS `Num_char_extract`$$
 
CREATE FUNCTION `Num_char_extract`(Varstring VARCHAR(100)CHARSET utf8, flag INT) RETURNS VARCHAR(50) CHARSET utf8
BEGIN
	DECLARE len INT DEFAULT 0;
	DECLARE Tmp VARCHAR(100) DEFAULT '';
	SET len=CHAR_LENGTH(Varstring);
	IF flag = 0 
	THEN
		WHILE len > 0 DO
		IF MID(Varstring,len,1)REGEXP'[0-9]' THEN
		SET Tmp=CONCAT(Tmp,MID(Varstring,len,1));
		END IF;
		SET len = len - 1;
		END WHILE;
	ELSEIF flag=1
	THEN
		WHILE len > 0 DO
		IF (MID(Varstring,len,1)REGEXP '[a-zA-Z]') 
		THEN
		SET Tmp=CONCAT(Tmp,MID(Varstring,len,1));
		END IF;
		SET len = len - 1;
		END WHILE;
	ELSEIF flag=2
	THEN
		WHILE len > 0 DO
		IF ( (MID(Varstring,len,1)REGEXP'[0-9]')
		OR (MID(Varstring,len,1)REGEXP '[a-zA-Z]') ) 
		THEN
		SET Tmp=CONCAT(Tmp,MID(Varstring,len,1));
		END IF;
		SET len = len - 1;
		END WHILE;
	ELSEIF flag=3
	THEN
		WHILE len > 0 DO
		IF NOT (MID(Varstring,len,1)REGEXP '^[u0391-uFFE5]')
		THEN
		SET Tmp=CONCAT(Tmp,MID(Varstring,len,1));
		END IF;
		SET len = len - 1;
		END WHILE;
	ELSE 
		SET Tmp = 'Error: The second paramter should be in (0,1,2,3)';
		RETURN Tmp;
	END IF;
	RETURN REVERSE(Tmp);
    END$$
 
DELIMITER ;

利用上述代码,在MySQL中创建一个名为Num_char_extract的函数,即可通过调用该函数进行字符提取。

使用方法如下:

(1) 第二个参数为0:代表提取数字

(2) 第二个参数为1:代表提取字母

(3) 第二个参数为2:代表提取数字+字母

(4) 第二个参数为3:代表提取汉字

(5) 第二个参数为其他数字:打印错误提示

示例2:

DELIMITER $$
DROP FUNCTION IF EXISTS `Num_char_extract3`$$
CREATE FUNCTION `Num_char_extract3`(Varstring VARCHAR(100)CHARSET utf8, myFlag VARCHAR(100) CHARSET utf8) RETURNS VARCHAR(50) CHARSET utf8
BEGIN
	DECLARE len INT DEFAULT 0; -- Varstring的总长度
	DECLARE bLen INT DEFAULT 0;-- 当前循环开始的字符位置
	DECLARE flag INT DEFAULT 0; -- 定义获取文字的类别,0 表示(0),(-1)这种格式;1,表示D1,D2这种格式
	DECLARE myText VARCHAR(100) DEFAULT '';-- myFlag中的文字,例如(-1),则myText为-1;(1),则myText为1
	DECLARE myTextNum INT DEFAULT 0; -- 和myText对应,是myText对应的数字
	DECLARE myIndex INT DEFAULT -1;-- D1,D2里面1,2的数字
	DECLARE Tmp VARCHAR(100) DEFAULT '';-- 返回的字符串
	DECLARE v_isFind BOOL DEFAULT FALSE;-- 标记是否找到
	DECLARE prevChar VARCHAR(1) DEFAULT NULL;-- 上一个字符
	DECLARE myReturn VARCHAR(100) DEFAULT '';
	SET len = CHAR_LENGTH(Varstring);
	SET bLen = 0;
	IF LOCATE ('(',myFlag) > 0 AND LOCATE (')',myFlag) > 0 THEN SET flag = 0;
	ELSEIF LOCATE ('D',myFlag) > 0 THEN SET flag = 1;	
	ELSE SET flag = -1;
	END IF;
	IF flag = 0 
	THEN  
		-- (1)取()中的按照字符串分割,取索引位置为0值,例如马栏山连接线(K0+000~K3+840)”,(0)特征值取“马栏山连接线”,(1)取特征值取“K0+000~K3+840”
		SET myText = SUBSTRING_INDEX(SUBSTRING_INDEX(myFlag,')',1),'(',-1);-- 取出括号内的数字
		IF myText NOT REGEXP '[0-9]' THEN 
			SET Tmp = 'Error: The (1111) paramter should be in num';
			RETURN Tmp;
		ELSE 
			SET myTextNum = myText+0;-- 转为数字
		END IF;
		IF myText = '0' THEN -- 取括号外的内容
			WHILE bLen <= len DO
			IF MID(Varstring,bLen,1) NOT REGEXP'[(]' AND MID(Varstring,bLen,1) NOT REGEXP'[(]' THEN
				SET Tmp=CONCAT(Tmp,MID(Varstring,bLen,1));
			ELSE 
				SET bLen = len;	-- 即跳出循环
			END IF;
			SET bLen = bLen + 1;
			END WHILE; 
		ELSE
			IF LOCATE ('(',Varstring) > 0 THEN -- 兼容中文括号和外文括号
				SET myText = SUBSTRING_INDEX(SUBSTRING_INDEX(Varstring,')',1),'(',-1);
			ELSE 
				SET myText = SUBSTRING_INDEX(SUBSTRING_INDEX(Varstring,')',1),'(',-1);	
			END IF;
			SET Tmp = SPLIT_STR(myText, ',', myTextNum);	
		END IF;
	ELSEIF flag=1
	THEN
	        SET myText = SUBSTRING(myFlag,2);-- 截取D之后的所有字符
	        IF myText NOT REGEXP '[0-9]' THEN 
			SET Tmp = 'Error: The (222) paramter should be in num';
			RETURN Tmp;
		ELSE 
			SET myIndex = myText+0;-- 转为数字
		END IF;
		SET myTextNum = 0;-- 当前循环的已经获取的符合条件的个数
		-- D1,D2,D3:表示分别于分项名称中第一个开始的数字+字母的值,如冲击钻机冲孔桩径150cm以内孔深30m以内黏土,D1表示特征值的为150cm,D2特征值的为30m
		WHILE bLen <= len DO
			IF bLen > 0 THEN
				SET prevChar = MID(Varstring,bLen-1,1);-- 存放上一个的字符
			END IF;
			IF MID(Varstring,bLen,1) REGEXP '[0-9]' AND (prevChar IS NULL OR prevChar REGEXP '[0-9]' OR Tmp = '') THEN -- 获取连续的数字
				SET Tmp=CONCAT(Tmp,MID(Varstring,bLen,1));
			ELSE 
				IF prevChar REGEXP'[0-9]' AND (MID(Varstring,bLen,1) REGEXP '[a-zA-Z]') THEN-- 如果上一个是数字,当前是字母,则符合条件
					SET myTextNum = myTextNum+1;-- 已经符合条件的个数,myTextNum则累加1
					IF myIndex = myTextNum THEN -- 如果已经找到满足条件的个数了
						SET v_isFind = TRUE;
						SET Tmp=CONCAT(Tmp,MID(Varstring,bLen,1));
					END IF;
				ELSE 
					IF v_isFind THEN -- 已经找到,如果没有找到,则需要继续找
						IF (MID(Varstring,bLen,1) NOT REGEXP '[a-zA-Z]') THEN -- 只要不匹配字母,则推出
							SET bLen = len;	-- 即跳出循环
						ELSE
							SET Tmp=CONCAT(Tmp,MID(Varstring,bLen,1)); -- 匹配,则一直累加
						END IF;
					ELSE 
						SET Tmp = '';-- 开始新一轮循环
					END IF;
				END IF;
			END IF;
			SET bLen = bLen + 1;
			END WHILE; 
	ELSE 
		SET Tmp = 'Error: The second paramter should be in (0,1,2,3)';
		RETURN Tmp;
	END IF;
	RETURN Tmp;
    END$$
 
DELIMITER ;

1.查询结果

SELECT Num_char_extract3('马栏山连接线(K0+000~K3+840,连接线)','(0)');//马栏山连接线
SELECT Num_char_extract3('马栏山连接线(K0+000~K3+840,连接线)','(1)');//K0+000~K3+840
SELECT Num_char_extract3('马栏山连接线(K0+000~K3+840,连接线)','(2)');//连接线

SELECT Num_char_extract3('冲击70钻65机冲孔桩径150cm以内孔深30m以内黏土80km我的世界90我的','D0');//""
SELECT Num_char_extract3('冲击70钻65机冲孔桩径150cm以内孔深30m以内黏土80km我的世界90我的','D1');//150cm
SELECT Num_char_extract3('冲击70钻65机冲孔桩径150cm以内孔深30m以内黏土80km我的世界90我的','D2');//30m
SELECT Num_char_extract3('冲击70钻65机冲孔桩径150cm以内孔深30m以内黏土80km我的世界90我的','D3');//80km
SELECT Num_char_extract3('冲击70钻65机冲孔桩径150cm以内孔深30m以内黏土80km我的世界90我的','D4');//""

 

推荐阅读