Dynamically adding column to the temptable? - sql-server

In my sqluery, i am trying to add columns dynamically, but it is showing error Like:
Msg 214, Level 16, State 2, Procedure sp_executesql, Line 1
Procedure expects parameter '#statement' of type 'ntext/nchar/nvarchar'.
this is my proc
declare #curntyear int
declare #pasyear int
declare #sql nvarchar(max)
declare #temp varchar(50)
select #pasyear=YEAR( DATEADD (YEAR,-3,GETDATE ()))
select #curntyear =YEAR (getdate())
print #pasyear
print #curntyear
create table #TempTable (years varchar(30))
insert into #TempTable select (cargo+port+railway+estate)as 'sum' from operatingincome where YEAR(createddate)=#pasyear
while (#curntyear >=#pasyear )
begin
set #pasyear =#pasyear +1
--select #temp=(cargo+port+railway+estate)as 'sum' from operatingincome where YEAR(createddate)=#pasyear
select #temp= convert(varchar,(cargo+port+railway+estate),106) from operatingincome where YEAR(createddate)= #pasyear
set #sql ='alter table #TempTable add '+ CONVERT(varchar,#pasyear,106)+' varchar(50)'
exec sp_executesql #sql
print #sql
set #sql = 'update #TempTable set '+CONVERT(varchar,#pasyear,106) +'='+#temp +' where years='''+CONVERT(varchar,#pasyear,106)+''
exec sp_executesql #sql
set #temp =''
end
select * from #TempTable
i am getting error like this :
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '2009'.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '2010'.
alter table #TempTable add 2010 varchar(50)
update #TempTable set 2010=9300 where years=2010

Sounds like you're calling sp_executesql with a VARCHAR statement, when it needs to be NVARCHAR.
e.g. This will give the error because #SQL needs to be NVARCHAR
Declare your variable #sql varchar to nvarchar, that will work fine:
declare #sql nvarchar(max)
UPdate:
Change your sql setting as below: you need to use [] in column name as [ColumName]
set #sql ='alter table #TempTable add ['+ CONVERT(varchar,#pasyear,106)+'] varchar(50)'
set #sql = 'update #TempTable set ['+CONVERT(varchar,#pasyear,106) +']='+#temp +' where years='''+CONVERT(varchar,#pasyear,106)+''

Change
declare #sql varchar(max)
to be
declare #sql nvarchar(max)
You are told this in the error message and on MSDN (my bold)
[ #statement= ] statement
Is a Unicode string that contains a Transact-SQL statement or batch. statement must be either a Unicode constant or a Unicode variable.

Related

T-SQL variable not used in sp_execsql

I am running a cursor that executes dynamic SQL using a variable.
SET #Wk = CAST(#Cntr AS nvarchar(5))
DECLARE #params nvarchar(30) = N'#Wk nvarchar(5)'
-- .. start cursor
EXEC sp_executesql N'ALTER TABLE #Temp DROP COLUMN [WK #WK Sold]', #params, #Wk
I get the error
Msg 4924, Level 16, State 1, Line 4
ALTER TABLE DROP COLUMN failed because column 'WK #WK Sold' does not exist in table #Temp
I know that #param and #Wk work because I ran
EXEC sp_executesql N'select #Wk', #params, #Wk
and it worked. I know I can just run
EXEC ('ALTER TABLE #Temp DROP COLUMN [WK ' + #Wk + ' Sold]')
but I'd like to use sp_executesql.
Is it even possible the way I have tried?
Thank you
The problem has nothing to do with the variable here. The problem is that you think that a variable/parameter when used in the context of an object results in that variable being injected into the statement. That doesn't happen. SELECT 1 AS [#a] return return a column aliased as literally #a not a column where the alias is the value of a variable called #a.
What you need to do here is safely inject the value into the dynamic statement and ideally validate the name too:
DECLARE #Cntr SomeDataType; --I don't know what the datatype should be.
DECLARE #wk nvarchar(5),
#Column sysname;
SET #wk = #Cntr; --No need for the cast here
SET #Column = (SELECT c.name
FROM tempdb.sys.tables t
JOIN tempdb.sys.columns c ON t.object_id = c.object_id
WHERE t.[name] LIKE N'#temp%'
AND c.name = N'WK
' + #wk + N' Sold');--Does your column name really have a carriage return and line break in it?
DECLARE #SQL nvarchar(MAX) = N'ALTER TABLE #Temp DROP COLUMN ' + QUOTENAME(#Column) + N';';
EXEC sys.sp_executesql #SQL;

Cannot pass column name as parameter to sp_executesql

I'm having trouble executing the below piece of code, it's giving me an error as below:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '#ST'.
I can try implementing the login using dynamic SQL, but wanted to try the sp_executesql method. Please let me know if I'm having some syntax error or I'm not supposed to pass table names as parameters?
DECLARE #SQL NVARCHAR(4000)= '';
SET #SQL = N'--INSERT INTO #missingkeys ( SOURCE_KEY,[ROWCOUNT] )
SELECT S.[SOURCE_KEY], COUNT(1) AS [ROWCOUNT] FROM (SELECT DISTINCT #SK AS [SOURCE_KEY]
FROM [PDA].#ST ) AS S
LEFT JOIN [PDA].#MT AS T
ON T.[SOURCE_KEY] = S.[SOURCE_KEY]
GROUP BY S.[SOURCE_KEY]';
DECLARE #SOURCETABLE NVARCHAR(255)= 'FACT';
DECLARE #SOURCE_KEY NVARCHAR(255)= 'KEY', #MAP_TABLE NVARCHAR(255)= 'DimMap';
EXEC sp_executesql
#SQL,
N'#SK nvarchar(255), #ST nVARCHAR(255), #MT nVARCHAR(255)',
#SK = #SOURCE_KEY,
#ST = #SOURCETABLE,
#MT = #MAP_TABLE;
You can't have columns as parameters, same for any object name (table, stored procedure, ...).
You will have to make the statement dynamic, i.e. format the column name in the SQL string:
SET #SQL =
N'SELECT '+
'S.[SOURCE_KEY],'+
'COUNT(1) AS [ROWCOUNT] '+
'FROM ('+
'SELECT DISTINCT '+
QUOTENAME(#SK)+' AS [SOURCE_KEY] '+
'...'; -- the rest of your statement
PS: Use QUOTENAME to escape object names to avoid SQL Injection.
You can pass tables if you write the data to an identical user-defined table type. The parameter must be READONLY:
CREATE TYPE [dbo].[t] AS TABLE([a] [int] NOT NULL PRIMARY KEY CLUSTERED)
create table #t (a int)
insert into #t values (1), (2), (3)
exec sp_executesql N'select * from #t'
declare #t t
insert into #t select a from #t
exec sp_executesql N'Select * from #p1', N'#p1 t readonly', #t

SQL, Assign Select Column to Variable

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

declare variable in a table in SQL

I have a below query that requires help
Declare #DB varchar(3)
set #DB = 'C01'
SELECT * FROM SVBNORD+#DB WHERE ORDER_DATE = ''
But I get a message
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '+'.
Can you please help me correct my statement.
You should use execute to dynamically call the query:
Declare #DB varchar(3)
set #DB = 'C01'
execute ('SELECT * FROM SVBNORD'+#DB+' WHERE ORDER_DATE = '''' ')
You can't do this in normal sql. You can however build up sql dynamically and execute it, like so:
DECLARE #sql NVARCHAR(MAX);
SET #sql =
'SELECT * FROM SVBNORD' + #DB + N'WHERE ORDER_DATE = ''''';
EXEC(#sql);
You'll need to double up any single quotes in the query.

Error in Creating stored procedure

Anybody tell me what's wrong with creating this stored procedure.
CREATE PROC ImportData
AS
BEGIN
DECLARE #DatabasePath VARCHAR(MAX)
SET #DatabasePath = 'E:\ABC.xls'
DECLARE #sql nvarchar(MAX)
SET #sql = '
INSERT INTO [dbo].[Table_1]
SELECT *
FROM OPENROWSET(''Microsoft.Jet.OLEDB.4.0'',
''Excel 8.0;Database=' + #DatabasePath + ',
''SELECT * FROM [Sheet1$]'') AS xlsTable'
EXEC sp_executesql #sql
GO
END
ERROR:-
Incorrect syntax near '#sql'.
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near 'END'.
Remove the GO from within the Stored Procedure
Something like
CREATE PROC ImportData
AS
BEGIN
DECLARE #DatabasePath VARCHAR(MAX)
SET #DatabasePath = 'E:\ABC.xls'
DECLARE #sql nvarchar(MAX)
SET #sql = '
INSERT INTO [dbo].[Table_1]
SELECT *
FROM OPENROWSET(''Microsoft.Jet.OLEDB.4.0'',
''Excel 8.0;Database=' + #DatabasePath + ',
''SELECT * FROM [Sheet1$]'') AS xlsTable'
EXEC sp_executesql #sql
END
You cannot have a batch terminator (GO) in the body of a stored procedure.

Resources