Oracle 中, 使用 Instr 函數 替換 OR


簡述

今天在寫 sql時遇到一個情況,表 A中的 ID 是按照 TREE結構存儲的。現在需要和表 B中的 NODE_ID連接,取出 B中 NODE_ID可以和 A中任意一個 level的 NODE_ID連接的信息。但是表 B中的 NODE_ID 具體對應到表 A中哪個 level是未知的。對此,最先想到使用的是 OR運算,但是由於效率太低,速度很慢,后來使用 INSTR代替,查詢速度得到明顯提高。

表結構

表 A -
A_SEQ_ID,
LVL1_NODE_ID,
LVL2_NODE_ID,
LVL3_NODE_ID,
LVL4_NODE_ID,
LVL5_NODE_ID,
LVL6_NODE_ID,
LVL7_NODE_ID,
LVL8_NODE_ID,
LVL9_NODE_ID,
LVL10_NODE_ID

表 B -
B_SEQ_ID,
NODE_ID,
INFO

開始時的 sql

SELECT *
  FROM A, B
WHERE A.LVL1_NODE_ID = B.NODE_ID OR
            A.LVL2_NODE_ID = B.NODE_ID OR
            A.LVL3_NODE_ID = B.NODE_ID OR 
            A.LVL4_NODE_ID = B.NODE_ID OR 
            A.LVL5_NODE_ID = B.NODE_ID OR 
            A.LVL6_NODE_ID = B.NODE_ID OR 
            A.LVL7_NODE_ID = B.NODE_ID OR
            A.LVL8_NODE_ID = B.NODE_ID OR 
            A.LVL9_NODE_ID = B.NODE_ID OR
            A.LVL10_NODE_ID = B.NODE_ID;

 這條 sql雖然可以達到最終的目的,但是由於表 A和表 B的數據量比較大,所以執行起來相當慢。

使用 Instr函數

SELECT *
  FROM A, B
WHERE instr(
                   (','||A.LVL1_NODE_ID||','||A.LVL2_NODE_ID||','||A.LVL3_NODE_ID||
                    ','||A.LVL4_NODE_ID||','||A.LVL5_NODE_ID||','||A.LVL6_NODE_ID||
                    ','||A.LVL7_NODE_ID||','||A.LVL8_NODE_ID||','||A.LVL9_NODE_ID||
                    ','||A.LVL10_NODE_ID), 
                    ','||B.NODE_ID||',') > 0;

比起 OR語句一個字段一個字段的比較,instr函數更加高效。當 instr函數匹配到子串的時候就會返回子串在源字符串中的位置,所以這里用 大於0 即表示在表 A的源字符串中可以找到表 B的 NODE_ID (子串或源字符串為 NULL時返回 NULL)。

注:給每個字段加上逗號(',')的原因是匹配的一種方法,例如源數據是 1,2,3,13. 子串是 23.如果直接拼接的話,源字符串就變成 '12313',用instr('12313', '23') 明顯可以匹配成功,但事實並非如此。所以換成給每個字符兩邊都加上逗號,不僅匹配字符也匹配其兩邊的逗號 - instr(',1,2,3,13,', '23')。

Oracle Instr 函數

 
Description of instr.gif follows
 

其中:
INSTR   接受 characters格式的輸入字符集,返回 characters格式的子串位置,位置索引從 1開始;
INSTRB 使用 bytes 而非 characters;
INSTRC 使用 Unicode complete characters;
INSTR2 使用UCS2 code points;
INSTR4 使用UCS4 code points。

對於源字符串,除了INSTRC, INSTR2, 和 INSTR4 不允許CLOB 和 NCLOB 類型外,其他兩個函數的源字符串接受CHAR, VARCHAR2, NCHAR, NVARCHAR2, CLOB 或 NCLOB等任意數據類型。

instr 語法如下: instr( string1, string2, start_position,nth_appearance )

 
string1
源字符串,要在此字符串中查找。
string2
要在string1中查找的字符串 。
start_position
代表string1 的哪個位置開始查找。此參數可選,如果省略默認為1. 字符串索引從1開始。如果此參數為正,從左到右開始檢索,如果此參數為負,從右到左檢索,返回要查找的字符串在源字符串中的開始索引。
nth_appearance
代表要查找第幾次出現的string2. 此參數可選,如果省略,默認為 1.如果為負數系統會報錯。
 

注意:
  如果String2在String1中沒有找到,instr函數返回0。
  示例:
  SELECT instr('syranmo','s') FROM dual; -- 返回 1
  SELECT instr('syranmo','ra') FROM dual; -- 返回 3
  SELECT instr('syran mo','a',1,2) FROM dual; -- 返回 0

 參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM