• 几个很好用SQL语法(SqlServer)


    1,MERGE INTO 语句:

    这个语法仅需要一次全表扫描就完成了全部工作,执行效率要高于INSERT+UPDATE,作用还是很强大的(简单的说就是它可以批量更新和插入处理一个数据集,如果存在就更新指定列,不存在就插入)

    /****** MERGE INTO 语句运用实例 ******/
    -- =============================================
    -- Author:        <Author,yuanchen,Name>
    -- Create date: <Create Date,,>
    -- Description:    <Description,将数据批量新增或更新到[dbo].[Table]中,ID为主键自增>
    -- =============================================
    Create PROCEDURE [dbo].[AddOrUpdateTable]
        @Roles UDT_Table READONLY,--用户自定义表类型(相当于一个传入的临时表)
        @ReturnValue INT OUTPUT  --返回值
    AS
    BEGIN
        SET NOCOUNT ON;
        BEGIN TRY
        BEGIN TRANSACTION
            MERGE INTO [dbo].[Table] AS TARGET --此处[dbo].[Table]是需要插入或更新数据的表
            USING (SELECT * FROM @UDT_Table) AS SOURCE
                ON TARGET.ID = SOURCE.ID --根据此处的列作为条件判断是新增还是更新(多个列作为条件用and连接)
            WHEN MATCHED
            THEN UPDATE 
            SET 
                TARGET.[A]=SOURCE.[B],
                TARGET.[B]=SOURCE.[B],
                TARGET.[UpdateTime]=getdate() --内置函数获取当前时间
            WHEN NOT MATCHED 
            THEN INSERT 
                ([A],[B],[CreateTime])
                VALUES(SOURCE.[A],SOURCE.[B],getdate());  
            SET @ReturnValue = 1 
        COMMIT TRAN
        END TRY
        BEGIN CATCH
          IF XACT_STATE() <> 0
            BEGIN
              ROLLBACK TRANSACTION;
              --此处可以用Error_message()函数记录日志,千万不要在ROLLBACK TRANSACTION前面记录日志,会被回滚
              SET @ReturnValue = -1
            END;
        END CATCH  
    END

    2,WITH XXX AS  语句:

    WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到。有的时候,是为了让SQL语句的可读性更高些,也有可能是在UNION ALL的不同部分,作为提供数据的部分。 
    特别对于UNION ALL比较有用。因为UNION ALL的每个部分可能相同,但是如果每个部分都去执行一遍的话,则成本太高,所以可以使用WITH AS短语,则只要执行一遍即可。如果WITH AS短语所定义的表名被调用两次以上,则优化器会自动将WITH AS短语所获取的数据放入一个TEMP表里,如果只是被调用一次,则不会。而提示materialize则是强制将WITH AS短语里的数据放入一个全局临时表里。很多查询通过这种方法都可以提高速度。(更高效,可读性更好,复杂的子查询推荐使用)

    With [Table1] As(
        select * from [A] inner join [B] on [A].ID=B.[A_ID] --A表和B表连表查询
    ),[Table2] As(
        select * from [C] inner join [Table1] T on [C].ID=T.[C_ID] --C表和A,B表的查询结果连表查询
    )Select * From [Table2]
     
     --上面的查询结果等同于下面这段Sql
     select * from [C] inner join (select * from [A] inner join [B] on [A].ID=B.[A_ID]) T on [C].ID=T.[C_ID]

    3,游标的常规使用,游标可以遍历数据集对每条数据的指定列做处理,处理数据的能力也是相当强大的,但是滥用和使用不当可能对造成性能问题哦,而且处理复杂的多表多条数据时一般都要配合事务一起使用,不然一旦程序错误就会产生错误数据

    /****** 游标的使用实例  ******/
    -- =============================================
    -- Author:        <Author,yuanchen>
    -- Create date: <Create Date,>
    -- Description:    <Description,>
    -- =============================================
    Create Proc [dbo].[Proc_CURSOR_USE] 
    AS
    BEGIN
        SET NOCOUNT ON;
    
        DECLARE @ID BIGINT    --定义变量
        DECLARE @A BIGINT    
        DECLARE @B NVARCHAR(100) 
    
        Select * INTO #Table From [Table] --将查询结果放入临时表
        --定义游标
        DECLARE CURSOR_JOB01 CURSOR FOR
            Select [ID],[A],[B] From #Table --此处可以不用临时表,直接写查询语句,但在实际的业务处理中我们需要的查询结果可能是通过复杂的查询语句得到的,直接写在此处,可读性较差
           OPEN CURSOR_JOB01
           FETCH CURSOR_JOB01 INTO @ID,@A,@B
           BEGIN TRY
             BEGIN TRANSACTION    
             WHILE (@@FETCH_STATUS=0)
             BEGIN
                --此处可以编写逻辑代码,即对游标遍历的当前数据做处理,例如:如果当前数据列A>0,那么就向[BaseLog]表记录一条日志
                IF(@A>0)
                Begin
                     Insert into BaseLog([CONTENT],[CreateTime],[Pro_Name]) values('ID为:'+CONVERT(varchar(10),@ID)++'的A列的值大于0',getdate(),'[Proc_CURSOR_USE]'); --记录错误日志
                End
                FETCH CURSOR_JOB01 INTO @ID,@A,@B
              END
              CLOSE CURSOR_JOB01
              DEALLOCATE CURSOR_JOB01       
            COMMIT
            END TRY
            BEGIN CATCH
            IF XACT_STATE() <> 0
            BEGIN
              ROLLBACK TRANSACTION;
              Insert into BaseLog([CONTENT],[CreateTime],[Pro_Name]) values(Error_message(),getdate(),'[Proc_CURSOR_USE]'); --记录错误日志
              IF CURSOR_STATUS('local','CURSOR_JOB01') <> -3
              BEGIN       
                 IF CURSOR_STATUS('local','CURSOR_JOB01') <> -1
                 BEGIN
                    CLOSE CURSOR_JOB01
                    DEALLOCATE CURSOR_JOB01
                 END
              END
          END;
       END CATCH    
        DROP TABLE #Table --清除临时表
    END
  • 相关阅读:
    java中Switch的实现原理浅谈
    漫谈计算机编码:从ASCII码到UTF8
    从斐波那契数列看java方法的调用过程
    Java中的位运算及简单的算法应用介绍
    在powserdesigner中,如何将Name(中文注释)导入到sqlserver的字段说明中?
    关于ArcMap的符号库和字体
    ORACLE CHAR,VARCHAR,VARCHAR2,NVARCHAR类型的区别与使用
    在window 2008 上安装arcgisserver93,报arcgissom 密码不符合安全策略
    Power Designer反向数据库时遇到sqlstate=37000错误,解决方案!
    解决PowerDesigner 反向工程没有注释且如何将注释转换成PDM的name
  • 原文地址:https://www.cnblogs.com/ruanraun/p/9174532.html
Copyright © 2020-2023  润新知