我們每個人都知道是個不好的做法,但有時我們還是要這樣做:我們執行SELECT * 語句。這個方法有很多弊端:
- 你從你的表里返回每個列,甚至后期加的列。想下如果你的查詢里將來加上了VARCHAR(MAX)會發生什么……
 - 對於指定的查詢,你不能定義覆蓋非聚集索引來克服執行計划里的查找(lookup)運算符,因為你會在額外的索引里重復你的數據……
 
現在的問題是你如何阻止SELECT *語句?當然你可以進行代碼審核,你可以提供最佳模式指導,但誰最終會留意這些?基本上沒有人——很遺憾這就就是令人傷心的事實……
但有一個非常簡單方法來阻止SELECT *語句,在表里用技術層面來解決。
這個問題的解決方法非常簡單:在你的表定義上增加一個產生除零錯誤的的計算列。這個方法超簡單,但卻真正有效。我們來看下面的表定義:
1 -- Create a simple table with a computed column that generates 2 -- a divide by zero exception. 3 CREATE TABLE Foo 4 ( 5 Col1 INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, 6 Col2 CHAR(100) NOT NULL, 7 Col3 CHAR(100) NOT NULL, 8 DevelopersPain AS (1 / 0) 9 ) 10 GO 11 12 -- Insert some test data 13 INSERT INTO Foo VALUES ('a', 'a'), ('b', 'b'), ('c', 'c') 14 GO
如你所見,我這里增加了一個進行除零的計算列。這表示當是查詢這個列時,你會得到一個錯誤信息——例如在SELECT * 語句里:
1 -- A SELECT * statement doesn't work anymore, ouch... 2 SELECT * FROM Foo 3 GO

但另一方面如果你通過名稱指定查詢列,你不會反悔計算列,你的查詢如願正常執行:
1 -- This SQL statement works 2 SELECT Col1, Col2, Col3 FROM Foo 3 GO

很不錯吧,是不是?
小結
在各個交流會上我經常提到:有時我們只是變得太復雜了!這個用計算列的方法非常簡單——肯定需要表架構修改。但下次設計新表的時候,要記得用這個方法。
感謝關注!
參考文章:
www.sqlpassion.at/archive/2015/10/26/how-to-prevent-select-statements/
