2013-03-15 92 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