问题
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.
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
)Even thought you are checking
@CntTmp > 1
you are not really assigning count(*) value to it (won't work anyway due to reason 1)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