• 动态执行SQL语句,接收返回值


    一、exec和sp_executesql介绍

           当需要根据外部输入的参数来决定要执行的SQL语句时,常常需要动态来构造SQL查询语句。比如,一个比较通用的分页存储过程,可能需要传入表名,字段,过滤条件,排序等参数,而对于搜索的话,可能要根据搜索条件判断来动态执行SQL语句。

      在SQL Server中有两种方式来执行动态SQL语句,分别是execsp_executesql。sp_executesql相对而言具有更多的优点,它提供了输入输出接口,可以将输入输出变量直接传递到SQL语句中,而exec只能通过拼接的方式来实现。还有一个优点就是sp_executesql,能够重用执行计划,这就大大提高了执行的性能。所以一般情况下建议选择sp_executesql来执行动态SQL语句。

      使用sp_executesql需要注意的一点就是,它后面执行的SQL语句必须是Unicode编码的字符串,所以在声明存储动态SQL语句的变量时必须声明为nvarchar类型,否则在执行的时候会报“过程需要类型为 'ntext/nchar/nvarchar' 的参数 '@statement'”的错误,如果是使用sp_executesql直接执行SQL语句,则必须在前面加上大写字母N,以表明后面的字符串是使用Unicode类型编码的。

            在SQL中,字符串前加N,表示双字节字符,即字符串用Unicode方式存储。对于西文字符,用一个字节来存储过足够了,对于东方文字字符,就需要两个字节来存储。Unicode 为了统一、规范、方便、兼容,就规定西文字符也用两个字节来存储。

    下面看几种不同的动态执行SQL的例子

    --1,普通SQL
    exec ('select GETDATE();');
    exec sp_executesql N'select GETDATE();';--加上N,不用Unicode表示方式会报错

    --2,带参数的SQL语句
    declare @tempsql nvarchar(1024);
    declare @start_date datetime;
    set @start_date = '2018-12-24';
    set @tempsql = 'select DATEDIFF(day, @start_date,GETDATE());';

    exec('select DATEDIFF(day, ''' + @start_date + ''',GETDATE());')
    exec sp_executesql @tempsql, N'@start_date datetime',@start_date;

    --3,有返回值的SQL语句
    declare @tempsql nvarchar(1024);
    declare @temp datetime;
    set @tempsql = N'select @temp = GETDATE();';

    exec sp_executesql @tempsql,N'@temp datetime output',@temp output;
    select @temp

    执行普通SQL时,exec和sp_executesql没有太大差别。

    执行带参数的sql时,exec只能以字符串拼接的方式执行,sp_executesql可以以传参的方式执行,更安全一些

    执行有返回值的sql时,只能使用sp_executesql

     二、存储过程中动态执行SQL,并且获取执行的值

    假如在存储过程中需要动态执行SQL,并且还要把动态执行的结果,比如行数、sum的总数等,赋值给变量,或者赋值到临时表里,那么就可以用exec和sp_executesql结合使用,如下例子


    IF object_id('tempdb..#tempTB') IS NOT NULL
    BEGIN
    DROP TABLE #tempTB
    END

    --创建临时表
    CREATE TABLE #tempTB(
    testTime datetime NULL,
    testTime2 datetime NULL,
    )

    --将查询的数据insert到临时表
    declare @tempSQL nvarchar(1000);
    set @tempSQL = 'insert into #tempTB (testTime,testTime2) select GETDATE(), DATEADD(day, 1,GETDATE());';
    exec(@tempSQL);
    select * from #tempTB;

    --动态查询临时表行数,并赋值到变量
    declare @tempCon int;
    set @tempSQL = N'select @tempCon = count(*) from #tempTB;';
    exec sp_executesql @tempSQL,N'@tempCon int output',@tempCon output;
    select @tempCon;

    DROP TABLE #tempTB

  • 相关阅读:
    关于ORALE将多行数据合并成为一行 报错未找到where关键字
    Input限制输入数字
    Dev Gridcontrol每行添加序号或者文本。
    Android studio SDK配置
    介数中心性快速计算
    Buuoj 被嗅探的流量
    Docker安装(win10)
    filter CTF
    MySQLdb._exceptions.OperationalError: (2026, 'SSL connection error: unknown error number')
    DNS解析原理(www.baidu.com)
  • 原文地址:https://www.cnblogs.com/huyueping/p/10173036.html
Copyright © 2020-2023  润新知