2013-03-15 93 views
0

我正在使用动态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的声明:

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

错误陈述:

Invalid column name 'TestName'.

Invalid column name 'TestCode'.

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

在此先感谢

芒卡

回答

0

我认为该错误信息是因为你裹列名与'(即; 'Designation'是错误的)。应该是Designation

但也有其他问题。

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

  2. 甚至认为你正在检查@CntTmp > 1你是不是真的分配COUNT(*)的值给它(不会工作无论如何,由于原因1)

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

如果你需要得到这个工作,你所描述的方式,你必须声明变量,检查记录的存及其然后更新/插入all within the same dynamic query。你可以不使用if exists (select ....) update ... else insert...

+0

感谢您的SQL。所有点都注意到了。我试图使用IF EXISTS()而不是count。但是,IF EXISTS不会采取动态查询。它给我错误。 – user2174615 2013-03-15 20:32:12

+0

谢谢。所有观点都指出。是否可以在IF EXISTS()中使用动态sql?当我尝试这样做时,我遇到了错误。 – user2174615 2013-03-15 20:34:49

+0

是的,你可以。 [检查这个例子小提琴](http://sqlfiddle.com/#!3/ac7f7/7) – Kaf 2013-03-15 20:41:07

0

你的字符串连接缺少一些'和DB解释值作为列名:

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

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

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

因为​​是一个数字,并且可以在不表达直接使用。

如果改成这样:

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

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

所以,你可以创建另一个变量来存储结果,从铸numericvarchar,然后执行ISNULL功能给变量的值,如果它是空。

其次,您缺少'作为您的列值。

这里是工作的存储过程:

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