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
Related
Create Function fnRMatrixColorGet1(
#RMID varchar(20)
)
returns varchar(100)
as
begin
EXEC (N'SELECT ' + 'C'+#RMID + ' FROM vwemployeeget where empid='+#RMID)
return
end
As Gordon wrote in the comments, user defined functions in SQL Server can't execute dynamic SQL.
From Create User-defined Functions:
User-defined functions cannot make use of dynamic SQL or temp tables. Table variables are allowed.
However, you can create a stored procedure to do that:
CREATE PROCEDURE stpRMatrixColorGet1
(
#RMID varchar(20)
#MatrixColor varchar(100) OUTPUT
)
AS
DECLARE #Sql nvarchar(4000),
#Column sysname = N'C' + #RMID;
-- White list column name since it can't be parameterized
IF EXISTS
(
SELECT 1
FROM Information_Schema.Columns
WHERE Table_Name = 'vwemployeeget'
AND Column_Name = #Column
)
BEGIN
SET #SQL = N'SELECT #MatrixColor = QUOTENAME('+ #Column +') FROM vwemployeeget where empid = #RMID'
-- Safely execute dynamic SQL using sp_ExecuteSql
EXEC sp_ExecuteSql
#Sql,
N'#RMID varchar(20), #MatrixColor varchar(100) OUTPUT',
#RMID,
#MatrixColor OUTPUT
END
I have an Error table which stores the names of the table in which the error occurred.
Now I want to query the table using the table name selected from the "Error" table.
I tried to store the table name in a variable and use this variable in the FROM clause in my query. But this doesn't work:
DECLARE #tableName VARCHAR(15)
select #tableName = TableName from SyncErrorRecords where Status = 'Unsynced'
select * from #tableName
Can anyone help me out on this.
Thanks in advance.
you need to use Dynamic SQL
either
declare #sql nvarchar(max)
select #sql = 'select * from ' + quotename(#tableName)
exec (#sql)
or
exec sp_executesql #sql
The Query as follows.
DECLARE #tableName VARCHAR(15),
#Qry VARCHAR(4000)
SELECT #tableName = TableName FROM SyncErrorRecords WHERE Status = 'Unsynced'
SET #Qry = 'SELECT * FROM ' + #tableName
EXEC SP_EXECUTESQL #Qry
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)
I'm making a way for our developers to easily update our database. The way we're doing this is by creating dynamic queries where they define the variables at the top and the query uses the variables for everything else. I've used many recommendations off Stackoverflow, but can't get this to work.
USE MyDatabase
DECLARE #TABLE VARCHAR(200) = 'MyTable'
DECLARE #COLUMN VARCHAR(200) = 'MyColumn'
DECLARE #DATATYPE VARCHAR(200) = 'VARCHAR(200)'
IF COL_LENGTH(#TABLE, #COLUMN) IS NULL
BEGIN
DECLARE #SQL as NVARCHAR(MAX) = 'ALTER TABLE ' + #TABLE + ' ADD COLUMN '
+ #COLUMN +' '+ #DATATYPE
EXEC SP_EXECUTESQL #SQL
END
I get the error:
Incorrect syntax near the keyword 'COLUMN'.
As the error message indicates that is the wrong syntax. Somewhat confusingly the COLUMN keyword is not permitted when adding a column.
Also VARCHAR(200) should really be SYSNAME to cope with all possible valid names (currently equivalent to nvarchar(128)) and use QUOTENAME to correctly escape any object names containing ]
More about this is in The Curse and Blessings of Dynamic SQL: Dealing with Dynamic Table and Column Names
I highly suggest against doing this due to exposure to SQL injection. However, if you must, remove the word COLUMN from your script and it should work.
USE MyDatabase
DECLARE #TABLE VARCHAR(200) = 'MyTable'
DECLARE #COLUMN VARCHAR(200) = 'MyColumn'
DECLARE #DATATYPE VARCHAR(200) = 'VARCHAR(200)'
IF COL_LENGTH(#TABLE, #COLUMN) IS NULL
BEGIN
DECLARE #SQL as NVARCHAR(MAX) = 'ALTER TABLE ' + #TABLE + ' ADD ' + #COLUMN +' '+ #DATATYPE
EXEC SP_EXECUTESQL #SQL
END