需求: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中的結構就可以了,在這裡記錄下這個問題,方便以後有需要時查詢使用,嘿嘿