• 这些年你需要注意的SQL


    [20141114]这些年你需要注意的SQL

    #1、使用对象时,请显式的指定对象的架构者(默认为dbo)

    分析:在SQL SERVER中,如果用户User1访问表table1,那么查询分析器必须决定是检索 User1.table1 还是 dbo.table1 。所以每次User1访问同一张表table1时,查询分析器都必须对查询计划 重编译,影响执行速度。

    #2、尽量避免使用SELECT *,建议使用 SELECT

    分析:采用SELECT * 语法会导致DB对列进行一个遍历,同时可能会查询多余字段数据(本着用啥查啥的原则,建议使用SELECT <Field List>),导致查询性能下降。

    #3、如果一个T-SQL语句涉及到多个表,则引用的每个列必须制定该列所属的对象

    分析:避免造成数据查询异常

    #4、Insert语句中必须指定插入列的列表

    分析:避免表列变化导致插入语句失败

    #5、在非事物和特别要求完整性的上下文中,使用NOLOCK查询

    分析:考虑到并发性,提高查询效率

    示例:

    SELECT TOP 100 COL1,COL2 FROM TABLE1 t1 WITH (NOLOCK)
    

    #6、通过SELECT语句对变量赋值时,如果未使用聚合函数,请加上TOP 1

    分析:防止结果非预期

    示例:(预期结果为2,因为第二次Name2是后添加的。)

    CREATE TABLE test6
    ( 
         Id int 
        ,Name nvarchar(32) 
    )
    
    INSERT INTO test6   (Id, Name)
    SELECT     1, N'Name1'
    UNION all
    SELECT     2, N'Name2' 
    
    INSERT INTO test6   (Id, Name)
    SELECT     3, N'Name2'
    
    --错误的写法
    DECLARE @Id int
    SELECT 
        @Id=Id 
    FROM test6 
    WHERE 
        Name = 'Name2'
    
    --正确的写法
    DECLARE @Id int
    SELECT TOP 1
        @Id=Id 
    FROM test6 
    WHERE 
        Name = 'Name2' 
    

    #7、对于排序后取字段TOP 1的值,建议使用聚合

    分析:可以用上索引,而且不需要Table Scan

    示例:

    --错误的写法
    SELECT TOP 1 col1 FROM table1 ORDER BY col1 DESC
    
    --正确的写法
    SELECT MAX(col1) FROM table1
    

    #8、有关char和varchar,char和nchar,varchar和nvarchar的区别

    分析:

    1. char是固定长度,如果数据不够,会在存储时自动补空格
    2. varchar是可变长度,会有三个字节来存储字段信息,可以设置最大长度
    3. nchar和varchar这种以N开头的表示存储unicode编码字符
    4. 在特定字符集下,如果定义数据格式为char或者是varchar,那么存储特殊字符(包括中文)会乱码
    5. 关于数据库函数LEN(),是用于返回指定字符串表达式的字符数,其中不包含尾随空格。
    6. 关于DATALENGTH函数,返回用于表示任何表达式的字节数。

    示例:

    DECLARE @s1 CHAR(5)
           ,@s2 VARCHAR(5)
           ,@s3 NCHAR(5)
           ,@s4 NVARCHAR(5)
    
    --看看这个结果是什么?
    SET @s1 = 'test'
    SET @s2 = 'test'
    SET @s3 = 'test'
    SET @s4 = 'test'
    SELECT 
        LEN(@s1)
       ,LEN(@s2)
       ,LEN(@s3)
       ,Len(@s4)
    SELECT 
        DATALENGTH(@s1)
       ,DATALENGTH(@s2)
       ,DATALENGTH(@s3)
       ,DATALENGTH(@s4)
    
    --如果这样呢?
    SET @s1 = '我是中文'
    SET @s2 = '我是中文'
    SET @s3 = '我是中文'
    SET @s4 = '我是中文'
    SELECT 
        LEN(@s1) 
       ,LEN(@s2) 
       ,LEN(@s3) 
       ,Len(@s4)
    SELECT 
        DATALENGTH(@s1)
       ,DATALENGTH(@s2)
       ,DATALENGTH(@s3)
       ,DATALENGTH(@s4)
    
    --一般情况下,SELECT @s1,@s2,@s3,@s4不会显示乱码,是由于安装SQL SERVER的时候后默认字符集是支持unicode字符的。如果遇到不支持的字符集,就需要显示定义字段类型为带N的类型,同时在赋值的时候使用N'中文'这种形式。
    

    #9、禁止在使用了事物的情况下,不编写防止造成未提交或者未回滚事务的情况的处理代码

    分析:数据库阻塞,你懂的...罪过大大的!

    #10、警惕表变量的使用

    示例:

    --思考下结果是什么?
    IF NOT exists (SELECT 1)
    BEGIN
        PRINT 'enter'
        DECLARE @table TABLE 
        ( 
             name nvarchar(32) 
        )
    END
    SELECT name FROM @table
    

    分析:

    1. 在表变量的使用中,会出现如JavaScript一样的定义前置,相当于不管你在哪个条件(也不关心是否能走到这个分支)中定义表变量,那么这个表变量在整个作用域中都是有效的。
    2. 临时表表现正常
    3. 表变量和一般的变量有点不一样的地方,表变量也会在tempdb中创建表。示例如下:

    CREATE TABLE #TempTable (TT_Col1 INT)
    DECLARE @TableVariable TABLE (TV_Col1 INT)
    
    SELECT TOP 2 * 
    FROM tempdb.sys.tables
    ORDER BY create_date DESC 
    

    #11、判断是否存在(或者不存在)符合条件的记录使用 EXISTS 关键字。

    分析:

    IF (SELECT COUNT(*) FROM Table WITH (NOLOCK))>0
    BEGIN
        --Do something
    END
    --应该用:
    IF EXISTS(SELECT TOP 1 1 FROM Table WITH (NOLOCK)
    BEGIN
        --Do something
    END  
    

    #12、字符串比较时,SQL SERVER会忽略末尾的空格。

    示例:

    SELECT 1 
    WHERE 't' ='t        '
    

    #13、注意NULL的特殊性

    分析:

    1.NULL既不能被=匹配,也不能被<>(!=)匹配,只能用IS NULL 或者是 ISNULL()

    示例:

    CREATE TABLE #tb(col1 int)
    INSERT INTO #tb(col1)
    SELECT NULL 
    UNION 
    SELECT 1    
    UNION
    SELECT 2
    
    SELECT COUNT(*) FROM #tb 
    WHERE col1 <> 1 OR col1 = 1 --2
    
    SELECT COUNT(*) FROM #tb --3
    

    14、COUNT(0),COUNT(*),COUNT(column)的区别

    分析:

    1. COUNT(0),COUNT(*)计数时会包含NULL值
    2. COUNT(column)计数时,如果需要该列为NULL,则会忽略计数

    示例:

    CREATE TABLE #tb(col1 int)
    INSERT INTO #tb(col1)
    SELECT NULL 
    UNION 
    SELECT 1    
    UNION
    SELECT 2
    
    SELECT COUNT(*) FROM #tb --3
    SELECT COUNT(0) FROM #tb --3
    SELECT COUNT(col1) FROM #tb --2
    

    #15、通过合理的方法避免在 SELECT 语句中使用 DISTINCT

    分析:

    1. DISTINCT 是数据查询中一个非常慢的操作,所以尽可能的避免

    示例:

    SELECT DISTINCT
            A.au_fname
            ,A.au_lname
    FROM dbo.authors AS A WITH (NOLOCK) 
        INNER JOIN dbo.titleAuthor AS T WITH (NOLOCK)  --一对多的关系
    ON T.au_id = A.au_id
    
    --避免DISTINCT的写法
    SELECT au_fname
            ,au_lname
    FROM dbo.authors AS A WITH (NOLOCK) 
    WHERE EXISTS (
                    SELECT TOP 1 1
                    FROM dbo.titleAuthor AS T WITH (NOLOCK)
                    WHERE T.au_id = A.au_id
    
  • 相关阅读:
    bzoj 2456 mode
    codeforces 630 I(规律&&组合)
    codeforces 630H (组合数学)
    codeforces 651A Joysticks
    codeforces 651B Beautiful Paintings
    codeforces 625C K-special Tables
    codeforces 630F Selection of Personnel(组合数)
    codeforce 630N Forecast
    后缀数组模板
    Hdu5737-Differencia(有序表线段树)
  • 原文地址:https://www.cnblogs.com/humin/p/4098961.html
Copyright © 2020-2023  润新知