• SQL Server 要避免的编程坏习惯


    摘自

    使用select *

    • 会返回不需要的列,增加磁盘和网络开销

    • 如果view的定义里用了select *, 而底层的表有列名的变化的时候,view仍然会返回原来的列

    
    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。

    声明变量varchar/nvarchar 不指定长度

    有面向对象编程经验的人可能习惯了使用string类型而不用定义长度,到了SQL里面,这种习惯就会出问题

    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的参数没有定义长度,在传参的过程中就被偷偷截断了

    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

    关于order by的误解

    很多人以为对一个有clustered index的table 进行查询即使不指定order by也会按照clustered index的定义返回有序的数据集,这个假设是不成立的. 从执行计划上是可以看出来的

  • 相关阅读:
    Android学习笔记14:Tween Animation动画的实现
    Android学习笔记17:单项选择RadioButton和多项选择CheckBox的使用
    北国的雪
    Android学习笔记11:图像的平移、旋转及缩放
    三极管基本放大电路解析
    51单片机中data,idata,xdata,pdata的区别
    充电开关制作
    慢慢学Linux驱动开发,第五篇,初探设备模型概念
    慢慢学Linxu驱动开发,第二篇:启程,模块机制,Hello World
    H桥电机驱动原理与应用
  • 原文地址:https://www.cnblogs.com/sqlzh/p/9649033.html
Copyright © 2020-2023  润新知