Sql 在存储过程中,最好是简单地查询数据,还是构造一个查询然后执行它?为什么?

Sql 在存储过程中,最好是简单地查询数据,还是构造一个查询然后执行它?为什么?,sql,sql-server,stored-procedures,Sql,Sql Server,Stored Procedures,我研究过SQL存储过程,我注意到许多人使用两种不同的方法: 首先,使用select查询,例如 Select * from TableA where colA = 10 order by colA 第二,是通过构造一个查询(即like)来实现同样的功能 Declare @sqlstring varchar(100) Declare @sqlwhereclause varchar(100) Declare @sqlorderby varchar(100) Set @sqlstring = 'Se

我研究过SQL存储过程,我注意到许多人使用两种不同的方法:

首先,使用select查询,例如

Select * from TableA where colA = 10 order by colA
第二,是通过构造一个查询(即like)来实现同样的功能

Declare @sqlstring varchar(100)
Declare @sqlwhereclause varchar(100)
Declare @sqlorderby varchar(100)

Set @sqlstring = 'Select * from TableA '
Set @sqlwhereclause = 'where colA = 10 '
Set @sqlorderby = 'order by colA'

Set @sqlstring = @sqlstring + @sqlwhereclause + @sqlorderby 
exec @sqlstring
现在,我知道两者都很好用。但是,我提到的第二种方法维护起来有点烦人


我想知道哪一个更好?有没有什么具体的原因,一个人会选择一种方法而不是另一种?一种方法比另一种方法有什么好处?

使用第一种方法。这将允许正确缓存查询计划,而不仅仅是使用SQL的方式

除其他问题外,第二个问题容易受到SQL注入攻击

使用动态SQL不会进行编译时检查,因此只有在调用时才会失败(越早知道错误的语法越好)


而且,您自己也注意到,维护负担也更高

第二种方法有一个明显的缺点,就是在编译时没有进行语法检查。但是,它允许动态ORDERBY子句,而第一个不允许。我建议您始终使用第一个示例,除非您有很好的理由使查询成为动态的。而且,正如@Oded已经指出的,如果您选择第二种方法,请务必防止sql注入。

我没有一个全面的答案给您,但我现在可以告诉您,在将存储过程作为ORM中的函数导入时,后一种方法更难使用。由于SQL是动态构造的,因此必须手动创建从存储过程返回的、与模型中的实体没有直接关联的任何类型类


记住这一点,有时您无法避免构造SQL语句,特别是当where子句和连接依赖于传入的参数时。根据我的经验,我发现为执行者创建大型、可变联接/whered语句的存储过程试图做的事情太多了。在这种情况下,我建议您牢记单一责任原则

在存储过程中执行动态SQL会将使用存储过程的价值降低到只保存查询容器。存储过程的最大好处在于,查询执行计划(一个非常昂贵的操作)在第一次执行该过程时被编译并存储在内存中。这意味着该过程的每个后续执行都会绕过查询计划计算,并直接跳到操作的数据检索部分

此外,允许存储过程将可执行查询字符串作为参数也是危险的。任何对过程授予执行权限的人都可能对数据库的其余部分造成严重破坏