1. 程式人生 > >需求:MYSQL表中一個欄位用逗號分隔,需要查出來split拆分並依次存入另一個表的一個欄位中

需求:MYSQL表中一個欄位用逗號分隔,需要查出來split拆分並依次存入另一個表的一個欄位中



需求:表中一個欄位用逗號分隔,需要查出來split拆分並依次存入另一個表的一個欄位中

假設問題是這丫那個的,table1中id=2的name值為'xiaoming,xiaohua,xiaowang,xiaohui',我們要取出這個name欄位值,並且根據逗號拆分出來,儲存到table2中的name欄位?

-----------------table1--------------------

id            name

1             xiaomig

2             xiaoming,xiaohua,xiaowang,xiaohui

---------------------table2------------------------

id           name        

如果要實現這個功能,MYSQL自帶函式沒有像java中的字串拆分split函式,所以需要我們自己實現類似的功能函式。

分析:

1 首先需要知道拆分完畢之後的字串陣列的個數 len 。可以根據MYSQL自帶的 lengh(param) 函式和 replace(param, oldparam, newparam) 函式結合實現。

程式碼如下:

 length(str)-length(replace(str, splitstr, ''))+1

2 然後根據計算出來的 len,迴圈該欄位的字串 str ,依次取出拆分出來的字串。據 reverse() 函式和 substring_index(param, splitparam, index) 函式結合實現,該方法非常巧妙,

程式碼如下:

reverse(substring_index( reverse(substring_index(str, splitstr, index)), splitstr, 1))

兩次擷取,兩次反轉,即可根據傳入的 index 得到每次我們要取出的字串。

根據程式碼執行順序,優先執行最裡面的substring_index函式,依次向外執行。

模擬程式碼執行為:

當 index = 1 時,

reverse(substring_index( reverse(substring_index('xiaoming,xiaohua,xiaowang,xiaohui', ',', 1)), ',', 1)) ->

reverse(substring_index( reverse('xiaoming'), ',', 1)) ->

reverse(substring_index('gnimoaix'), ',', 1)) ->

reverse('gnimoaix')->

xiaoming

當 index = 2 時,

reverse(substring_index( reverse(substring_index('xiaoming,xiaohua,xiaowang,xiaohui', ',', 2)), ',', 1)) ->

reverse(substring_index( reverse('xiaoming,xiaohua'), ',', 1)) ->

reverse(substring_index('auhoaix,gnimoaix'), ',', 1)) ->

reverse('auhoaix')->

xiaohua

當 index = 3 時,

reverse(substring_index( reverse(substring_index('xiaoming,xiaohua,xiaowang,xiaohui', ',', 3)), ',', 1)) ->

reverse(substring_index( reverse('xiaoming,xiaohua,xiaowang'), ',', 1)) ->

reverse(substring_index('gnawoaix,auhoaix,gnimoaix'), ',', 1)) ->

reverse('gnawoaix')->

xiaowang

當 index = 4 時,

reverse(substring_index( reverse(substring_index('xiaoming,xiaohua,xiaowang,xiaohui', ',', 4)), ',', 1)) ->

reverse(substring_index( reverse('xiaoming,xiaohua,xiaowang,xiaohui'), ',', 1)) ->

reverse(substring_index('iuhoaix,gnawoaix,auhoaix,gnimoaix'), ',', 1)) ->

reverse('iuhoaix')->

xiaohui

由此即可獲得所有拆分後的字串了

根據以上兩步,並使用function和procedure做了實現,程式碼如下:

-- 修改結束符,防止在mysql命令列中預設分號直接執行
delimiter $$

-- 建立一個計算拆分後字串的個數函式
drop function if exists calc_length $$
create function calc_length(str varchar(200), splitstr varchar(5)) returns int(11)
begin 
return length(str)-length(replace(str, splitstr, ''))+1;
end $$

-- 建立一個模擬的split拆分字串的函式
drop function if exists split_string $$
create definer='root'@'localhost' function split_string(str varchar(200), splitstr varchar(5), strindex int) returns varchar(255)
begin
declare result varchar(255) default '';
set result =reverse(substring_index( reverse(substring_index(str, splitstr, strindex)), splitstr, 1));
return result;
end $$

-- 建立一個儲存過程
drop procedure if exists proce_split $$
create procedure proce_split()
begin
declare cnt int default 0;
declare i int default 0;
declare str varchar(2000) default '';
select name into str from table1 where id =2;
set cnt = calc_length(str, ',');

drop table if exists table2;
create table2(id int not null, name varchar(255) not null) default charset=utf8;

while i < cnt 
do 
set i = i+1;
insert into table(id, name) values(i, split_string(str,',', i));
end while;
end $$

我們登入mysql,使用命令: mysql -u 使用者名稱 -p 

登入後我們執行上面的程式碼,完成之後,我們檢視table2中的資料

輸入程式碼:

delimiter ;
call proce_split();
select * from table2;


結果如下:

-----------------------table2--------------------------

id               name

1                xiaoming

2                xiaohua

3                xiaowang

4                xiaohui

問題就這樣解決了,當然,實際情況可能比這個要負責,我們只需在這個基礎上新增其他部分即可, 如在儲存拆分好的name值時還要儲存其他age等欄位,我們就修改儲存過程裡的insert table2中的結構就可以了,在這裡記錄下這個問題,方便以後有需要時查詢使用,嘿嘿