Oracle通過一個字段的值將一條記錄拆分爲多條記錄

前言

之前遇到了一次這樣的需求,當時沒有記錄,這一次又趕上了,簡單的記錄一下。

本文個人拙見,若有出入,請指出——來自菜的顫抖該方式的效率不高,如何優化,請看記Oracle中regexp_substr函數的一次調優(速度提高99.5%)

場景

表A中存放了集裝箱的信息,一個集裝箱一條記錄,表B中存放了對於集裝箱操作的指令,一條指令包括多個集裝箱箱號,通過分號;切割(TCIU2347687;XUTR3546865),現在的需求是,對於已經在指令表B中的集裝箱,在查詢表A時需要過濾掉。

  • 很容易想到的是not in, 然而分號分割。
  • 其次,not like,然而[Err] ORA-01427: 單行子查詢返回多個行,表示like後面只接受模糊查詢的單個值。

所以必須將分號分割的記錄,拆分成單獨的記錄。單個記錄變成:切割後

實現

Oracle可使用regexp_substr函數實現,實現上面切割的sql爲:

select regexp_substr('TCIU2347687;XUTR3546865', '[^;] ', 1, level) JZXXH
from dual connect by level <= regexp_count('TCIU2347687;XUTR3546865', ';')   1

其中regexp_substr各個參數的含義:

  • TCIU2347687;XUTR3546865 表示需要分割匹配的串(我這裏只是做了示例,真實情況下是表的字段)。
  • [^;] 典型的正則表達式,我這裏分號切割,因此確定分割規則是多個不是分號的字符,因此遇到分號便結束,完成一個串的獲取。
  • 1開始位置,最左端(Oracle下標都是1開始
  • level表示第幾個匹配上的。
    爲了直觀點搞清楚這個函數,比如下面的語句:
select REGEXP_SUBSTR('aaa;bbb','[^;] ',1,1) AS STR FROM dual; 

結果就是aaa, 如果把第二個1變成2,輸出就是bbb。好了,這部分意圖很明顯了,下面就是把它每一個切割串取出來,看到上面取level個,而這個level是個什麼東西呢,在這個之前,先看regexp_count(string, c)函數,這個函數其實很好理解,返回string中c的個數。然後就是這個level,這是一個僞列,和RowNum相似,

SELECT LEVEL FROM DUAL CONNECT BY LEVEL <=2; 

level所以再回到最初的sql,也就很好理解了。

最後

此致,敬禮

---

歡迎賞臉關注:家佳Talk

歡迎賞臉關注:家佳Talk

本文內容個人拙見,若有出入,歡迎指正!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章