摘自 <SQL Server MVP Deep Dives Vol.2>sql
會返回不須要的列,增長磁盤和網絡開銷編程
IF OBJECT_ID('tb1') IS NOT NULL DROP TABLE tb1 GO CREATE table tb1(id int) GO IF OBJECT_ID('v1') IS NOT NULL DROP VIEW v1 GO CREATE view v1 as select * from tb1 GO select * from v1 --改表的定義,增長1列 ALTER TABLE tb1 ADD name sysname; --仍然只返回id列,新加的name沒有返回 select * from v1
解決的方法是使用sys.sp_refreshsqlmodule刷新定義網絡
sys.sp_refreshsqlmodule 'v1' --返回id, name兩列 select * from v1
將view定義爲SCHEMABINDING類型能夠阻止select *的使用,同時也會阻止底層table的schema的改動,若是須要改table的schema,就須要先drop view。函數
有面向對象編程經驗的人可能習慣了使用string類型而不用定義長度,到了SQL裏面,這種習慣就會出問題code
DECLARE @x CHAR = 'foo'; SELECT a = @x, b = CAST('foo' AS CHAR), c = CONVERT(CHAR, 'foo');
結果以下:
a | b | c
--|---|--
f | foo | foo |對象
緣由是全部字符類型若是在聲明變量時若是沒有定義長度,那麼長度就是1.(這是遵循ANSI標準的),把上面代碼的char換成varchar,nvarchar也是同樣的結果。若是你用cast或者convert函數的話,長度是30.排序
若是你建立表的時候字符類型的列沒有指定長度,行爲也是同樣的,只能存1個字符串字符串
CREATE TABLE dbo.x(y VARCHAR); GO INSERT dbo.x(y) SELECT 'foo'; --結果 Msg 8152, Level 16, State 14, Line 2 String or binary data would be truncated. The statement has been terminated.
若是sp的參數沒有定義長度,在傳參的過程當中就被偷偷截斷了string
CREATE TABLE dbo.x(y VARCHAR); GO CREATE PROCEDURE dbo.x_insert @y VARCHAR AS BEGIN SET NOCOUNT ON; SELECT @y; END GO EXEC dbo.x_insert @y = 'foo'; --結果返回'f'
常見的錯誤是不少人喜歡用字符類型來存時間,理由是能保存成想要的格式,不須要作格式轉換就能夠直接讀取到UI上. 這樣與使用日期類型作存儲比較,缺點是面向對象編程
使用>, <, 而不是between
不少人覺得對一個有clustered index的table 進行查詢即便不指定order by也會按照clustered index的定義返回有序的數據集,這個假設是不成立的. 從執行計劃上是能夠看出來的