2012-06-26 48 views
0

我在表中包含以波浪號分隔的數據的列。在Oracle中使用包含波浪號分隔數據的列

我想觸發一個單一的sql查詢(出於性能原因),它應該返回表中所有記錄,其中此代字號中至少有一個記號分隔數據不在預定義的有效值列表中。

我已經在各種論壇尋找解決方案,他們中的大多數人說有一個用戶定義的拆分功能來拆分記錄或使用一些正則表達式,但這不適用於單個查詢。

有人可以幫我嗎?

回答

3

您可以使用正則表達式來解析單個SQL語句中的數據。然後,您可以將您想要的任何過濾器來找到一組不在預定值列表

SQL> ed 
Wrote file afiedt.buf 

    1 with test as 
    2 (select 'ABC~DEF~GHI~JKL~MNO' str from dual) 
    3 select regexp_substr (str, '[^~]+', 1, rownum) split 
    4 from test 
    5* connect by level <= length (regexp_replace (str, '[^~]+')) + 1 
SQL>/

SPLIT 
---------------------------------------------------------------------------- 
ABC 
DEF 
GHI 
JKL 
MNO 

你也可以做這樣的事情

SQL> ed 
Wrote file afiedt.buf 

    1 with test as 
    2 (select 1 id, 'ABC~DEF~GHI~JKL~MNO' str from dual union all 
    3  select 2, 'XY~PDQ~435' from dual union all 
    4  select 3, 'This~is~a~test' from dual) 
    5 select id, regexp_substr (str, '[^~]+', 1, e.lvl) split 
    6 from test, 
    7   (select level lvl 
    8   from dual 
    9   connect by level <= (select max(regexp_count(str,'~')) + 1 
10        from test)) e 
11* where regexp_substr (str, '[^~]+', 1, e.lvl) is not null 
SQL>/

     ID SPLIT 
---------- -------------------- 
     1 ABC 
     2 XY 
     3 This 
     1 DEF 
     2 PDQ 
     3 is 
     1 GHI 
     2 435 
     3 a 
     1 JKL 
     3 test 
     1 MNO 

12 rows selected. 

當然,這不會特別高效 - 你將不得不對錶進行全面掃描,因爲你無法有效地索引各種子字符串。還有其他方法可以生成這些行--Rob van Wijk的一篇文章比較了各種interval based row generation techniques在他的博客中的表現。

您通常會更好地修復您的數據模型。在列中存儲分隔的數據違反了基本的規範化原則。如果您已將數據存儲在單獨的列中(大概在與現有表格有一對多關係的單獨表格中),則可以對數據建立索引,並且可以創建映射到預定義的有效列表的外鍵約束值,因此您可以防止首先插入無效數據(或至少防止將來添加新的無效行)。

+1

對於「*你通常會修好你的數據模型*」 –

相關問題