I have two tables called ALUMNO and ALUMNO_GENERAL.
I would like to create a stored procedure which automatically chooses which table will update by looking at the variable #campo declared as a parameter to the stored procedure.
When I execute the procedure below, it says 1 row affected, but does not update the value of the table.
exec updateAl 'CALLE','0015','ROJO'
Stored procedure:
create procedure updateAl
#campo varchar(30), #matr varchar(10), #newVal varchar(15)
as begin
if #campo IN ('AP_PATERNO' , 'AP_MATERNO', 'NOMBRE', 'GRUPO', 'TURNO' , 'SEMESTRE' , 'STATUS' , 'NUMEMPLEADO')
begin
select #campo
declare #sql varchar (1000)
select #sql= 'update alumno set '+ #campo+'='+#newVal +' where MATRICULA='+#matr
exec(#sql)
end
else
update ALUMNO_GENERAL set #campo =#newVal where MATRICULA=#matr
end
Your dynamic sql is not correct, try this:
select #sql= 'update alumno set '+ #campo+'='''+#newVal +''' where MATRICULA='''+#matr + '''
exec(#sql)
end
Related
I want to create a stored procedure that will update a table. The procedure will join two tables and I want to pass the table name using a variable (#tablename).
This error is generated:
Must declare the table variable "#tablename".
My code:
Create Procedure dbo.SpUpdate (#TableName varchar(50))
as
begin
set #tablename='Customer'
Update a
Set AgentNumber = '5',
From dbo.CustomerList a
join #tablename b on a.customerid = b.customerid
end
You can use this script:
Create Procedure dbo.SpUpdate (#TableName varchar(50))
as
begin
DECLARE #SqlText NVARCHAR(MAX)
SET #SqlText =
'Update a
Set AgentNumber=''5'',
From dbo.CustomerList a
join ' + QUOTENAME(#tablename) + ' b
on a.customerid= b.customerid'
EXEC sp_executesql #SqlText
end
It seems very simple solution, but I can't figure it out. Please help.
I have to call a stored proc with OUTPUT param from another stored proc. I think one of the issues is dynamic SQL, but I don't know how else to write it since #SQLWhere will change dynamically within C# code.
This is the proc being called from another proc:
ALTER PROCEDURE [dbo].[USP_RetrieveTotalRecord]
#SQLWhere AS NVARCHAR(1000),
#TotalRecordsFound as varchar(16) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL AS NVARCHAR(Max)
SET #SQL='Select #TotalRecordsFound = Count(Table_ID)
From TableName Where ' + #SQLWhere
EXEC(#SQL)
return
END
Here is how I am calling it from another proc:
Declare #TotalRec AS NVARCHAR(16);
Declare #SQLWhere AS NVARCHAR(1000);
SET #SQLWhere='Date Between ''12/13/2016'' AND ''12/14/2016'''
EXECUTE USP_RetrieveTotalRecord #SQLWhere, #TotalRec output;
Here is the error I am trying to resolve:
Msg 137, Level 15, State 1, Line 30
Must declare the scalar variable "#TotalRecordsFound".
Don't do what you are trying to do, Only pass values to stored procedure and then build the dynamic sql inside your procedure, something like ......
ALTER PROCEDURE [dbo].[USP_RetrieveTotalRecord]
#StartDate DATE = NULL
,#EndDate DATE = NULL
,#TotalRecordsFound INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(Max);
SET #SQL = N' Select #TotalRecordsFound = Count(Table_ID) '
+ N' From TableName Where 1 =1 '
+ CASE WHEN #StartDate IS NOT NULL THEN
N' AND [Date] >= #StartDate ' ELSE N' ' END
+ CASE WHEN #EndDate IS NOT NULL THEN
N' AND [Date] <= #EndDate ' ELSE N' ' END
EXEC sp_executesql #SQL
,N'#StartDate DATE, #EndDate DATE, #TotalRecordsFound INT OUTPUT'
,#StartDate
,#EndDate
,#TotalRecordsFound OUTPUT
END
Now #EndDate and #StartDate variables are optional , depending on what variable values you pass procedure will build the dynamic sql accordingly and return the results.
Also using parameterised query with sp_executesql will protect you against a possible SQL-Injection attach and also your proc will benefit from parameterised execution plans.
Not sure why you have a 2nd SP, just use one like so:
Declare #TotalRec AS NVARCHAR(16);
Declare #SQLWhere AS NVARCHAR(1000);
SET #SQLWhere='Date Between ''12/13/2016'' AND ''12/14/2016'''
SET #SQL='Select #TotalRecordsFound = Count(Table_ID)
From TableName Where ' + #SQLWhere
EXEC(#SQL)
Or use date variables if that's all you are using for selection (no dynamic sql necessary) - unless this is just a simplified example
--- comment section is broken, so, in response to get a value out, use something like this:
Ok - the simplest way is to use sp_ExecuteSQL
Declare #result int
Declare #sql nvarchar(max)
SET #SQL = ' SELECT COUNT(*) FROM MyTable'
exec sp_ExecuteSQL #sql, N' #Result int Output', #Result output
select #result as MyCount
M. ali, thanks for your help, but we have all SELECT, WHERE, and GROUP by criteria being passed from the application after dynamic selections. I needed a quick fix.
Finally I was able to resolve the issue using a temp table. I know they are not recommended, but I tried using Common table expression, table variable, but the #TotalRecordsFound was not visible outside the dynamic SQL. Therefore, created temp table, Inserted data into it using dynamic SQL, and then joined it with the next select statement.
I am using SQL Server 2012, I am going to Create Store Procedure which copies a column from a table in a variable, Could any one please tell me what is Wrong with this code?
alter Procedure Id_Fetch
#Col varchar(50)=null,
#Table VARCHAR(50)=Null,
#OrdrBy Varchar(40)=null
as
Begin
declare #TempCol nvarchar (100)
Exec(' SELECT '+#TempCol+' = '+#Col+' from ' + #Table +' order by '+#OrdrBy )
its showing error "Incorrect Syntax near '='
A little modification ...... Use TOP 1 in your select as if more than one value is returned by your select it will throw an error.
Use SYSNAME datatype for your Column names and table names.
Use QUOTENAME() function around your object name parameters, which puts square brackets [] around the passed parameter value and forces it to be treated as an object name (Protection against Sql Injection attack).
Use sp_executesql instead of EXEC and concatenating parameter values into string and executing again protects you against Sql Injection attack.
ALTER PROCEDURE Id_Fetch
#Col SYSNAME,
#Table SYSNAME,
#OrdrBy SYSNAME,
#Col_Value NVARCHAR(100) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N' SELECT TOP 1 #Col_Value = ' + QUOTENAME(#Col)
+ N' FROM ' + QUOTENAME(#Table)
+ N' ORDER BY ' + QUOTENAME(#OrdrBy)
EXECUTE sp_executesql #Sql
,N'#Col_Value NVARCHAR(100) OUTPUT'
,#Col_Value OUTPUT
END
I have some tables for storing different file information, like thumbs, images, datasheets, ...
I'm writing a stored procedure to retrieve filename of a specific ID. something like:
CREATE PROCEDURE get_file_name(
#id int,
#table nvarchar(50)
)as
if #table='images'
select [filename] from images
where id = #id
if #table='icons'
select [filename] from icons
where id = #id
....
How can I rewrite this procedure using case when statement or should I just use table name as variable?
You can't use case .. when to switch between a table in the FROM clause (like you can in a conditional ORDER BY). i.e. so the following:
select * from
case when 1=1
then t1
else t2
end;
won't work.
So you'll need to use dynamic SQL. It's best to parameterize the query as far as possible, for example the #id value can be parameterized:
-- Validate #table is E ['images', 'icons', ... other valid names here]
DECLARE #sql NVARCHAR(MAX)
SET #sql = 'select [filename] from **TABLE** where id = #id';
SET #sql = REPLACE(#sql, '**TABLE**', #table);
sp_executesql #sql, N'#id INT', #id = #id;
As with all dynamic Sql, note that unparameterized values which are substituted into the query (like #table), make the query vulnerable to Sql Injection attacks. As a result, I would suggest that you ensure that #table comes from a trusted source, or better still, the value of #table is compared to a white list of permissable tables prior to execution of the query.
Just build SQL string in another variable and EXECUTE it
DECLARE #sql AS NCHAR(500)
SET #sql=
'SELECT [filename] '+
' FROM '+#table+
' WHERE id = #id'
EXECUTE(#sql)
CREATE PROCEDURE get_file_name(
#id int,
#table nvarchar(50)
)as
DECLARE #SQL nvarchar(max);
SET #SQL = 'select [filename] from ' + #table + ' where id = ' + #id
EXECUTE (#SQL)
Hi I am writing a large stored procedure, which creates a dynamic report table, of n columns in size, the first 6 are constant the remainder depend on a few arguments passed to the procedure to create the table with the required columns.
The problem that I am having is with the following TSQL
DECLARE #columnname VARCHAR(50)
SET #columnname = 'on_' + #description
IF NOT EXISTS(SELECT * FROM syscolumns WHERE id = OBJECT_ID('reports')
AND NAME = #columnname)
BEGIN
ALTER TABLE reports ADD #columnname VARCHAR(50) NULL
END
I am getting syntax errors with this at the #columnname in the ALTER TABLE statement of the above code.
Also as I am new to this, I am not sure if this is the best way to do this, or if there are better ways in TSQL to generate the required dynamic table.
Try this:
declare #sql nvarchar(100)
set #sql = 'ALTER TABLE reports ADD '+ #columnname+' VARCHAR(50) NULL'
exec sp_executesql #sql
Try
DECLARE #columnname VARCHAR(50)
SET #columnname = '[on_' + #description +']'
IF NOT EXISTS(SELECT * FROM syscolumns WHERE id = OBJECT_ID('reports')
AND NAME = #columnname)
BEGIN
ALTER TABLE reports ADD #columnname VARCHAR(50) NULL
END
Cannot get around having to do it dynamically I believe so change your BEGIN block to something like this:
DECLARE #sql VARCHAR(8000)
BEGIN
SET #sql = 'ALTER TABLE Table_1 ADD '+#columnname+' VARCHAR(50) NULL'
EXEC(#sql)
END