2013-03-15 3 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. Я думаю, что вы не можете определить переменные из динамического sql и назначить их внутри. Потому что dynamic sql runs in a different session и поэтому переменные, определенные вне области действия, неизвестны.(То есть, @CntTmp)

  2. Даже думал, что вы проверяете @CntTmp > 1 вы на самом деле не назначая количество (*) значение этого (не будет работать в любом случае из-за причины 1)

  3. Ваш @CntTmp будет переполнение, если количество записей> 99 (на самом деле не проблема, если у вас нет плохих данных)

Если вам нужно, чтобы получить эту работу так, как вы описали, вы должны объявить переменные, проверьте существование записей и затем обновить/вставить all within the same dynamic query. Можно обойтись без переменной с помощью if exists (select ....) update ... else insert...

+0

Спасибо за это. Все отмеченные пункты. Я попытался использовать IF EXISTS() вместо count. Но IF EXISTS не принимает динамический запрос. Это дает мне ошибку. – user2174615

+0

Спасибо. Все отметили. Можно ли использовать динамический sql в IF EXISTS()? Я получаю ошибки, когда пытаюсь это сделать. – user2174615

+0

Да, вы можете. [Проверьте этот пример скрипта] (http://sqlfiddle.com/#!3/ac7f7/7) – Kaf

0

Ваша конкатенация отсутствуют некоторые ' и дб интерпретировать значения в качестве имен столбцов:

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) 

Поскольку CntTmp является числовой и не может непосредственно использоваться в этом выражении.

Если изменить это:

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

Это даст вам ошибку, потому что вы не можете использовать переменную непосредственно в динамическом SQL. Кроме того, он не даст вам выход, потому что CntTmp имеет значение null.

Таким образом, вы можете создать другую переменную, чтобы сохранить результат из списка 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 

Во всяком случае, вы можете форматировать SQL с помощью this

Смежные вопросы