我有一個包含像'code1 code2 code3'這樣的代碼的字串。如果輸入的所有代碼都包含在字串中,它應該回傳字串。
例如:
select * from (
select 'avs cde jkl' code from dual)
where REGEXP_LIKE(code, 'REGEX-MAGIC')
當正則運算式現在類似于^(?=.*\bjkl\b)(?=.*\bavs\b).*$then 它應該回傳代碼。但是這種語法不適用于 oracle 中的正則運算式。
邏輯是“如果查找的所有代碼都在字串中(順序無關緊要),則回傳代碼。”
我已經研究過,這可以通過積極的前瞻性來實作,但據我所知,oracle 不支持這一點。我會搜索一個正則運算式,而不是像REGEXP_LIKE(...,..) and REGEXP_LIKE(...,..) and ....
Oracle 版本是 12c。
任何幫助,將不勝感激!
uj5u.com熱心網友回復:
Oracle 不支持正則運算式中的前瞻、后瞻或字邊界。
如果您有示例資料:
CREATE TABLE table_name (code) AS
SELECT 'avs cde jkl' FROM DUAL UNION ALL
SELECT 'avs cde' FROM DUAL UNION ALL
SELECT 'jkl avs' FROM DUAL UNION ALL
SELECT 'cde jkl' FROM DUAL;
選項1:
LIKE最簡單的查詢是不使用正則運算式并使用多個條件查找子字串匹配:
SELECT code
FROM table_name
WHERE ' ' || code || ' ' LIKE '% avs %'
AND ' ' || code || ' ' LIKE '% jkl %'
哪個輸出:
代碼 avs cde jkl jkl avs
選項 2:
REGEXP_LIKE您可以使用(較慢)具有多個條件的正則運算式:
SELECT code
FROM table_name
WHERE REGEXP_LIKE(code, '(^| )avs( |$)')
AND REGEXP_LIKE(code, '(^| )jkl( |$)')
其輸出與上述相同。
選項 3:
您可以將匹配項放入子查詢因式分解子句中,然后使用LATERAL連接:
WITH match_conditions (match) AS (
SELECT 'avs' FROM DUAL UNION ALL
SELECT 'jkl' FROM DUAL
)
SELECT code
FROM table_name t
CROSS JOIN LATERAL (
SELECT 1
FROM match_conditions
WHERE ' ' || code || ' ' LIKE '% ' || match || ' %'
HAVING COUNT(*) = (SELECT COUNT(*) FROM match_conditions)
)
其輸出與上述相同。
選項 4:
如果您真的想要一個正則運算式,那么您可以生成代碼的每個排列以匹配并將它們連接成一個正則運算式:
SELECT code
FROM table_name
WHERE REGEXP_LIKE(
code,
'(^| )avs( | .*? )jkl( |$)' -- Permutation 1
|| '|(^| )jkl( | .*? )avs( |$)' -- Permutation 2
)
其輸出與上述相同。
但是,隨著要匹配的代碼數量的增加,這將變得難以維護,因為 2 個專案有 2 個排列,但 5 個專案有 5 個!= 120 個排列。
選項 5:
您可以宣告一個嵌套表集合:
CREATE TYPE string_list AS TABLE OF VARCHAR2(20);
然后拆分字串(同樣,您不需要慢正則運算式),然后將其與嵌套表進行比較:
WITH bounds (rid, code, spos, epos) AS (
SELECT ROWID, code, 1, INSTR(code, ' ', 1)
FROM table_name
UNION ALL
SELECT rid, code, epos 1, INSTR(code, ' ', epos 1)
FROM bounds
WHERE epos > 0
)
SEARCH DEPTH FIRST BY code SET order_rn
SELECT MAX(code) AS code
FROM bounds
GROUP BY rid
HAVING string_list('avs', 'jkl') SUBMULTISET OF CAST(
COLLECT(
CAST(
CASE epos
WHEN 0
THEN SUBSTR(code, spos)
ELSE SUBSTR(code, spos, epos - spos)
END
AS VARCHAR2(20)
)
)
AS string_list
);
根據您使用的客戶端應用程式,您可以將整個string_list('avs', 'jkl')集合作為單個系結變數傳入,您可以從陣列中填充該變數。使用 ODBC 驅動程式的 Java(以及一些基于 Java 構建的語言)可以做到這一點;C# 不能直接傳遞,但您可以傳遞關聯陣列并使用輔助函式將其轉換為嵌套表集合。
其輸出與上述相同。
db<>在這里擺弄
uj5u.com熱心網友回復:
我不擅長regex-magix,但是 - 看看這樣的事情是否有幫助。
這是一個包含這些代碼的表:
SQL> select * from codes;
ID CODE
---------- -----------
1 avs cde jkl
2 xyz avs
詢問
- 將每個代碼分成行(
t_splitCTE) - 對輸入的引數 (par_string) 值 (
p_splitCTE)執行相同操作 - 為什么?這樣它們就可以像表中的行一樣運行,并且您可以應用
MINUS集合運算子 - 如果沒有
MINUS回傳任何內容,則匹配;否則就是不匹配
SQL> with
2 -- split code to rows
3 t_split as
4 (select id,
5 code original_code,
6 regexp_substr(code, '[^ ] ', 1, column_value) code
7 from codes cross join
8 table(cast(multiset(select level from dual
9 connect by level <= regexp_count(code, ' ') 1
10 ) as sys.odcinumberlist))
11 where id = &&par_id
12 ),
13 -- split parameter to rows
14 p_split as
15 (select regexp_substr('&&par_string', '[^ ] ', 1, level) code
16 from dual
17 connect by level <= regexp_count('&&par_string', ' ') 1
18 )
19 --
20 -- if all parameter's "pieces" of code are contained in CODE value, MINUS returns nothing
21 -- so there's a match
22 select distinct t.original_code,
23 '&&par_string' par_string,
24 case when (select count(*)
25 from (select code from t_split
26 minus
27 select code from p_split
28 )
29 ) = 0 then 'Match'
30 else 'Mismatch'
31 end result
32 from t_split t
33 where t.id = &&par_id;
Enter value for par_id: 1
Enter value for par_string: jkl avs cde
ORIGINAL_CO PAR_STRING RESULT
----------- ----------- --------
avs cde jkl jkl avs cde Match
SQL> undefine par_string
SQL> /
Enter value for par_string: avs jkl www
ORIGINAL_CO PAR_STRING RESULT
----------- ----------- --------
avs cde jkl avs jkl www Mismatch
SQL>
根據您使用的工具(這是 SQL*Plus),您可能需要&&用冒號替換:;或者,將這樣一段代碼轉換為函式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/445150.html
