动态sql填充存储过程变量

时间:2014-02-27 11:41:50

标签: sql sql-server stored-procedures

我想使用存储过程在aTable中添加记录。但在此之前,我需要检查它是否是重复的条目。如果不重复,则仅添加到aTable

我有一个存储过程可以完成两件事

  1. 检查重复
  2. 如果不重复则只添加记录。
  3. 在这个存储过程中,我有

    1. @count变量(范围是存储过程本身)
    2. 列值作为参数(7-8为varchar数据类型)
    3. 我将@count设置为1,然后使用@qry值构建动态@count字符串,其中包含@column值,如下所示

      CREATE PROCEDURE sp_aTable_ADD
         @col1 varchar(20) = null,
         @col2 varchar(20) = null,
         @col3 varchar(20) = null,
         ...
         @colN varchar(20) = null,
      AS
         DECLARE @count int
         SET @count = 1
      
         DECLARE @qry nvarchar(max)
         SET @qry = 'SELECT @count = count(*) FROM aTable WHERE '
      
         IF @col1 IS NOT EMPTY
         BEGIN
             SET @qry = @qry + ' col1 = '+ ''''+@col1+''''
         END
      
         IF @col2 IS NOT EMPTY
         BEGIN
             SET @qry = @qry + ' AND col2 = '+ ''''+@col2+''''
         END
      
         ...
         ...
      
         IF @colN IS NOT EMPTY
         BEGIN
             SET @qry = @qry + ' colN = '+ ''''+@colN+''''
         END
      
         /*once all the stored procedure variables are done processing, close the sql*/
         SET @qry = @qry + ' )'
      
         /*final @qry value would end up looking like as follows
         SELECT @count = count(*) 
         FROM aTable 
         WHERE (col1 = 'val1' AND col2 = 'val2' AND col3 = 'val3')*/
      

      现在,在此存储过程中,我想知道@count的值,如果它是'0',则继续执行'INSERT'过程。我坚持在这个存储过程中获得'@count'值。

      有什么想法吗?

2 个答案:

答案 0 :(得分:0)

为什么要使用动态sql只是用WHERE Clause写一个像这样的查询

CREATE PROCEDURE usp_aTable_ADD  --<-- Use usp
   @col1 varchar(20) = null,
   @col2 varchar(20) = null,
   @col3 varchar(20) = null,
   ...
   @colN varchar(20) = null,
AS
BEGIN
 SET NOCOUNT ON;
DECLARE @Count INT;

SELECT @count = count(*) 
FROM aTable 
WHERE 
     (@col1 IS NULL OR Col1 = @col1)
AND  (@col2 IS NULL OR Col2 = @col2)
AND  (@col3 IS NULL OR Col3 = @col3)
.
.
AND  (@colN IS NULL OR ColN = @colN)

--And then at the end of your Proc just return the @Count Variable 

   RETURN @count;
END

答案 1 :(得分:0)

使用输出参数:

EXECUTE sp_executesql @qry, N'@Count INT OUTPUT', @Count OUTPUT;

进行简单的测试:

DECLARE @count INT;
DECLARE @qry NVARCHAR(MAX) = 'SELECT @Count = 10';
EXECUTE sp_executesql @qry, N'@Count INT OUTPUT', @Count OUTPUT;
SELECT @Count;

最后,您永远不会在WHERE子句中打开括号:

SET @qry = 'SELECT @count = count(*) FROM aTable WHERE '

但你继续关闭它们:

SET @qry = @qry + ' )'

此外,如果所有参数都为null,即使您打开了括号,也会出现错误的语法错误,因为您的SQL将是:

SELECT @count = count(*) FROM aTable WHERE ();

如果@ Col1为NULL,您将获得:

SELECT @count = count(*) FROM aTable WHERE AND col2 = col2();

首先删除括号,可以避免这种情况。 WHERE A = 1表示与WHERE (A = 1)完全相同,并且首先添加无意义的内容:

SET @qry = 'SELECT @count = count(*) FROM aTable 1 = 1 ';

IF @col1 IS NOT EMPTY
BEGIN
    SET @qry = @qry + ' AND col1 = '+ ''''+@col1+''''
END

最后,我建议您进一步参数化查询。

SET @qry = 'SELECT @count = count(*) FROM aTable WHERE 1 = 1 '
DECLARE @ParamDef NVARCHAR(MAX) = '@Col1 VARCHAR(20), @Col2 VARCHAR(20), @Col3 VARCHAR(20), @Count INT OUTPUT';

IF @Col1 IS NOT NULL
    SET @qry = @qry + ' AND Col1 = @Col1';

IF @Col2 IS NOT NULL
    SET @qry = @qry + ' AND Col2 = @Col2';

IF @Col3 IS NOT NULL
    SET @qry = @qry + ' AND Col3 = @Col3';


EXECUTE sp_executesql @qry, @ParamDef, @Col1, @Col2, @Col3, @Count OUTPUT;

<强> Working Examples on SQL Fiddle