施行动态sql的权位难题,存款和储蓄进程中奉行动态Sql语句

当 sp_executesql 或 EXECUTE
语句实施字符串时,字符串将作为它的自包蕴批处理试行。
SQL Server 会将字符串中的1个或多少个 Transact-SQL
语句编译为独立于批处理(包括 sp_executesql 或 EXECUTE
语句)实行布置的实行安插。

动态SQL能够通过EXECUTE 或SP_EXECUTESQL那两种艺术来试行

<一>存储进程加密

  在近期的项目中,有用到动态施行sql语句,SQL为我们提供了三种动态试行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更有着优势,它提供了输入输出接口,而EXEC没有。还有贰个最大的益处正是利用sp_executesql,能够重用实施布置,那就大大提供了进行质量,仍是可以编写制定更安全的代码。EXEC在某个意况下会越来越灵活。除非你有令人信服的说辞使用EXEC,否侧尽量利用sp_executesql。

跟权限有啥关联?也正是说通过 sp_executesql 或
EXECUTE施行的sql被编写翻译为单身的批处理,并不是当前用户能够直接实施的,依然通过难点来说明呢。

execute:
可进行系统存款和储蓄进程,用户自定义存款和储蓄进程,标量值用户定义函数,扩充存款和储蓄进程
sp_executesql:
施行数次重复使用恐怕动态变化的sql语句也许批处理,sql语句能够分包嵌入参数
在批处理,名称功效域可能数据库上下文中,sp_executesql 和
execute的表现1律,。

实在,用了那十多年的SQL
server,作者一度成了仓库储存进程的忠诚拥趸。在向来动用SQL语句如故存款和储蓄进程来拍卖事务逻辑时,我基本会不暇思索地挑选后者。

1.EXEC的使用

 

前端比后者方便些,比如推行动态sql字符串是varchar类型,不是nvarchar类型,后者只好进行是Unicode的字符串,也许能够隐转换为ntext的常量或变量,execute则两种档次的字符串都能执行

理由如下:

    
EXEC命令有三种用法,一种是实践三个储存进程,另1种是施行2个动态的批处理。以下所讲的都以第两种用法。

创制用户

EXECUTE (N’SELECT * FROM Groups’) –施行成功
EXECUTE (‘SELECT * FROM Groups’) –推行成功

一、使用存款和储蓄进度,至少在防不合法注入(inject)方面提供更加好的掩护。至少,存款和储蓄进程在实践前,首先会施行预编写翻译,(假诺是因为地下参数的由来)编写翻译出错则不会试行,这在某种程度上提供一层天然的遮挡。

  下边先使用EXEC演示一个例子,代码一

平昔上例子,成立二个用户,通过四个用户施行非动态sql的存款和储蓄进程和动态sql的存款和储蓄进程看那中间的权柄难题

SP_EXECUTESQL N’SELECT * FROM Groups’; –实行成功
SP_EXECUTESQL ‘SELECT * FROM Groups’ –实施出错

本人迄今还记得大概捌、玖年前使用的三个权力调整种类便是经过拼凑2个SQL语句,最终得到了3个形如“
where 一=1 and dataID in (一,二) and ModelID in (二,45伍) And ShopID in (11①)
and departID in ( 1,三) and ([Name] like %myword%)
”的where条件子句来获得符合条件的结果集。

997755.com澳门葡京 1997755.com澳门葡京 2

997755.com澳门葡京 3

总计下:EXECUTE
能够试行非Unicode或Unicode类型的字符串常量、变量。而SP_EXECUTESQL只可以进行Unicode或能够隐式转变为ntext的字符串常量、变量。

在意:那一个参数是由此地点栏web应用的地点栏或Winform的UI分界面来输入的,所以对恶意注入须要开销一定的基金来保卫安全。因为有的常用的第二字(或敏感词)很难区分是恶意或非恶意。

1 DECLARE @TableName VARCHAR(50),@Sql NVARCHAR (MAX),@OrderID INT;
2 SET @TableName = 'Orders';
3 SET @OrderID = 10251;
4 SET @sql = 
5      'SELECT * FROM '+QUOTENAME(@TableName) +'WHERE OrderID = '+
6      CAST(@OrderID AS VARCHAR(10))+' ORDER BY ORDERID DESC'
7 EXEC(@sql);

 

EXECUTE
括号内部只可以是字符串变量、字符串常量、或它们的连接组合,不可能调用别的一些函数、存储进度等。
假如要动用,则采取变量组合,

2、使用存款和储蓄进度而不是一贯访问基表,可以提供更加好的安全性。你能够在行级或列级调节数据怎么着被修改。绝对于表的走访,你能够肯定有实施权限许可的用户实践相应的蕴藏进度。那也是造访数据服务器的惟一调用门路。由此,任何偷窥者将不能够看出你的SELECT语句。换句话说,每一个应用只可以具备相应的囤积进度来做客基表,而不是“SLEECT
*”。

View Code

以新创设用户的地位实行非动态sql和动态sql的贮存进程

EXEC SP_EXECUTESQL @Sql, N’@GroupName NVARCHAR’,@GroupName
询问出来未有结果,因为从没注明参数长度。

三、存款和储蓄进程能够加密。(那一点十一分实用,设想一下,您的数据库服务器是托管的或租用的,你是还是不是能心安理得的每一日睡个落到实处觉。如果竞争对手“一相当大心”登上你的SQL
Server,或通过注入获得了您的贮存进程,然后相应的注入恶意的SQL,将你的业务逻辑乱改1通,而刚好您5分钟前又没做备份,那会怎么样?)

注:这里的EXEC括号中只同意包涵2个字符串变量,然而足以串联五个变量,若是我们这么写EXEC:

始建三个非动态sql的蕴藏进程,授权给ReadWriteUser奉行这么些蕴藏进度的权能

动态批处理不能够访问定义在批处理里的部分变量 。 SP_EXECUTESQL
能够有输入输出参数,比EXECUTE灵活。

(注意:加密仓库储存进度前应该备份原始存款和储蓄进度,且加密应该在布局到生产条件前成功。)

  

997755.com澳门葡京 4

 

仓库储存进程的加密相当轻巧,我们看二个例子:

EXEC(‘SELECT TOP(‘+ CAST(@TopCount AS VARCHAR(10)) +’)* FROM ‘+

以ReadWriteUser这么些用户的地方施行存款和储蓄进程TestPrivilege_NoDynamic,没极度

SELECT cacheobjtype, objtype, usecounts, sql
FROM sys.syscacheobjects
WHERE sql NOT LIKE ‘%cache%’
AND sql NOT LIKE ‘%sys.%’;

安插测试表

           QUOTENAME(@TableName) +’ ORDER BY ORDERID DESC’); 

997755.com澳门葡京 5

前者每便试行生成1个奉行安排,然后再进行,后者只生成三次,但会重复使用,所现在者比前者功用高

复制代码 代码如下:
use testDb2
go

      SQL编写翻译器就会报错,编写翻译不经过,而借使大家这么:

 

/**********测试表*****************/
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tb_demo]施行动态sql的权位难题,存款和储蓄进程中奉行动态Sql语句。(
[id] [int] NOT NULL,
[submitdate] [datetime] NULL,
[commment] [nvarchar](200) NULL,
)
GO
SET ANSI_PADDING OFF
GO
Insert into [tb_demo]
select 1024, getdate(),REPLICATE(‘A’,100);
WAITFOR DELAY ’00:00:04′;
Insert into [tb_demo]
select 1024, getdate(),REPLICATE(‘B’,50);
go

  

新创造一个以sp_executesql实施动态sql的贮存进度,同样授权给ReadWriteUser那么些蕴藏进度的执行权限

布署存款和储蓄进度:
复制代码 代码如下:
/***************创设未加密的贮存进度*******************/
Create Procedure CPP_test_Original
AS
select * from [tb_demo]
go
/***************创立加密的囤积进度*******************/
Create Procedure CPP_test_Encryption
with encryption
AS
—-能够换到自由的逻辑
execute CPP_test_Original
go

EXEC(@sql+@sql2+@sql3);

997755.com澳门葡京 6

未加密的蕴藏进度:

编写翻译器就会透过;
 
     
所以最棒的做法是把代码构造到一个变量中,然后再把该变量作为EXEC命令的输入参数,那样就不会受限制了。
 
     
EXEC的瑕疵是不提供接口,那里的接口是指,它不能够实施二个富含贰个带变量符的批处理,如下:

以ReadWriteUser这么些用户的地点施行存款和储蓄进度TestPrivilege_WithDynamic,此时是实践倒闭的,即就是ReadWriteUser具备执TestPrivilege_WithDynamic那个蕴藏进度的权柄

加密的积存进程:

997755.com澳门葡京 7997755.com澳门葡京 8

997755.com澳门葡京 9

这时,至少,存款和储蓄进度的内容不会被任意看出(尽管解密也是有十分的大希望的)。应用这些,大家能够对某个主要的积存进度进展加密。但那时,存款和储蓄进程依然能被execute、alter和drop。

1 DECLARE @TableName VARCHAR(50),@Sql NVARCHAR(MAX),@OrderID INT;
2 SET @TableName = 'Orders';
3 SET @OrderID = 10251;
4 SET @sql = 'SELECT * FROM '+QUOTENAME(@TableName) +
5      'WHERE OrderID = @OrderID ORDER BY ORDERID DESC'
6 EXEC(@sql);

  此时若是给ReadWriteUser授权表上的读的权能:grant select on T一 to
ReadWriteUser,再度实践TestPrivilege_WithDynamic
  然后再实施存款和储蓄进程,是从未难点的

<2>安全上下文

View Code

997755.com澳门葡京 10

除去加密sql文本的始末,大家还足以使用EXECUTE AS
子句设定期存款款和储蓄进度的安全上下文,以满意区别的安全等第须求。

首要就在SET
@sql这一句话中,假诺我们运营那几个批处理,编译器就会爆发一下错误

  

假诺您对那一个不感兴趣,请直接路过痛经划线的段落。

  Msg 137, Level 15, State 2, Line 1 
  必须注明标量变量 “@OrderID”。

  用户就算有进行存款和储蓄进程的权位,因为给User授予了实行存款和储蓄进程的权杖(grant
execute on TestPrivilege_WithDynamic to ReadWriteUser)
  不过固然存款和储蓄进度中有动态sql,就会并发“The
SELECT(或然Insert,Update,Delete)permission was denied on the object
‘***’”
  此时就须求给User授予具体的表上的照应的SELECT(大概Insert,Update,Delete)权限,然后本领健康地实行李包裹蕴动态sql的囤积进程

(关于EXECUTE AS
子句的详尽用法,请参考MSDN:

     
使用EXEC时,即便你想访问变量,必须把变量内容串联到动态营造的代码字符串中,如:

*  *

此间,大家供给领会的是:

SET @sql = ‘SELECT * FROM ‘+QUOTENAME(@TableName) +

  其余一种格局是在蕴藏进度中WITH EXECUTE AS OWNELacrosse,
  WITH EXECUTE AS
OWNE本田UR-V只需给予用户对模块自个儿的权位,而无需给予用户对被引用对象的显式权限。
  也便是说,在蕴藏进度中增添了WITH EXECUTE AS
OWNE福特Explorer,就不用再予以给用户实际对象的权能

1、在 SQL Server
中,能够定义以下用户定义模块的实施上下文:函数(内联表值函数除此而外)、进程、队列和触发器。

   ’WHERE OrderID = ‘+CAST(@OrderID AS VARCHAR(10))+’ ORDER BY ORDERID
DESC’

  也即如下

经过点名推行模块的上下文,能够调控数据库引擎使用哪贰个用户帐户来表明对模块引用的靶子的权杖。这促进人们更灵活、有力地保管用户定义的模块及其所引述对象所形成的靶子链中的权限。必须同时只需给予用户对模块本人的权位,而无需给予用户对被引用对象的显式权限。唯有运维模块的用户必须对模块访问的靶子具有权力。

      串联变量的始末也设有品质方面包车型大巴弊端。SQL
Server为每1个的查询字符串创建新的实施布署,即便查询情势同样也是这么。为示范那一点,先清空缓存中的试行安排

  997755.com澳门葡京 11

针对函数、进程、队列和触发器,对应的参数也不及。存款和储蓄进程对应的参数包蕴(CALLEPAJERO| SELF | OWNERAV四 | ‘user_name’)。

  DBCC FREEPROCCACHE (这几个不是本文所提到的始末,您能够查阅MS的MSDN)

 

■CALLE宝马7系钦定模块内的言语在模块调用方的内外文中施行。施行模块的用户不仅必须对模块自身有所适合的权柄,还要对模块引用的别的数据库对象具有万分权限。
CALLE帕杰罗 是除队列外的有着模块的暗中认可值,与 SQL Server 二零零五 行为等同。
CALLE帕杰罗 不能够在 CREATE QUEUE 或 ALTE兰德LX570 QUEUE 语句中钦点。
■SELF EXECUTE AS SELF 与 EXECUTE AS user_name
等价,在那之中钦赐用户是成立或转移模块的用户。成立或退换模块的用户的莫过于用户
ID 存款和储蓄在 sys.sql_modules 或 sys.service_queues 目录视图的
execute_as_principal_id 列中。SELF 是队列的默许值。
■OWNELacrosse内定模块内的言语在模块的当前主人上下文中推行。即使模块没有点名的主人,则应用模块架构的全部者。不可能为
DDL 或登入触发器钦命 OWNE奥迪Q三。注意:OWNEHummerH二必须映射到独门帐户,不可能是剧中人物或组。
■’user_name’ 钦命模块内的言语在 user_name
钦命的用户的上下文中试行。将依据 user_name
来声明对模块内随机对象的权位。不可能为富有服务器作用域的 DDL
触发器或登6触发器内定 user_name。请改用 login_name。user_name
必须存在于近日数据库中,并且必须是独自帐户。user_name
不可能是组、角色、证书、密钥或内置帐户,如 NT AUTHO大切诺基ITY\LocalService、NT
AUTHORITY\NetworkService 或 NT AUTHORITY\LocalSystem。试行上下文的用户
ID 存款和储蓄在元数据中,能够在 sys.sql_modules 或 sys.assembly_modules
目录视图的 execute_as_principal_id 列查看。

      将代码一运行3次,分别对@OrderID
赋予下边1个值,1025壹,1025二,⑩二伍三。然后利用下边包车型大巴代码查询

二、全部权链具备以下限制:
仅适用于 DML 语句:SELECT、INSERT、UPDATE 和 DELETE。
调用和被调用对象的主人必须1律。
不适用于模块内的动态查询。

SELECT cacheobjtype,objtype,usecounts,sql FROM sys.syscacheobjects WHERE
sql NOT LIKE ‘%cach%’ AND sql NOT LIKE ‘%sys.%’ 

咱俩看一个演示:
率先步、创制三个测试存储进度,用来delete表tb_Demo的具有数据
复制代码 代码如下:
USE testDb2
GO

     
点击F伍运营,我们得以见见,每实行1次都要发生一回的编译,试行陈设未有赢得丰盛重用。

CREATE PROCEDURE dbo.[CPP_DEL_ALL_Tb_997755.com澳门葡京,Demo]
AS
— Deletes all rows prior to the data feed
DELETE dbo.[tb_Demo]
GO

     
EXEC除了不辅助动态批处理中的输入参数外,他也不帮助出口参数。私下认可意况下,EXEC把询问的出口再次来到给调用者。例如上边代码重返Orders表中有所的记录数

其次步:创造多少个账号TonyZhang,并赋于该账号对该存款和储蓄进程的exec权限
复制代码 代码如下:
USE master
GO
CREATE LOGIN TonyZhang WITH PASSWORD = ‘123b3b4’
USE testDb2
GO
CREATE USER TonyZhang
GO
GRANT EXEC ON dbo.[CPP_DEL_ALL_Tb_Demo] to TonyZhang

997755.com澳门葡京 12997755.com澳门葡京 13

以该账号登入SQL Server,并实施:
复制代码 代码如下:
EXECUTE dbo.CPP_DEL_ALL_Tb_Demo/**(4 row(s) affected)**/

1 DECLARE @sql NVARCHAR(MAX)
2 SET @sql = 'SELECT COUNT(ORDERID) FROM Orders';
3 EXEC(@sql);

小心:此时,固然托尼Zhang除了举办存储进程[CPP_DEL_ALL_Tb_Demo]之外未有其它其他权限,但照样试行了蕴藏进程,并剔除了表记录。
万壹我们修改存储进程为:
复制代码 代码如下:
Alter PROCEDURE dbo.[CPP_DEL_ALL_Tb_Demo]
AS
— Deletes all rows prior to the data feed
truncate table dbo.[tb_Demo]
GO

View Code

那时,再以托尼Zhang登陆,并进行存款和储蓄进程,会提醒:

 然则,假如您要把出口再次回到给调用批处理中的变量,事情就未有那么粗略了。为此,你无法不利用INSERT
EXEC语法把出口插入到多个对象表中,然后从这表中收获值后赋给该变量,就好像这么:

那是因为全部者权链只限定在SELECT、INSERT、UPDATE 和
DELETE。而不包罗Truncate,换句话说,系统授于的Exec只既定于SELECT、INSERT、UPDATE
和 DELETE

997755.com澳门葡京 14997755.com澳门葡京 15

有人大概会问:要是在仓库储存进度里面调用动态语句,而不是家喻户晓的表名,大家什么界定权限呢?
其三步:大家建立一个存储进程,成效是流传3个参数表名,查询该表的记录数。
复制代码 代码如下:
CREATE PROCEDURE dbo.[CPP_SEL_CountRowsFromAnyTable]
@SchemaAndTable nvarchar(255)
AS
EXEC (‘SELECT COUNT(1) FROM ‘ + @SchemaAndTable)
GO

1 DECLARE @sql NVARCHAR(MAX),@RecordCount INT
2 SET @sql = 'SELECT COUNT(ORDERID) FROM Orders';
3 CREATE TABLE #T(TID INT);
4 INSERT INTO #T EXEC(@sql);
5 SET @RecordCount = (SELECT TID FROM #T)
6 SELECT @RecordCount
7 DROP TABLE #T2

授于托尼zhang 以进行该存款和储蓄进程的权力:
复制代码 代码如下:
GRANT EXEC ON dbo.[CPP_SEL_CountRowsFromAnyTable] to TonyZhang
go

View Code

那儿,以托尼zhang登陆,实践存储进程,会唤起:

2.sp_executesql的使用

小心,此时,tonyzhang尽管有实践存储进度的权能,可是从未参数表的select权限,所以进行破产。
第六步:修改存款和储蓄进度的上下文
始建1个新账号jackwang,赋于表tb_Demo的select权限
复制代码 代码如下:
USE master
GO
CREATE LOGIN JackWang WITH PASSWORD = ‘123b3b4’
USE Testdb2
GO
CREATE USER JackWang
GRANT SELECT ON OBJECT::dbo.[tb_Demo] TO JackWang
GO

sp_executesql命令在SQL
Server中引进的比EXEC命令晚一些,它首要为重用施行安排提供越来越好的支撑。

/*******
小心:此时,杰克Wang 可以进行dbo.[tb_Demo的Select
*******/

为了和EXEC作2个分明的比较,我们看看若是用代码一的代码,把EXEC换成sp_executesql,看看是否拿走大家所期望的结果

修改存款和储蓄的实践者
复制代码 代码如下:
USE Testdb2
GO

997755.com澳门葡京 16997755.com澳门葡京 17

alter PROCEDURE dbo.[CPP_SEL_CountRowsFromAnyTable]
@SchemaAndTable nvarchar(255)
WITH EXECUTE AS ‘JackWang’
AS
EXEC (‘SELECT COUNT(1) FROM ‘ + @SchemaAndTable)
GO

1 DECLARE @TableName VARCHAR(50),@sql NVARCHAR(MAX),@OrderID INT ,@sql2 NVARCHAR(MAX);
2 SET @TableName = 'Orders ';
3 SET @OrderID = 10251;
4 SET @sql = 'SELECT * FROM '+QUOTENAME(@TableName) + ' WHERE OrderID = '+CAST(@OrderID AS VARCHAR(50)) + ' ORDER BY ORDERID DESC'
5 EXEC sp_executesql @sql

留意:那样,大家再调用存款和储蓄进程[CPP_SEL_CountRowsFromAnyTable]时,会活动以杰克Wang的地位运转该存款和储蓄进程。
那时,大家仍以托尼zhang登录,再实施:

View Code

小结:
正文通过轻巧的七个示范开端SQL server代码的平安之旅,
1、存款和储蓄进程的加密,(注意:加密囤积进度前应该备份原始存款和储蓄进度,且加密应该在配备到生育环境前成功。)
二、存储过程的延安上下文。能够经过上下文设置越发严酷的数量访问等第。(首借使对SELECT、INSERT、UPDATE
和 DELETE语句的造访限制)

留意最终1行;事实评释能够运行;

sp_executesql提供接口

   
sp_executesql命令比EXEC命令更加灵活,因为它提供三个接口,该接口及援救输入参数也支撑出口参数。那效用使你能够创造带参数的询问字符串,那样就足以比EXEC更加好的任用实践布置,sp_executesql的重组与仓储进度卓殊相像,差异之处在于您是动态创设代码。它的结合蕴含:代码快,参数注脚部分,参数赋值部分。说了那般多,依然看看它的语法:

997755.com澳门葡京 18

EXEC sp_executesql

@stmt= <statement>,–类似存储进度主体

@params = <params>, –类似存储进度参数部分,注解参数类型

<params assignment> –类似存款和储蓄进程调用,为参数赋值,参数值要和参数顺序要逐项对应,也得以由此为参数指明参数值的章程为其赋值

@stmt参数是输入的动态批处理,它能够引进输入参数或输出参数,和存款和储蓄进程的重心语句同样,只可是它是动态的,而存款和储蓄进度是静态的,可是你也得以在储存过程中使用sp_executesql;

 @params参数与定义输入/输出参数的存款和储蓄进度头类似,实际上和储存过程头的语法完全平等;

 @<params assignment> 与调用存款和储蓄进度的EXEC部分类似。

     其实@stmt,@params能够轻松,那么exec
sp_executesql的语法就能够简写成如下格式:

997755.com澳门葡京 19

EXEC sp_executesql
<statement>,
<params>,
<params assignment>

997755.com澳门葡京 20

     

   
 为了验证sp_executesql对实践布置的军管优于EXEC,小编将选择前边切磋EXEC时用到的代码。

997755.com澳门葡京 21

997755.com澳门葡京 22代码

DECLARE @TableName VARCHAR(50),@sql NVARCHAR(MAX),@OrderID INT; 
SET @TableName = ‘Orders ‘;
SET @OrderID = 10251; 
SET @sql = ‘SELECT * FROM ‘+@TableName + ‘ WHERE OrderID = @OID ORDER
BY ORDERID DESC’ 
–注意当要对动态sql语句的表名举行参数化时,不得以如下表示:
–set @sql=’select * from @TableName where OrderID=@OID ORDER BY
Orderid desc’,
–假诺那样会提醒必须表明标量变量@TableName,只可以够如上面所写的平等,将表名@TableName作为变量名进行拼接

EXEC sp_executesql 
@sql, 
N’@OID int ‘, 
@OID = @OrderID

997755.com澳门葡京 23

     下边大家看看exec
sp_executesql的实行功效,在调用该代码和反省它生成的实行安顿前,先清空缓存中的试行陈设;

  DBCC FREEPROCCACHE

     将地方的动态代码实践叁遍,每一次实施都给予@OrderID
分歧的值,然后查询sys.syscacheobjects表,并注意它的输出,优化器只开创了3个备用布署,而且该安排被圈定的二回

SELECT cacheobjtype,objtype,usecounts,sql FROM sys.syscacheobjects

  WHERE sql NOT LIKE ‘%cache%’ AND sql NOT LIKE ‘%sys.%’ AND sql NOT
LIKE ‘%sp_executesql%’

     点击F5运行。

    
sq_executesql的另贰个与其接口有关的庞大功效是,你能够选拔输出参数为调用批处理中的变量重回值。利用该功能可以幸免用一时半刻表重返数据,从而获得更便捷的代码和越来越少的重复编写翻译。定义和动用输出参数的语法与存款和储蓄进程看似。约等于说,你须求在宣称参数时钦定OUTPUT子句。例如,上边的静态代码轻松的以身作则了何等从动态批处理中利用输出参数@p把值重回到表面批处理中的变量@i.

997755.com澳门葡京 24

DECLARE @sql AS NVARCHAR(12),@i AS INT;
SET @sql = N’ SET @p = 10′;
EXEC sp_executesql
@sql, 
N’@p AS INT OUTPUT’,
@p = @i OUTPUT
SELECT @i –该代码重临输出10

997755.com澳门葡京 25

  以字母 N 为前缀标志 Unicode 字符串常量

      计算以下几点:   一.使用exce
sp_executesql作用比exec要高,同一品种的言辞,只需编写翻译二回就可以,而exec试行四次就必要编写翻译五次。
  贰.构造动态sql的where子句,也正是标准子句时,exec无法使用变量来进展站位,要求将变量调换到字符串,然后和动态sql实行拼接,那就大概引起Sql注入难题,如下:
    

SET @sql = ‘SELECT * FROM ‘+QUOTENAME(@TableName) +

   ’ WHERE OrderID = ‘+CAST(@OrderID AS VARCHAR(50)) + ‘ ORDER BY
ORDERID DESC’

        而若使用exec
sp_executesql则能够运用变量来拓展站位,未来再给那一个参数字传送值的放式构造动态sql,就制止的Sql注入的标题,如下:

SET @sql = ‘SELECT * FROM ‘+@TableName + ‘ WHERE OrderID = @OID ORDER
BY ORDERID DESC’

  三.无论是Exec还是Exec
sp_executesql,借使想要将表名和列名举办动态参数化,不得以选择表名参数和列名参数来进展站位,而且表名参数和列名参数须求利用存款和储蓄进度的参数.对    
于exec sp_executesql来说,不可能将表名参数和列名参数在钦命为在exec
sp_executesql参数申明部分证明的参数,如:

997755.com澳门葡京 26

997755.com澳门葡京 27代码

create PROCEDURE GetData
@tbName nvarchar(10),
@colName nvarchar(10),
@Name nvarchar(10)
AS
BEGIN
declare @sql nvarchar(50);
set @sql=’select ‘+ @colName+’ from ‘ +@tbName+ ‘ where
name=@whereName’;
–注意此句不能写成如下:
— set @sql=’select @colName from @tbName where name=@whereName’;
exec sp_executesql 
@sql,
N’@whereName nvarchar(10)’,
@Name
END

997755.com澳门葡京 28

 

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website