2014-10-10 102 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

相關問題