Mariadb

當我不知道分隔符是否多次存在時,如何提取子字元串?

  • June 9, 2022

我有一列具有這種模式的字元串<email> - <id>

我想只提取電子郵件地址,但這裡的問題是電子郵件地址也可以包含連字元,所以我不能確定分隔符只會出現一次。

所以基本上我想匹配 .* 直到最後一個連字元並將其提取為電子郵件

我有一列具有這種模式的字元串-

這就是你最大的問題。

您在一個欄位中有**兩位數據,這從根本上是個壞主意。

在決定如何儲存任何數據之前,您應該問的第一個問題是

我將如何訪問這些數據?

你真的應該在兩個單獨的欄位中擁有它,然後這個“提取”問題就會“消失”。

數據庫非常非常擅長查找少量數據並將它們組合在一起。

他們通常在尋找大量數據並將它們分開時非常垃圾。

您可以執行以下操作(下面的所有程式碼都可以在此處的小提琴中找到):

CREATE TABLE test
(
 field VARCHAR (200) NOT NULL
);

填充一些範例數據:

INSERT INTO test VALUES
('<pol@blah.com> - <1345>'),
('<xyz@blah.com> - <1345>'),
('<rubbish> - <abc@blah.com> - <1345>'),
('<more_rubbish> - <zyx1234@blah.com> - <1345>');

然後執行:

SELECT 
 REGEXP_SUBSTR
 (
   field, 
   '[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}') AS email
FROM 
 test;

結果:

email
pol@blah.com
xyz@blah.com
abc@blah.com
zyx1234@blah.com

現在,我用於電子郵件的簡單[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}正則表達式是- 您可以根據需要/要求將其複雜化 - 請參見此處- 連結到的一個正則表達式解決方案有 6,500 個字元,也許是矯枉過正?搜尋將使您在解決方案健壯和適合您之間做出妥協。

請注意,正則表達式很昂貴,並且根據您的表大小和字元串的長度,您的查詢可能會很慢。您可以使用 s 以犧牲一點磁碟空間為代價來減少查詢時間成本,GENERATED COLUMN如下所示:

CREATE TABLE test_bis
(
 field VARCHAR (200) NOT NULL,
 email VARCHAR (200) AS
 (
   REGEXP_SUBSTR
   (
     field, 
     '[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'
   )
 ) PERSISTENT -- HDD cost,  also works with VIRTUAL - CPU cost.
);

做了同樣的INSERT事情 - 見小提琴,結果是:

field                                         email
<pol@blah.com> - <1345>                       pol@blah.com
<xyz@blah.com> - <1345>                       xyz@blah.com
<rubbish> - <abc@blah.com> - <1345>           abc@blah.com
<more_rubbish> - <zyx1234@blah.com> - <1345>  zyx1234@blah.com

您可以索引PERSISTENT欄位以加快搜尋速度:

CREATE INDEX fb_regex_email
ON test_bis (email);

據我所知,MariaDB 還沒有功能(或表達式)索引(例如,參見PostgreSQL )。

如果您不想犧牲 HDD 空間,您可以改為創建GENERATEDVIRTUAL- 以 CPU 週期為代價 - *à vous le choix!*我無法測試索引,因為範例表非常小,以至於 MySQL 無論如何都會進行表掃描,無論索引是否存在。

我只是建議您使用自己的硬體和自己的數據測試這些解決方案,以確保您的性能對於您的要求/約束是最佳的。

引用自:https://dba.stackexchange.com/questions/313122