2014-10-10 48 views
2

我有以下存储过程动态SQL Server存储与表名作为输入参数的过程

CREATE PROCEDURE [dbo].[Insert] 
    @Service varchar(max), 
    @TableName varchar(100), 
    @Query varchar(250), 
    @Results varchar(max), 
    @CreatedDate datetime, 
    @ExpirationDate datetime 
AS 
BEGIN 
    SET NOCOUNT ON; 

    BEGIN TRANSACTION 
     DECLARE @SQL NVARCHAR(MAX), @ParmDefinition NVARCHAR(MAX) 
     DECLARE @q1 VARCHAR(MAX), @rez1 VARCHAR(MAX), 
       @date1 DATETIME, @date2 DATETIME 

     DECLARE @tablename VARCHAR(MAX) = @Service + '.' + @TableName 

     SET @SQL = N'if not EXISTS (select @q from ' + @tablename + ' where Query = @q) insert into ' + @tablename + ' values(@q, @rez, @date1, @date2)' 

     SET @ParmDefinition = N'@q varchar(max), @rez varchar(max), 
           @date1 datetime, @date2 datetime' 

     EXECUTE sp_executeSQL  -- Dynamic T-SQL 
      @SQL, 
      @ParmDefinition, 
      @q = @Query, 
      @rez = @Results, 
      @date1= @CreatedDate, 
      @date2 = @ExpirationDate 

     COMMIT TRANSACTION 
END 

当我试着执行它时,它不会将任何东西,0行

如果我执行没有存储过程的代码,就像它插入的单个查询

我错过了什么吗?

+0

你确定使用'@ TableName'和'@ tablename'作为2个不同的变量有效吗? – jazzytomato 2014-10-10 11:52:02

+0

尝试使用PRINT,看看执行过程中发生了什么。传递参数到执行可能是issue.Please提供一些示例为参数 – Recursive 2014-10-10 11:53:26

+0

修改与另一个变量@dynamictable,仍然没有插入 – user3057678 2014-10-10 11:53:45

回答

3

在你的问题中你做了很多事情,对我没有任何意义,你为什么需要在你的过程中声明所有这些变量。

是的,你正在使用参数化查询来保护自己免受SQL注入攻击,但是你通过连接对象名称(表和数据库名称)留下了一个漏洞,是的,你需要连接它们,但你可以使用QUOTENAME()函数他们传递参数并强制sql server将方括号放在这些参数的周围,并强制sql server将它们视为对象名称。

而在IF EXISTS中选择一个变量没有多大意义。如果找到具有匹配条件的行,选择1返回true,如果找不到行,则只会插入一行。

只声明需要声明的变量,否则这会使它看起来像一团乱麻,难以调试。正如他们所说Keep it simple :)

还可以使用适当的数据类型为您的参数,@Service我相信是你的数据库名称为什么它需要一个VARCHAR(MAX)数据类型,使用特定的存储SQL Server对象的数据类型名称SYSNAME

CREATE PROCEDURE [dbo].[Insert] 
    @Service SYSNAME, 
    @TableName SYSNAME, 
    @Query varchar(250), 
    @Results varchar(max), 
    @CreatedDate datetime, 
    @ExpirationDate datetime 
AS 
BEGIN 
SET NOCOUNT ON; 

BEGIN TRANSACTION 
    DECLARE @SQL NVARCHAR(MAX), @ParmDefinition NVARCHAR(MAX) 

    SET @SQL = N'IF NOT EXISTS (select 1 from ' + QUOTENAME(@Service) + '.' + QUOTENAME(@TableName) 
      + N' where Query = @q) ' 
      + N'insert into ' + QUOTENAME(@Service) + '.' + QUOTENAME(@TableName) 
      + N' values(@q, @rez, @date1, @date2)' 

    SET @ParmDefinition = N'@q varchar(250), @rez varchar(max), 
          @date1 datetime, @date2 datetime' 

    EXECUTE sp_executeSQL @SQL 
         ,@ParmDefinition 
         ,@q = @Query 
         ,@rez = @Results 
         ,@date1= @CreatedDate 
         ,@date2 = @ExpirationDate 

COMMIT TRANSACTION 
END 
+0

效果很好。感谢你的所有帮助,下次我会尽量减少使用这样的变量, – user3057678 2014-10-10 13:15:44

相关问题