Stored Procedure with Dynamic Query

好久不见. 提交于 2019-12-25 05:42:05

问题


I am writing a stored procedure using dynamic SQL.

In my procedure, I have say some 10 tables of similar columns.

For example if I consider Designation & Department tables, Designation table has these columns:

Designation, Code, EntryBy, EntryOn, ModifiedBy, ModifiedOn 

and Department table has these columns:

Department, Code, EntryBy, EntryOn, ModifiedBy, ModifiedOn

and similarly I have some eight other tables.

In my stored procedure, I need to update and insert data into all the tables. So, instead of writing update & insert statements for each table, I am using a stored procedure which accepts the table name as a parameter and checks if the row already exists in that table.

If that row is present, then that record will be updated otherwise that record will be inserted into the respective table.

    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

where @MasterTypeTmp is the table name(can be Department/Designation.....)

I am getting an error while executing the procedure:

Exec Statement:

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

Error Statements:

Invalid column name 'TestName'.

Invalid column name 'TestCode'.

But TestName & TestCode are not column names. Those are the values for the columns. Please let me know if my dynamic queries are wrong or where the problem is!

Thanks in advance

Mounika


回答1:


I think the error message is because you have wrapped column names with ' (ie; 'Designation' is wrong). Should be Designation

But there are other issue as well.

  1. I think you cannot define variables out side dynamic sql and assign them inside. Because dynamic sql runs in a different session and therefore variables defined outside the scope are unknown. (ie; @CntTmp)

  2. Even thought you are checking @CntTmp > 1 you are not really assigning count(*) value to it (won't work anyway due to reason 1)

  3. Your @CntTmp will overflow if the record count > 99 (not really an issue if you don't have bad data)

If you need to get this work the way you have described, you have to declare variables, check the existance of records and then update/insert all within the same dynamic query. You could do without a variable using if exists (select ....) update ... else insert...




回答2:


Your string concatenation are missing some ' and the db interpret the values as column names:

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



回答3:


First, this part will give you an error: Error converting data type varchar to numeric.

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

Because the CntTmp is an numeric and can't directly used in that expression.

If you change to this:

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

It will give you an error because you can't use variable directly in dynamic SQL. Also, it will not give you the output, because CntTmp is null.

So, you can create another variable to store the result from cast the numeric to varchar and then perform ISNULL function to give the variable a value if it's null.

Second, you're missing ' for your column value.

And here is the working stored procedures:

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

Anyway, you can format your SQL using this



来源:https://stackoverflow.com/questions/15441024/stored-procedure-with-dynamic-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!