zoukankan      html  css  js  c++  java
  • 这些年你需要注意的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
    
  • 相关阅读:
    HDU 5585 Numbers
    HDU 3308 LCIS
    POJ 2991 Crane
    POJ 1436 Horizontally Visible Segments
    POJ 3667 Hotel
    HaiHongOJ 1003 God Wang
    【SDOI 2008】 递归数列
    5月19日省中提高组题解
    【HDU 1588】 Gauss Fibonacci
    【POJ 3233】Matrix Power Series
  • 原文地址:https://www.cnblogs.com/humin/p/4098961.html
Copyright © 2011-2022 走看看