星期五, 7月 29, 2011

[SQL] CURSOR

SQL Server DML 語法(SELECT、UPDATE 和 DELETE)是以資料集為資料處理單位,方便且有效率,而 Cursor 則是以記錄為資料處理單位,對於資料操作彈性較大。

SQL Cursor 的基礎架構
DECLARE curTemp CURSOR Local Fast_Forward -- 宣告 Cursor 及其資料來源
  FOR
      (
        SELECT Col1,Col2,Col3......
        FROM SourceTable
        WHERE Condition
      )
 
OPEN curTemp -- 打開 Cursor,並建立 Cursor 與資料表關連
 
DECLARE @var1 as .....
DECLARE @var2 as .....
 
FETCH NEXT FROM curTemp INTO @var1,@var2 -- 將資料存進變數中
  WHILE (@@FETCH_STATUS = 0) -- 檢查是否有讀取到資料
    BEGIN  
  
        .................... 
 
        FETCH NEXT FROM curTemp INTO @var1,@var2  
    END
 
CLOSE curTemp -- 關閉 Cursor,並關閉 Cursor 與資料表連結
DEALLOCATE curTemp -- 將 Cursor 物件移除
    使用 Cursor 會導致 SQLServer 效能不彰,應視為最後手段,但假如使用時請注意下列事項:
    1. 盡量由前往後讀取資料就好 FORWARD_ONLY 和 FETCH NEXT 為預設值,不要使用 SCROLL 和 FETCH PRIOR、FETCH FIRST、FETCH LAST 等語法,個人習慣通常都會設定 FAST_FORWARD 來提高效率。
    2. 不要利用 Cursor 來修改和刪除資料,能明確指定為 READ_ONLY 較好。
    3. 避免在 Cursor 中進行排序

    判斷 Cursor 中的最後一筆資料
     
    利用 @@CURSOR_ROWS 來查詢最近一次 OPEN 的 Cursor 中有多少筆資料。
    DECLARE @Temp Table (EmpNO char(5),EmpName nchar(8))
    INSERt INTO @Temp VALUES ('00001','張三')
    INSERt INTO @Temp VALUES ('00002','李四')
    INSERt INTO @Temp VALUES ('00003','王五')
    
    -- Cursor 的 T-SQL 延伸語法
    DECLARE curTemp CURSOR STATIC -- 宣告此 Cursor 為 STATIC
      FOR
         (
           SELECT EmpNO,EmpName
           FROM @Temp
           WHERE EmpNO IN ('00001','00002')
         )
    
    OPEN curTemp
     
    DECLARE @EmpNO as char(5),@EmpName nchar(8)
    DECLARE @Count as smallint 
    
    SET @Count = 0 -- 設定一個計數變數
    
    FETCH NEXT FROM curTemp INTO @EmpNO,@EmpName
      WHILE (@@FETCH_STATUS = 0)
        BEGIN  
          SET @Count = @Count + 1
     
          IF @Count = @@CURSOR_ROWS
              PRINT '最後一筆資料為 ' + @EmpName
       
          FETCH NEXT FROM curTemp INTO @EmpNO,@EmpName
        END
     
    CLOSE curTemp
    DEALLOCATE curTemp
    
      說明:
    1. 由於動態資料指標會反映所有變更,因此,Cursor 內資料列數會不斷改變,@@CURSOR_ROWS 永遠不可能明確指出 Cursor 內有多少資料列數,也因此必須把 Cursor 設為靜態指標(STATIC)。
    2. 宣告 Cursor 為 STATIC,會先把資料放進 TempDB 內,應盡量縮小資料量,以免 TempDB 瞬間爆增,影響效能。
    • 2013 DBA 天團試題

    星期五, 7月 22, 2011

    [SQL] 數學運算-除法

    當一個運算子(EX:加減乘除四則運算)結合兩個不同資料類型的運算式(EX:被乘法乘法、被除數除數)時,資料類型優先順序的規則,會指定將低優先順序的資料類型,轉換為高優先順序的資料類型。如果轉換不是支援的隱含轉換,就會傳回錯誤。如果這兩個運算元運算式的資料類型相同,則作業結果就含有該資料類型。

    除法 Dividend / Divisor

    製作報表時,常常需要用百分比表示,因此會利用到除法來進行計算,使用除法有兩件注意事項
      分母不得為零
    當 T-SQL 語法中分母為零會出現 發現除以零錯誤 的錯誤訊息。
    SELECT 1.0 / 0 -- 模擬除以零錯誤
    
      NULLIF() 說明:
    • 語法:NULLIF ( express1 , express2 )
    • 傳回類型:當 express1 等於 express2 時,會傳回 NULL;當 express1 不等於 express2 時,傳回 express1 值。
    利用 NULLIF() 函數來處理分母,把分母為零轉換成 NULL ,搭配 NULL 本身的特性(任何數值除以 NULL 結果為 NULL ),就可以避免錯誤發生,而 NULLIF() 其實也算是 CASE WHEN 的應用之一。
    SELECT 
          1.0 / NULLIF(T.[分母], 0) AS [利用 NULLIF], 
          1.0 / CASE WHEN T.[分母] = 0 THEN NULL ELSE T.[分母] END AS [利用 CASE WHEN 1],
          CASE WHEN T.[分母] = 0 THEN NULL ELSE 1.0 / T.[分母] END AS [利用 CASE WHEN 2],
          CASE WHEN T.[分母] = 0 THEN 0 ELSE 1.0 / T.[分母] END AS [利用 CASE WHEN 3],
          CASE WHEN T.[分母] = 0 THEN '分母為0' ELSE '分母不為0' END AS [文字敘述]
    FROM 
          (
              SELECT 0 AS [分母]
              UNION ALL
              SELECT 3
          ) T
    
    除零錯誤

    星期五, 7月 15, 2011

    iGoogle 還原功能

    我都利用 iGoogle 的便利貼來記錄些重要或待辦事項,某天進入 iGoogle 時,嚇了一跳,我的便利貼竟然不見了,即使我把便利貼再加回來,便利貼的內容也都歸零了,當下一整個臉都綠了 ~~

    • 在 Google 搜尋頁面的右上角可以看到列圖示,請點擊 設定 => iGoogle 設定。
    iGoogle 還原功能 - 1
    • iGoogle 設定 => 一般 Tab 下方有個 疑難排解 / 回復 功能,請選擇下拉式選單,選擇要回復的時間點,再點擊立刻回復,我的便利貼內容就回來啦,感動 ~~
    iGoogle 還原功能 - 2