SQL 2005中的Common Table Expression(CTE)(註1)是很酷的新功能,比Temporay Table輕便(不用Create Table),又比Derived Table(註2)更耐用(建好後可以反覆使用),更不用說它還支援遞迴式參考的花式用法。

想當初在Beta版時代我寫過文章介紹SQL 2005的新功能,裡面紮紮實實地用範例介紹了CTE,沒想到今天發生可怕的鬼打牆,花了半小時連最簡單的CTE都建不出來。

由於打算寫一個很複雜的CTE,於是我照著語法範例先把宣告CTE的部分寫出來,其餘的部分想稍後再做:

WITH myCTE AS
(
SELECT * FROM MyList WHERE colA='123'
)

你猜怎麼著? SQL回了我一句,Msg 102, Level 15, State 1, Line 4 接近 ')' 之處的語法不正確。(英文原文為 Incorrect syntax near ')')

不會吧,CTE的宣告與範例上完全相符,WITH cte_name AS ( select blah )的寫法連白痴都不會寫錯。仔細檢查SELECT中有沒有拼錯字、全型半型弄錯,單獨拉出來跑一切正常,加入CTE後就是會嚷嚷著刮號附近的語法有問題。

於是我執著在"語法不正確"這件事上,檢查又檢查,換了台SQL 2005也是一樣,Google了半天找不到類似的案例回報,很快的,半個小時過去了... 畢竟身為資深茶包射手還是有異於常人的敏銳度,經驗告訴我,這一定是傳說中的

鬼打牆~牆~牆~~~~~

鬼打牆時有個特色,當事人會被困在正常人可輕鬆通過的地區,死命繞圈,無法脫困。遇到這種狀況,自己是走不出來的,最好由別人帶! 所以我馬上停止自己嘗試,MSN Call了幾個高手朋友,告訴他們我遇到鬼打牆了,請他們幫我看一下簡單到不行的語法哪邊出了問題。MVP朋友Bruce輕輕鬆鬆地指出來,我只要加個SELECT * FROM myCTE問題就解決了。

我想起很久前聽過的一個鬼故事,以前辛亥隧道是有衛兵站哨的,有一個深夜,執勤的衛兵看到隧道裡有台計程車停在原地不走。上前查看,隔著車窗看到司機慌張地看著前方,汗如雨下,一邊擦汗,還不斷看著手表,但車子似乎打到空檔。經驗老道的衛兵脫下小帽,用國徽的那一面用力拍了計程車的行李箱,頓時車子就飛也似地衝了出去... 剛才檢查了一下,我的電腦機殼上是有個國徽的印子。XD

【結論】

說是鬼打牆,其實應是SQL的錯誤訊息給得太模糊(底下如果隨便加個SELECT GETDATE(),錯誤會變成"Msg 422 定義了一般資料表運算式,但是未使用。"就正確多了),自己仗著以前有研究過,也沒規規矩地先Copy完整案例來試,就依自己的想法寫將起來,怪不得人。但這種當局者迷的經驗相信大家都有,像我這樣當機立斷,馬上停損請別人幫忙看(問題多簡單也不要怕丟臉,哈),已有好幾次成功克服盲點的記錄,推薦給大家參考。

註1: 可參考http://www.microsoft.com/taiwan/msdn/library/2004/Sep-2004/sql_ovyukondev.htm 關於"常見的資料表運算式"(真是爛到家的中文翻譯,SQL 2005後來自己翻成"一般資料表運算式")的說明
註2: 就是SELECT * FROM (SELECT * FROM T WHER A='1') AS X的這種寫法


Comments

Be the first to post a comment

Post a comment