• (2.3)DDL增强功能-流程化控制与动态sql


     关键词:动态SQL

    1.流程控制

    在T-SQL中,与流程控制语句相关的关键字有8个:

    BEGIN...END

    BREAK

    GOTO

    CONTINUE

    IF...ELSE

    WHILE

    RETURN

    WAITFOR

    其实还可以加一个,那就是GO,下面我们一个一个来解释说明意思吧

      (1)GO:批处理提交语句,相当于把GO之前的所有东西都提交给系统了(平常看好像不用它也没事,但是在sqlcmd登录后dos界面使用批处理就一定要用),该销毁的销毁该回收的回收等等,演示如图

        

      GO后面还可以加数字,会重复执行。如图:

        

      (2)BEGIN ... END

        这个其实就是逻辑块,类似于各大语言的{}

      (3)while/break/continue

       

         
     while (表达式) --如果表达式成立则运行begin end中的statement语句,否则略过     begin       statement;     end


        break:直接跳出循环
        continue:本次循环后续代码不执行了,直接开始下一次循环
        太简单,就不演示了

      (4)IF ... ELSE

        IF (表达式) --如果表达式成立就执行BEGIN END中间的statement句子;
        BEGIN
                  statement;
        END    
        ELSE  --如果IF中的表达式不成立则跳到ELSE中来,执行statement1;
        BEGIN
                  statement1;
        END    
    
        --注意:如果不写BEGIN END那么默认只有一条语句属于IF/ELSE

      (5)goto

        goto是个捣乱的家伙,可以随意跳到任意一个定义点,基本没什么用,一般用来跳到错误

        


    --实现循环功能的goto 跳转
    基本用法:
    定义点名称:
    goto 定义点名称
    案例:
      declare
    @n int   set @n=1   print_point:print @n   IF (@n < 3)   begin   set @n=@n+1   goto print_point   end   print 'the @n alread > 3'

      结果如图:

        

      (6)return

          迅速结束任何一个批处理(batch),并且return后面的语句不会再执行了,演示如下

        ,发现print 5也没有执行为什么呢。记住了,批处理是以GO为结束

       (7)waitfor  

            延迟与定点

         (7.1)waitfor delay time  延迟 time(默认为秒)后继续顺序执行

            (7.2)waitfor time  time  定点到time的时候再顺序执行

          演示如下

      print 1
      waitfor delay '00:00:05' --注意时间格式的写法
      print 2

      print 1
      waitfor time '16:02:05'  --注意时间格式的写法
      print 2

     

    2.动态SQL(其他类型必须转换成字符类型才能使用动态sql

      (1)变量定义

        declare @n int

        分析:declare: 为关键字;  @n:@为变量标识,n变量名 ;int为变量类型;

        set @n = 1 ; select @n=1

        分析:set为赋值关键字,用select 也可以赋值

        使用的话,直接用@n即可

      (2)执行动态sql

        (2.1)execute,可以简写为exec

            基本形式:exec sp   或 exec(字符串),演示如下

            

      动态sql的基本演示   

            declare @sql varchar(1000),@t int
            declare @n int
                set @n=2
                set @t=10
                set @sql = 'select '+cast(@n as varchar)+' where 10 =     '+cast(@t as varchar)  --注意,这里其他类型必须转换成字符类型才能使用动态sql
            execute(@sql)--可以简写为exec

      代码结果如下

          

      execute的连接到另一个服务器操作

        

      这就表示在链接服务器上做操作了。

      (2.2)sp_executesql 其实是一个存储过程

        要用exec去执行它,常用形式为: exec sp_executesql  @sql ,但@sql比较为UniCode形式,演示如下

        (不知道什么是Unicode的请看https://www.cnblogs.com/gered/p/9117522.html 中第5点中的字符串类型,常量字符串在前面加个N即可,如图)

          

        sp_executesql  可以在动态SQL中做参数输入输出操作

        【1】输入

    declare @sql nvarchar(1000),@num int
    set @sql = N'select @num=1'
    exec sp_executesql @sql,N'@num int output',@num output   --必须要在这里还要定义一次
    print @num

    结果:1

        【2】输入输出结合

    declare @sql nvarchar(1000),@num int
    set @sql = N'select @num=1 where @num2 = 10'
    exec sp_executesql @sql,N'@num int output,@num2 int',@num output,@num2=10   --如果多个参数,一一对应即可
    print @num

    结果:1


    declare @sql nvarchar(1000);
    declare @num1 int;
    declare @v_id int = 2 ;
    declare @table_name nvarchar(100)=N'test..test4';
    set @sql = N'select @num=id from '+@table_name+N' where id=@id ';
    print @v_id
    exec sp_executesql @sql,N'@num int output,@id int ',@num1 output,@id=@v_id--必须要在这里还要定义一次;
    print @sql
    print @num1

     

    结果:

    2
    select @num=id from test..test4 where id=@id
    2

     

        

    判断execute与sp_executesql的好坏与区别

      行为相同:使用的语句或批处理在执行时才编译,编译后的内容作为执行计划运行

      不同行为:execute必须要把所有东西转成字符串,sp_executesql可以入参出参。

      注意事项:

        (1)数据类型转换问题,在execute中必须转换成字符型,在sp_executesql中必须使用UniCode格式

        (2)字符串边界问题:其实也就是单引号'  问题

      举个例子,比如正常情况下

    declare @str char(6)
    set @str = 'a'
    select 1 where @str = 'a'

      换成动态sql的时候

    declare @str char(6),@sql varchar(1000)
    set @str = 'a'
    set @sql = 'select 1 where '''+@str+'''=''a'''
    exec(@sql)
    --单引号在使用其本身的时候要转移,即 ''表示为'


    再举个日期的例子,直接用要报错
      

    正确代码如下:

      

     --想执行的语句 select 1 where getdate() > '20180601'
      declare @str datetime,@sql varchar(1000)
      set @str = '20180601'
     --动态sql语句
      set @sql = 'select 1 where getdate() > '''+@str+''''
      exec(@sql)

    
    

       (3)表变量表字段问题

    --想要查询test101表中的所有内容
    declare
    @table_name char(30) set @table_name = 'test101' select * from @table_name

    这样报错
    --想要查询test101表中的所有内容

      declare @table_name Nchar(30)
      set @table_name = N'test101'
      exec sp_executesql N'select * from @table_name',N'@table_name char(30)',@table_name

      这样也报错

        

      正确的打开方式如下:

        

      declare @table_name Nchar(30),@sql nvarchar(100)
      set @table_name = N'test101'
      set @sql = 'select * from '+@table_name
      exec (@sql)

       

     

       (4) 不能再动态sql中用exec 给变量赋值,可以用sp_executesql来赋值

      

  • 相关阅读:
    JVM执行子系统探究——类文件结构初窥
    解决nexus3报Cannot open local storage 'component' with mode=rw的异常问题
    基础架构之spring cloud基础架构
    基础架构之持续发布
    基础架构之持续集成
    基础架构之Gitlab Runner
    基础架构之GitLab
    基础架构之Docker私有库
    基础架构之Maven私有库
    基础架构之Mongo
  • 原文地址:https://www.cnblogs.com/gered/p/9122898.html
Copyright © 2020-2023  润新知