2012-07-17 71 views
2

我有一個像瞭解基本的SQL查詢

SELECT tran_number 
    FROM table_a WHERE customer_id IN 
      (SELECT customer_id 
      FROM table_b 
      WHERE customer_key = 89564 
        AND ( other_phn_area_code 
         || other_phnum_pfx_num 
         || other_phnum_sfx_num IN 
          (123456789))) 
     AND phn_area_code || phnum_pfx_num || phnum_sfx_num IN (123456789) 

上面的代碼工作正常查詢。值得關注的是與內部查詢(複製下面單獨內部查詢)...

(SELECT customer_id 
       FROM table_b 
       WHERE customer_key = 89564 
         AND ( other_phn_area_code 
          || other_phnum_pfx_num 
          || other_phnum_sfx_num IN 
           (123456789))) 

當我執行此查詢時,我得到錯誤的customer_id: invalid identifier。實際上,table_b沒有任何名爲customer_id的字段。如果是這樣,那麼它是如何工作的,沒有任何問題,當我用它作爲上面的內部查詢。

請幫我理解這一點。

下面

Oracle 11G Enterprise edition 11.2.0.2.0 
PL/SQL Release 11.2.0.2.0 
+0

你是什麼意思的「上面的代碼工作正常。」 - 它返回給你一些輸出,但是你真正想用這個查詢來實現什麼?你試圖從customer_id滿足的行中獲得tran_number - 什麼? – 2012-07-17 08:19:18

回答

3

它的範圍的問題。 Oracle驗證從最內層子查詢開始並向外工作的標識符。如果加上表的別名到您的原始查詢的事情可能會變得更加清晰:

SELECT t1.tran_number 
    FROM table_a t1 
    WHERE t1.customer_id IN 
      (SELECT t1.customer_id 
      FROM table_b t2 
      WHERE t2.customer_key = 89564 
        AND ( t2.other_phn_area_code 
         || t2.other_phnum_pfx_num 
         || t2.other_phnum_sfx_num IN 
          (123456789))) 
     AND t1.phn_area_code || t1.phnum_pfx_num || t1.phnum_sfx_num IN (123456789) 

實際上,外部查詢使用子QUERTY作爲測試EXISTS,即只檢查給定值的存在CUSTOMER_KEY和其他列。如果這不是你想要的,那麼你應該改變子查詢中的列名。 (這是一個相當不錯的選擇:你可能從主查詢中得到令人費解的結果,這就是爲什麼你要單獨調查子查詢)。

在這些情況下使用別名始終是一種好的做法。如果你有這樣的子查詢的別名:

.... 
    WHERE t1.customer_id IN 
      (SELECT t2.customer_id 
      FROM table_b t2 
      WHERE t2.customer_key = 89564 
.... 

該錯誤將立即明顯。


SQL Reference沒有解釋子查詢中作用域的操作,但很難找到。什麼it says是這樣的:

您可以找到「甲骨文通過查看 子查詢,然後在 父語句中指定的表指定的表可解決子查詢不合格列」在PL/SQL文檔中更清晰地解釋範圍; SQL子查詢以相同的方式工作。 Find out more

7

數據庫細節如果該內選擇的where條件具有結果,然後從table_acustomer_id將被選擇。 如果不是那麼它不會被選中。外部選擇檢查與in條件。這就像是說:「如果內部選擇返回true,則只返回一些內容。」

0

這是一個已知的與IN錯誤。如果使用表的別名,你會得到錯誤

SELECT tran_number 
    FROM table_a WHERE customer_id IN 
      (SELECT b.customer_id 
      FROM table_b b 
      WHERE customer_key = 89564 
        AND ( other_phn_area_code 
         || other_phnum_pfx_num 
         || other_phnum_sfx_num IN 
          (123456789))) 
     AND phn_area_code || phnum_pfx_num || phnum_sfx_num IN (123456789) 

還可以使用EXISTS來避免這種類型的沉默行爲

SELECT tran_number 
    FROM table_a as t1 WHERE EXISTS 
      (SELECT * 
      FROM table_b as b 
      WHERE customer_key = 89564 
        AND ( other_phn_area_code 
         || other_phnum_pfx_num 
         || other_phnum_sfx_num IN 
          (123456789)) 
     AND b.customer_id =t1.customer_id) 
     AND phn_area_code || phnum_pfx_num || phnum_sfx_num IN (123456789) 
+4

我認爲將範圍規則的正確操作描述爲「bug」並不正確。更合適的是,如果我們不注意,範圍允許我們引入自己的錯誤。 – APC 2012-07-17 13:41:15