动态查询存储过程

时间:2013-03-15 19:52:40

标签: sql stored-procedures dynamic-sql

我正在使用动态SQL编写存储过程。

在我的程序中,我说了10个类似列的表。

例如,如果我考虑Designation& Department个表,Designation表包含以下列:

Designation, Code, EntryBy, EntryOn, ModifiedBy, ModifiedOn 

Department表包含以下列:

Department, Code, EntryBy, EntryOn, ModifiedBy, ModifiedOn

同样我还有其他八个表。

在我的存储过程中,我需要更新并将数据插入到所有表中。所以,而不是写更新&为每个表插入语句,我使用的是一个存储过程,它接受表名作为参数,并检查该表中是否已存在该行。

如果该行存在,那么该记录将被更新,否则该记录将被插入到相应的表中。

    ALTER PROC UpdateMasterItems
    (
        @MasterTypeTmp  varchar(50),
        @NameTmp    varchar(50),
        @CodeTmp    varchar(10))
    AS
    BEGIN   
       DECLARE @CntTmp numeric(2,0)

       EXEC('select count(*)' + @CntTmp + ' from ' + @MasterTypeTmp + ' where ' + @MasterTypeTmp  + ' = ' + @NameTmp)

       IF(@CntTmp > 1)
       BEGIN
          EXEC('UPDATE ' + @MasterTypeTmp + ' SET ' + 'Code = ' + @CodeTmp + ', ModifiedBy = CURRENT_USER, MOdifiedOn = CURRENT_TIMESTAMP WHERE' + @MasterTypeTmp + ' = ' +  @NameTmp)
          RETURN 10
       END      
       ELSE
       BEGIN    
          EXEC('INSERT INTO ' + @MasterTypeTmp + '(' + @MasterTypeTmp + ', Code, EntryBy, EntryOn, ModifiedBy, ModifiedOn )  VALUES (' + @NameTmp + ',' + @CodeTmp + ',' + 'CURRENT_USER, CURRENT_TIMESTAMP, CURRENT_USER, CURRENT_TIMESTAMP )') 
          RETURN 11
       END
END

其中@MasterTypeTmp是表名(可以是Department / Designation .....)

我在执行程序时遇到错误:

执行声明:

EXEC UpdateMasterItems 'Designation', 'TestName', 'TestCode'

错误陈述:

  

列名称'TestName'无效。

     

列名称'TestCode'无效。

但是TestName& TestCode不是列名。这些是列的值。如果我的动态查询错误或问题出在哪里,请告诉我!

提前致谢

芒卡

3 个答案:

答案 0 :(得分:0)

您的字符串连接缺少某些',db将这些值解释为列名:

EXEC('INSERT INTO ' + @MasterTypeTmp + '(' + @MasterTypeTmp + ', Code, EntryBy, EntryOn, ModifiedBy, ModifiedOn )  
VALUES (''' + @NameTmp + ''',''' + @CodeTmp + ''',' + 'CURRENT_USER, CURRENT_TIMESTAMP, CURRENT_USER, CURRENT_TIMESTAMP )') 

答案 1 :(得分:0)

我认为错误消息是因为您使用'包装了列名称(即; 'Designation'错误)。应为Designation

但是还有其他问题。

  1. 我认为你不能在动态sql中定义变量并将它们分配到里面。因为dynamic sql runs in a different session因此在范围之外定义的变量是未知的。 (即; @CntTmp

  2. 即使您正在检查@CntTmp > 1,您也没有真正为其分配计数(*)值(由于原因1无论如何也无法正常工作)

  3. 如果记录计数>您的@CntTmp将会溢出99(如果你没有坏数据,那真的不是问题)

  4. 如果您需要按照描述的方式完成这项工作,您必须声明变量,检查记录的存在,然后更新/插入 all within the same dynamic query 。您可以使用if exists (select ....) update ... else insert...

    而不使用变量

答案 2 :(得分:0)

首先,这部分会给您一个错误:Error converting data type varchar to numeric.

DECLARE @CntTmp numeric(2,0)
EXEC('select count(*)' + @CntTmp + ' from ' + @MasterTypeTmp + ' where ' + @MasterTypeTmp  + ' = ' + @NameTmp)

因为CntTmp是数字,不能直接在该表达式中使用。

如果改为:

EXEC('select count(*)' + cast(@CntTmp as varchar(30)) + ' from ' + @MasterTypeTmp + ' where ' + @MasterTypeTmp  + ' = ' + @NameTmp)

它会给你一个错误,因为你不能直接在动态SQL中使用变量。 此外,它不会为您提供输出,因为CntTmp为空。

因此,您可以创建另一个变量来存储结果,从numeric转换为varchar,然后执行ISNULL函数,如果变量为null,则为变量赋值。

其次,您的列值缺少'

这是工作存储过程:

ALTER PROC UPDATEMASTERITEMS   
( @MASTERTYPETMP VARCHAR(50), @NAMETMP VARCHAR(50), @CODETMP VARCHAR(10))    
AS

BEGIN

DECLARE @CNTTMP NUMERIC(2,0)
DECLARE @CNTTMPVAL VARCHAR(30) = ISNULL(CAST(@CNTTMP AS VARCHAR(30)) , '')

EXEC ('SELECT COUNT(*) ' + @CNTTMPVAL + ' FROM ' + @MASTERTYPETMP + ' WHERE ' + @MASTERTYPETMP  + ' = ''' + @NAMETMP + '''')
IF(@CNTTMP > 1)
    BEGIN
     EXEC('UPDATE ' + @MASTERTYPETMP + ' SET ' + 'CODE = ''' + @CODETMP + ''', MODIFIEDBY = CURRENT_USER, MODIFIEDON = CURRENT_TIMESTAMP WHERE' + @MASTERTYPETMP + ' = ''' +  @NAMETMP + '')
     RETURN 10
    END
ELSE
    BEGIN 
    EXEC('INSERT INTO ' + @MASTERTYPETMP + '(' + @MASTERTYPETMP + ', CODE, ENTRYBY, ENTRYON, MODIFIEDBY, MODIFIEDON )  VALUES (''' + @NAMETMP + ''',''' + @CODETMP + ''',' + 'CURRENT_USER, CURRENT_TIMESTAMP, CURRENT_USER, CURRENT_TIMESTAMP )') 
     RETURN 11
    END

END

无论如何,您可以使用this

格式化SQL