iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 15
1

接下來,我們在文中,繼續介紹幾個進階的SQL語法,以及寫SQL語法時,和效能有關的幾個議題和注意事項。進入主題前,我還是再囉嗦一次,想要學好 SQL

觀念最重要、語法要熟悉、實戰最有效。

首要之務,請務必拋棄迴圈式的程式 coding 邏輯,改以批次(整批)作業的概念來解決問題
使用基礎的SQL 標準語法即可解決絕大多數的問題
善用 Google 的搜尋功能

下面就是本文要說明的較常用且重要 SQL 進階語法

1.CASE WHEN
2.三種暫存表的寫法
3.配合 DB 的 user define function 讓SQL更靈活、更強大
4.迴圈式程式寫法的範例

CASE WHEN

什麼?有沒有搞錯,CASE WHEN 這麼普遍常用的語法,是哪裡進階了?一般而言,我們常用的SQL語法,通常都是使用在 Select 欄位時的判斷

--跟據某欄位值,判斷顯示男/女
Select EmpID,Case When Sex='1' Then '男生' Else '女' END 性別 From Employee;

--跟據某欄位有值否,取得不同的欄位內容
SELECT PERSONID USERID,
CASE WHEN ISNULL(DATAEXTEND5,'') = '' THEN DEPARTMENTID ELSE DATAEXTEND5 END GROUPID
FROM BASPERSON

之所以會寫再進階SQL的原因是在於,連 Where 條件都可以用 CASE WHEN取不同的欄位來判斷,之所以會有這種奇特的需求,是因為某張報表有一個超強的選項,再查詢對帳單時,取得資料的日期區間可以依客戶要求自選來定義(有圖有真相)@DATETYPE 就是畫面上的選項,傳給 Store Procedure 的參數值
https://ithelp.ithome.com.tw/upload/images/20181023/20111421B4TSG3lJpU.png
https://ithelp.ithome.com.tw/upload/images/20181023/20111421RejIt7mb9z.png

如果能很好的掌握 CASE WHEN 很多客戶希奇古怪的需求,彈彈手指間就輕鬆的解決了,這能更大的擴充SQL的能力。在沒有找到這個方式前,我一直都認為只能在前端程式跟據條件組好SQL再執行。但是誠如我一再強調的,要讓SQL能夠自主的解決所有的問題,前端呼叫時,永遠只是傳入參數,所有的需求都要用SQL語法解決,不要依靠前端程式處理,這樣才有辦法將前端UI和後端資料庫獨立,可以隨時切換、重組。如果能做到這樣,才算真正的掌握SQL的精髓。

三種暫存表的寫法

在 MS-SQL 中,有下列幾種暫存檔的寫法,其他資料庫大同而小異。

實體暫存檔(如 ESS_TMP)
WITH GEX01 (XX,XX) AS
DECLARE @ACT_TMP1 TABLE
#TmpDB、##TmpDB

所謂的實體暫存檔,事實上就是一般的資料表,完全一樣。只不過他存的資料內容,通常都是一些暫存的資料,因為要考慮多人同時使用的問題,一般都會有一個 LoginID 及 FuncTag 的欄位來區別呼叫的人員及程式代號。
至於 WITH 及 DECLARE @Table下面我貼一些程式的片段供各位參考。
https://ithelp.ithome.com.tw/upload/images/20181023/20111421hvQMNT0QKA.png

https://ithelp.ithome.com.tw/upload/images/20181023/20111421hkeUmhI0DC.png

https://ithelp.ithome.com.tw/upload/images/20181023/20111421weTQeM4585.png

之所以需要使用暫存表,通常是因為在較複雜的批次運算中,許多的數字無法透過SQL的語法,直接取得,而必須經過2次甚至多次的運算,才能得到所需的數字。像我之前一再舉例的 MRP 展算,就是一個經典的案例。為了要計算 MRP 我們必須根據諸如訂單量及計畫生產量(含維修量),然後依BOM設定多接展開,再計算採購預進量、現有庫存、在途量、產品的採購批量、交期天數等等數字,經過複雜的計算,最終取得原物料的建議採購量。這種複雜的計算,就有必要使用暫存檔來處理。

另外使用暫存檔,還有一個重要的原因,避免資料被鎖死 (deadlock),這個議題就有點大了,我們就不多說,先有個概念即可。上面的幾種暫存檔,各位可以 Google 即可找到相關詳細的說明,在明天的系列文,應該會舉幾個實際的範例說明。

配合 DB 的 user define function 讓SQL更靈活、更強大

昨天的單元,我有列出常用的一些資料庫本身提供的自定義函數。也可以自己利用SQL語法撰寫 udf 自行擴充。寫成 udf 的最大優點就是可以在 SQL 語法中直接使用。例如,如果我們寫了一個 getCost(prodid,costmethod) 的 function,傳入產品編號,成本方式後,會回傳該產品的現有成本。我們可以寫成下面的程式

select prodid,dbo.getCost(prodid,1) from zen_product;

非常的直覺、簡潔有力。

迴圈式程式寫法的範例

--取得要跑回圈的資料,並寫入暫存檔中
select *,row_number() over(order by 1,2) as rowid into #tmp_curr from xxx order by 1,2

declare @maxcount int
declare @currid int
declare @nextrowid int

select @maxcount=count(*) from #tmp_curr
select @currid=min(rowid) from #tmp_curr

while (@currid <= @maxcount)
begin
  --取得本筆資料內容
  select @xx1=xx1,@xx2=xx2,@xx2=xx2 from #tmp_curr where rowid > @currid
  
  --執行真正要處理的程式內容
  xxxxxx
  
  -- 取得下一筆資料
  select @nextrowid = min(rowid) from #tmp_curr where rowid > @currid;

  set @currid=@nextrowid
end

drop table #tmp_curr

今天我們又向著 SQL 高手邁出了重要的一步。要想完全使用 SQL 完成所有的商業邏輯,這些語法的熟悉是重中之重,因限於篇幅無法詳細說明,請各位自行研究,如果有問題,也歡迎提出。明天我會整理一些參考的範例,希望對大家能有所幫助,我們明天見。


上一篇
Day14:常用的 SQL 語法簡介 II
下一篇
Day16:進階的 SQL 語法簡介 II
系列文
以資料庫為開發核心,利用通用 API 玩轉後端資料存取的概念與實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言