摘自 <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的定义返回有序的数据集,这个假设是不成立的. 从执行计划上是能够看出来的