iT邦幫忙

1

mysql 的 text 欄位,要如何去除空白列?

  • 分享至 

  • xImage

我有個欄位【resume】(履歷),是 text 型態,


2011.01.01 依2011薪資調整表作業薪調

2016.03.01 考績B調薪1級→2階95級$1,104,年功俸$27



2016.05.01 勞保局調整勞保薪資最高級距$43900↑$45800
2017.01.01 勞健退保費調整,因基本工資由20,008調升至21,009
                及勞保費率由9%調升至9.5%
2019.07.01 物價調薪$500 → 2階99級,日給額$1120,年功俸$47
2021.01.01 物價調薪→2階104級,日給額$1140,年功俸$47。	2021.03.01 考績B,調薪2階105級,日給額$1144,年功俸$47。
2021.10.01 依行文100110-044年度基本薪資調整,→2階110級,
               日給額$1164,年功俸$47。			   
			   

我想要去除其中的所有的空白列(包括第一列和最後一列),變成

2011.01.01 依2011薪資調整表作業薪調
2016.03.01 考績B調薪1級→2階95級$1,104,年功俸$27
2016.05.01 勞保局調整勞保薪資最高級距$43900↑$45800
2017.01.01 勞健退保費調整,因基本工資由20,008調升至21,009
                及勞保費率由9%調升至9.5%
2019.07.01 物價調薪$500 → 2階99級,日給額$1120,年功俸$47
2021.01.01 物價調薪→2階104級,日給額$1140,年功俸$47。	2021.03.01 考績B,調薪2階105級,日給額$1144,年功俸$47。
2021.10.01 依行文100110-044年度基本薪資調整,→2階110級,
               日給額$1164,年功俸$47。

不知要用什麼函數?

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
㊣浩瀚星空㊣
iT邦大神 1 級 ‧ 2023-01-04 18:18:16
最佳解答

映像中沒有這對應的程式。
早期用的方法給你參考。

使用 replace做三次取代。

第一次先將換行符號改成不太會重覆的字串。一般我會用先取代為{:BR:}
第二次取代,是將「{:BR:}{:BR:}」有兩次的,取代成「{:BR:}」
最後再將{:BR:}再取代回換行符。

看更多先前的回應...收起先前的回應...
ckp6250 iT邦好手 1 級 ‧ 2023-01-04 21:55:49 檢舉

感恩戴德,真是百折千迴呀。
依照您的指點,我完成如下程式碼,其中有二個重點,
只有三次 replace有可能不夠,
1.因為使用者可能連續空白了二、三列或更多。
2.只有三次的話,最後還是會多出一列空白,無法達成【去除全部空白列】的要求。

CREATE DEFINER=`marco`@`%` FUNCTION `func_remove_empty_row`(`cStr` text) RETURNS text 
    NO SQL
    COMMENT '去除空白列'
BEGIN
	DECLARE counter INT DEFAULT 1;
	if CHAR_LENGTH(cStr)>0 then 
		set cStr = concat(replace(cStr,char(13),char(10)),char(10));
		set cStr = replace(cStr,char(10),'{:BR:}');
		REPEAT
			set cStr =  replace(cStr,'{:BR:}{:BR:}','{:BR:}');
			SET counter = counter + 1;
		UNTIL counter >= 5
		END REPEAT;
		set cStr = left(cStr,CHAR_LENGTH(cStr)-6);
		set cStr = replace(cStr,'{:BR:}',char(10));
	end if;
	RETURN cStr;
END

實在很麻煩,不知能否更精簡?

其實這比較無解。一般我都是輸出後用PHP處理。
原因是在PHP上可以用正則取代。會比較容易處理。

但MYSQL並不存在正則取代的方式。所以要寫的落落長的函式應用。
真要處理的話。就只能將第二次的取代,RUN個5~10次吧。(其實5次就可以RUN掉很多行的空白行了。真害怕還有更多就10次。
反正它取代的最後結果一定只會剩下一個。

至於最後的空白。嗯~~~這我倒是比較無解。

其實還有另外一招是字串切分法。切完後再回圈組合回來。
是空白的就跳過不組合
這招可能會比較容易。只是程式碼得寫的更長就是了。
反正寫成函式因該也沒差就是了。

有點懶的寫。其實早期在處理特殊的東西有寫過。
但後期都比較偏向在PHP內處理了。所以已經很少在SQL上下程式運算處理了。

ckp6250 iT邦好手 1 級 ‧ 2023-01-05 05:45:13 檢舉

㊣浩瀚星空㊣

至於最後的空白。嗯~~~這我倒是比較無解。

就是為了這點,只好再加上

set cStr = left(cStr,CHAR_LENGTH(cStr)-6);

以去掉最後一列。
真是麻煩耶。

不過,經殺豬大提點,mysql 也有 REGEXP_REPLACE 函數可用,我再試看看可行否。

剛查了一下。MYSQL8確實有支援 REGEXP_REPLACE 了。
這樣或許就簡單多了。我晚上回家試一下看看。
因為我早期使用是沒這函式可用。

========= 接續 =======
剛看到 一級屠豬士 有給了相關正則的應用。
大同小異,我這邊就不提供了。

ckp6250 iT邦好手 1 級 ‧ 2023-01-05 11:27:45 檢舉

㊣浩瀚星空㊣

剛看到 一級屠豬士 有給了相關正則的應用。
大同小異,我這邊就不提供了。

我實際上用 mariadb 10.x , 它的 REGEXP_REPLACE 參數沒有這麼多,我變不出來。

主要前三個參數就好了,後面可以不需要。
這段給你使用

regexp_replace(regexp_replace(tx,'^\n{1,}',''), '\n{2,}', '\n')

基本說明一下。

先將前置的換行給取代移除。
然後再將「2個以上」的換行,取代成1個。

去試試吧。剛我是有試成功就是了。用正則超簡單的。

ckp6250 iT邦好手 1 級 ‧ 2023-01-05 15:31:21 檢舉

㊣浩瀚星空㊣

十分感激,我的正則功力太差了,有好東西也不太會用。
借花獻佛,您的程式略微修補一下,否則最後一列的空白列不會去掉。

regexp_replace(regexp_replace(regexp_replace(tx,'^\n{1,}',''), '\n{2,}', '\n'),'$\n{1,}','')
0
一級屠豬士
iT邦大師 1 級 ‧ 2023-01-04 21:21:58

我使用 trim() 搭配 length()

測試如下:
Demo

看更多先前的回應...收起先前的回應...
ckp6250 iT邦好手 1 級 ‧ 2023-01-04 21:47:55 檢舉

報告殺豬大,
不是空白格,是空白列,它的值是 char(10);
您的 demo 要改成這樣才對,

insert into t230104a(vc,tx) values
('測試資料' , '2011.01.01 依2011薪資調整表作業薪調'),
('一個空白列', char(10)),
('三個空白列', concat(char(10),char(10),char(10))),
('五個空白列', concat(char(10),char(10),char(10),char(10),char(10))),
('頭尾空白', ' 2014.08.01 勞保局調整勞保保費 ');

如此一來,您的程式碼就嘸效啦。

你應該說明的清楚一點,而不是要我去猜你的"列".
現在知道了,等一下.用PG 就好了啊.
Demo

PG 有 MySQL-FDW,可以對應MySQL的table,然後修改的.
PG也可以搭Python, 我知道你又要說,這不是你要的.
已經晚了,剩下的明天繼續.

ckp6250 iT邦好手 1 級 ‧ 2023-01-05 05:16:55 檢舉

冤枉啊,大人!

有說是{我有個欄位【resume】(履歷),是 text 型態,}
我想要去除其中的所有的【空白列】,不知要用什麼函數?

我有再修補我的問題了,是text欄位內的空白列,不是空白格。
語焉不詳,是我的錯,歹勢。

不過,經您提點,mysql 也有 REGEXP_REPLACE 函數可用耶,我再試看看可行否。

同場加映, PG的方式,比較曲折一點.
同場加映PG

ckp6250 iT邦好手 1 級 ‧ 2023-01-05 11:21:28 檢舉

一級屠豬士
看到 mysql 8.0 的

regexp_replace(tx, '^\n*', '', 1, 0, 'm')

我要哭出來了啦,太神奇了啦。

我用的是 mariadb ,參考 ㊣浩瀚星空㊣
改成下列方式,可以成功。

regexp_replace(regexp_replace(regexp_replace(tx,'^\n{1,}',''), '\n{2,}', '\n'),'$\n{1,}','')

連用3次 regexp_replace , 不知還有沒有更精簡的方式?

0
rogeryao
iT邦超人 8 級 ‧ 2023-01-04 22:30:14

借用一級屠豬士的 Code :

create table t230104a (
  id int not null auto_increment primary key
, vc varchar(20)
, tx text
);

insert into t230104a(vc,tx) values
('測試資料' , '2011.01.01 依2011薪資調整表作業薪調'),
('一個空白', ' '),
('三個空白', '   '),
('五個空白', concat(char(10),'     ',char(10))),
('一個空白列', char(10)),
('三個空白列', concat(char(10),char(10),char(10))),
('五個空白列', concat(char(10),char(10),char(10),char(10),char(10))),
('頭尾空白', ' 2014.08.01 勞保局調整勞保保費 ');
delete from t230104a 
where id in (
    select id from t230104a 
      where length(replace(replace(tx,' ',''),char(10),'')) = 0
)
update t230104a
set tx = trim(tx);

Demo

你們是不是誤會版大的問題了。
他的內容是在一筆資料內的TEXT欄位。
不是多筆資料一行一個。

真多筆資料的話。直接正則處理就好了
才不需要那麼麻煩

ckp6250 iT邦好手 1 級 ‧ 2023-01-05 05:38:59 檢舉

rogeryao

我有再修補我的問題了,是text欄位內的空白列,不是空白格。
語焉不詳,是我的錯,歹勢。

我要發表回答

立即登入回答