2012-02-10 51 views
2

我經常使用的遊標這樣:在PL/SQL中使用「select *」作爲不正確編程的遊標?

for rec in (select * from MY_TABLE where MY_COND = ITION) loop 
    if rec.FIELD1 = 'something' then 
     do_something(); 
    end if; 

    if rec.FIELD2 <> 'somethingelse' then 
     blabla(); 
    end if; 
end loop; 

我的領隊告訴我,不要用select *,因爲它是不好的編程,但我不明白爲什麼(在這方面)。

+7

你問過你的團隊負責人,爲什麼他認爲不好的編程,因爲只是說「這是不好的編程」無需提供一個原因是糟糕的球隊領先,恕我直言... – beny23 2012-02-10 09:53:36

回答

9

在你的代碼中使用select *就是我所說的惰性編程,帶有幾個令人討厭的副作用。你有多少經歷這些副作用,會有所不同,但它從來沒有積極的。

,我會使用一些在其他的答案已經提到了點,但隨時編輯我的答案,並添加有關使用select *一些負分。

  1. 您正在從SQL引擎向您的代碼發送更多數據,而不是必要的,這會對性能產生負面影響。

  2. 你得到的信息需要被放置在變量(例如一個記錄變量)。這將需要更多的PGA內存。

  3. 通過使用select *您將永遠不會單獨使用索引來檢索想要的信息,您還需要始終訪問該表(如果沒有索引存在,其中包含表的所有列)。再次,對績效有負面影響。

  4. 不太清楚的人保持你的代碼你的意圖是什麼。他們需要深入到代碼中看到您記錄變量的所有實例知道正在檢索什麼。

  5. 你不會使用SQL函數進行計算,但總是依靠PL/SQL或Java計算。您可能錯過了一些偉大的SQL改進,例如分析功能,示範條款,遞歸子查詢分解等。

  6. 從Oracle11開始,在列級別上跟蹤依賴性,這意味着當您使用select *時,代碼在數據字典中被標記爲「依賴於該列的所有列」。當其中一列出現問題時,您的程序將失效。所以使用select *意味着你的代碼將被失效的次數超過必要的次數。

再次,隨意添加自己的觀點。

+0

在PL/SQL上下文,爲什麼編譯器無法通過刪除未使用的列優化查詢? – user272735 2012-02-11 07:08:18

+1

@ user272735我想這可能,但在一些高度優化的環境中,它是必不可少的查詢是嚴格控制(到應用程序開發人員只允許使用由DB調人認可的查詢點)添加一個字段訪問將意味着一個不同的查詢被髮送,這在這種情況下是不好的。我想Oracle只是假設你知道你在輸入查詢時正在做什麼。 – 2012-02-12 05:57:09

1

select *將拉你的表中的每一個領域。如果你需要他們,那麼這是可以接受的。但是,通常情況下,您不需要全部,那麼爲什麼還要帶入所有額外的數據呢? 取而代之的是隻選擇你關心的領域。

1

select *構造很可能會導致性能下降,從而帶來更多的信息。此外,代碼很可能會產生維護問題。隨着數據庫的變化,引入所有的領域可能會忽視效應。

EDIT 意料之外用於影響主要由那些科多和Rob麪包車Wijk列出 -

  1. 如果查詢取決於列的順序上;
  2. 對代碼的後續更改不夠清晰
  3. 未使用索引。
  4. 我不知道Rob提到的列級別依賴關係跟蹤,並且記住,如果對列進行更改,它可能會使代碼無效(正在檢索的額外列導致溢出;或者查詢取決於。一個特定列的存在

這些意料之外爲效果是一起提及的維護問題起因

+0

什麼「意料之外的效果」你在想什麼?還有什麼維修問題?你可以說得更詳細點嗎? – Codo 2012-02-10 09:52:11

1

SELECT *是有問題的,如果查詢取決於順序或列數,例如在:

INSERT INTO X (A, B) 
SELECT * FROM T 
WHERE B.NR = 113 

但是這是你的情況,這不是真的有問題。如果真的需要的數據比真實數據多得多,它可以被優化。但在大多數情況下,這沒有什麼區別。

+0

非常OT,但我敢肯定,你的頭像是從壁紙我年前:) – molok 2012-02-10 11:17:32

5

選擇比你需要更多的領域有幾個缺點:

  • 不太清楚 - select c1, c2表示在其列拉一目瞭然,而不需要鑽研的代碼。
  • ...對於負責管理/調整數據庫的人員也不那麼清楚 - 他們可能只能看到日誌中的查詢,而不會強制他們分析生成查詢的代碼。
  • 阻止某些查詢優化 - select c2 from t where c2<=5當您有索引c2時,有機會從索引本身中提取c2值,而無需獲取記錄。 select * ...使這不可能。