SELECT Query with Columns stored in a variable - sql

I have a stored procedure in which I am getting table's column which is needed for SELECT statement in a variable with comma separated. But It is not working for me.:
SP:
ALTER PROCEDURE [dbo].[SPGet_Assistance_Detail]
(
#Id int,
#UserDesig varchar(20) --User Desig can be 'FFR' or 'HO'
)
AS
DECLARE #Cols VARCHAR(MAX)
SELECT #Cols = Column_Listing FROM Role_Col_Mapping WHERE Tbl_Name = 'Assistance' and Role = #UserDesig
SELECT #Cols FROM dbo.Assistance WHERE Service_Id=(#Id)
RETURN
Here Role_Col_Mapping has fields like: Tbl_Name, Role , and Column_Listing. It stores data of cols allowed to any user based on his role in any table. And Assistance is a table which columns' data I needed to display.
I am getting wrong output. Which is cols separated by comma.

You must use dynamic SQL - something like this:
ALTER PROCEDURE [dbo].[SPGet_Assistance_Detail]
(
#Id int,
#UserDesig varchar(20) --User Desig can be 'FFR' or 'HO'
)
AS
DECLARE #Cols VARCHAR(MAX)
SELECT #Cols = Column_Listing FROM Role_Col_Mapping WHERE Tbl_Name = 'Assistance' and Role = #UserDesig
DECLARE #query NVARCHAR(MAX)
SELECT #query = 'SELECT ' + #Cols + ' FROM CRM.dbo.Assistance WHERE Service_Id=' + cast(#Id AS VARCHAR(MAX))
EXEC sp_executesql #query
RETURN

Related

not able to use sp_executesql command

I need to execute below query
SELECT *, IDENTITY( int ) AS IDColumn INTO #SmootheningTable FROM #TableName
where #SmootheningTable is temporary table
and #TableName is name of table
I need to use command either EXEC or sp_executesql to execute.
If I use EXEC, I wont be able to use #SmootheningTable in later portion of my stored procedure.
And while trying sp_executesql, I am getting error stating #statement error.
How can I use sp_executesql for above given query.
Or is there any other way to execute?
this is the query I am using
DECLARE #TablePlaceHolder VARCHAR(50)='';
DECLARE #SmootheningQuery NVARCHAR(max) = 'SELECT *, IDENTITY( int ) AS IDColumn INTO #SmootheningTable FROM #TablePlaceHolder';
EXEC sp_executesql #SmootheningQuery, N'#TablePlaceHolder varchar(50)', #PlanDetailTempTableName
and i am getting below error
Must declare the table variable "#TablePlaceHolder".
Thanks in advance
There are two issues in your code:-
First : Putting the variable name inside the string, put in out like next:-
instead of this line:-
DECLARE #SmootheningQuery NVARCHAR(max) = 'SELECT *, IDENTITY( int ) AS
IDColumn INTO #SmootheningTable FROM #TablePlaceHolder';
Type this line:-
DECLARE #SmootheningQuery NVARCHAR(max) = 'SELECT *, IDENTITY( int ) AS
IDColumn INTO #SmootheningTable FROM ' + #TablePlaceHolder;
Second: Don't use local temp table within sp_executeSql,
The Local temporary table [with one hash # ] is visible in current session only, use global temporary tables instead [with two hashes ## ] are visible in all sessions,
So instead of
#SmootheningTable
Type
##SmootheningTable
Demo (All Code): -
Create table MyTable (id int , name nvarchar(100))
go
insert into MyTable values (1, 'Ahmed');
insert into MyTable values (2, 'Abdelqader');
go
declare
#TableName varchar(50),
#MyQuery nvarchar(200)
set #TableName = 'MyTable'
set #MyQuery = 'select * Into ##MYTempTable From ' + #TableName
exec sp_executesql #MyQuery
select * from ##MYTempTable
Result:-
id name
1 Ahmed
2 Abdelqader
Please Try This,
CREATE PROC usp_SmootheningTable
AS
BEGIN
SELECT *, IDENTITY( int ) AS IDColumn INTO #SmootheningTable FROM
TableName
SELECT * FROM #SmootheningTable
END
GO
Please try this out
CREATE TABLE #Temp
(
Columns
)
DECLARE #SQL NVARCHAR(MAX)
DECLARE #TableName VARCHAR(MAX)
SET #TableName = 'TableName'
SET #SQL = 'SELECT TOP 10 * FROM '+#TableName
INSERT INTO #Temp
EXEC SP_EXECUTESQL #SQL
SELECT * FROM #Temp

Select all from tables where table names are from another table in SQL

I have a temp table which has a TableName column. I would like to loop through the temporary table and select everything in the the table (where table is the TableName column in the temp table).
I have been looking through the following link and related links however I am unable to adapt it to my needs. Any help is greatly appreciated.
I am using SQL Server 2014
Something which i have tried
Declare #id int
WHILE EXISTS(SELECT * FROM ##tt_tableList)
BEGIN
Select Top 1 #id = Id from ##tt_tableList
-- Do the work --
declare #query nvarchar(max)
set #query = 'Select * from (select TableName from ##tt_tablelist where id = '' +Cast(#id as nvarchar(50))+'')'
select #query
declare #tableName nvarchar(50)
set #tableName = (select TableName from ##tt_tableList where id = #id)
select #tableName
execute(#query)
-- Scrap the ID and Move On --
Delete ##tt_tableList where ID = #id
END
If I understood you correctly this is what you are asking for:
DECLARE #tbl table (TableName varchar(50))
insert into #tbl values ('SomeTableName')
insert into #tbl values ('AnotherTableName')
DECLARE #Tables VARCHAR(8000)
SELECT #Tables = COALESCE(#Tables + CHAR(13), '') + 'SELECT * FROM '+ TableName
FROM #tbl
exec(#Tables)
Just insert your table names in #tbl
I tried this based on answer from one of our fellow stack overflower and it works.
DECLARE #Tables VARCHAR(8000)
SELECT #Tables = COALESCE(#Tables + CHAR(13), '') + 'SELECT * FROM '+ TableName + ' Where Event like ''%CM_Manual_Change%'''
FROM ##tt_tableList
select #Tables
exec(#Tables)

How to insert into a table variable with a dynamic query?

I tried to develop this stored procedure using a temp table but that wouldn't work so I switched to using a table variable. I need to execute an interim dynamic query into the table variable and then I use that table variable to execute the final query. The problem is that I receive an error "must declare scalar variable #clms". I assume that Exec doesn't have scope for the table variable?
DECLARE #qry nvarchar(4000)
DECLARE #clms TABLE (mastcatname nvarchar(50),engdtlbeta decimal (18,4))
SET #qry='INSERT INTO #clms
SELECT distinct replace(mastcatname, '' '', '''') as mastcatname,
engdtlbeta
FROM vw_Scorecard
WHERE empsurveyid=' + cAST(#EmpSurveyID AS nvarchar(10)) + '
AND UnitID IN (' + #UnitIDs + ')
ORDER BY engdtlbeta desc, MastCatName'
EXEC(#qry)
DECLARE #cols nvarchar(1000)
SELECT #cols=COALESCE (#cols + ',[' + mastcatname + ']', '[' + mastcatname + ']')
FROM #clms
SET #qry='SELECT UnitName ,
ParentName, ' + #cols + '
FROM (
SELECT UnitName,
ParentName,
ScoreAvg,
replace(mastcatname, '' '','''') as mastcatname
FROM vw_Scorecard
WHERE UnitID IN (' + #UnitIDs + ')
AND EmpSurveyID=' + cast(#EmpSurveyID as nvarchar(5)) + ' ) p
PIVOT
(SUM(ScoreAvg) FOR mastcatname in (' + #cols + ')) as pvt'
EXEC (#qry)
This is simple minimal example. You can use INSERT EXEC statement. The key is to have table variable declared inside and outside dynamic query. At the end of dynamic query just select from table variable and insert resultset into outside table variable:
DECLARE #t TABLE ( id INT )
DECLARE #q NVARCHAR(MAX) = 'declare #t table(id int)
insert into #t values(1),(2)
select * from #t'
INSERT INTO #t
EXEC(#q)
SELECT * FROM #t
I found this attempting to do basically the same thing. I altered my SQL, and yes, it works! But then I thought, this is overcomplicating things. Why declare the table variable, insert, then select all in the dynamic SQL? Why not just select...
DECLARE #t TABLE ( id INT )
DECLARE #q NVARCHAR(MAX) = 'select 1 union select 2'
INSERT INTO #t
EXEC(#q)
SELECT * FROM #t

Getting output in a variable from dynamic SQL

I am using a dynamic sql i.e.
DECLARE #searchstring VARCHAR(500)
DECLARE #str VARCHAR(MAX)
SELECT #str = 'SELECT * FROM Table1 WHERE ' + #searchstring
EXECUTE #str
What I need is I want to select one column value from above dynamic sql to pass in a different SP
Let's say I need ID column value and pass it to another sp named GetAnotherData #Ids. How can I do that?
well you can go with Alexander Fedorenko example, but if you don't want to create any temp tables, you can use output xml parameter to pass your ids:
declare #stmt nvarchar(max), #Data xml, #searchstring nvarchar(max)
select #stmt = '
select #Data = (
select id
from Table1
where ' + #searchstring + '
for xml raw(''Data'')
)
'
exec sp_executesql
#stmt = #stmt,
#params = N'#Data xml output',
#Data = #Data output
select
T.C.value('#id', 'int') as id
from #Data.nodes('Data') as T(C)
sql fiddle demo
The following example creates a user-defined table type that has one Id column. Further the INSERT #RetIds EXEC(#STR) statement fills the parameter list, and then passes the values to a stored procedure
CREATE TYPE RetIds AS TABLE
(
Id int
)
DECLARE #searchstring varchar(500) = 'AND SearchCol = 1'
DECLARE #str varchar(max)
SELECT #str ='SELECT Id FROM dbo.test6 WHERE 1 = 1 ' + #searchstring
DECLARE #RetIds AS RetIds
INSERT #RetIds
EXEC(#str)
EXEC dbo.ExecIds #RetIds
See demo on SQLFiddle

using temp tables in SQL Azure

I am writing a query to pivoting table elements where column name is generated dynamically.
SET #query = N'SELECT STUDENT_ID, ROLL_NO, TITLE, STUDENT_NAME, EXAM_NAME, '+
#cols +
' INTO ##FINAL
FROM
(
SELECT *
FROM #AVERAGES
UNION
SELECT *
FROM #MARKS
UNION
SELECT *
FROM #GRACEMARKS
UNION
SELECT *
FROM #TOTAL
) p
PIVOT
(
MAX([MARKS])
FOR SUBJECT_ID IN
( '+
#cols +' )
) AS FINAL
ORDER BY STUDENT_ID ASC, DISPLAYORDER ASC, EXAM_NAME ASC;'
EXECUTE(#query)
select * from ##FINAL
This query works properly in my local database, but it doesn't work in SQL Azure since global temp tables are not allowed there.
Now if i change ##FINAL to #FINAL in my local database, but it gives me error as
Invalid object name '#FINAL' .
How can I resolve this issue?
Okay, after saying I didn't think it could be done, I might have a way. It's ugly though. Hopefully, you can play with the below sample and adapt it to your query (without having your schema and data, it's too tricky for me to attempt to write it):
declare #cols varchar(max)
set #cols = 'object_id,schema_id,parent_object_id'
--Create a temp table with the known columns
create table #Boris (
ID int IDENTITY(1,1) not null
)
--Alter the temp table to add the varying columns. Thankfully, they're all ints.
--for unknown types, varchar(max) may be more appropriate, and will hopefully convert
declare #tempcols varchar(max)
set #tempcols = #cols
while LEN(#tempcols) > 0
begin
declare #col varchar(max)
set #col = CASE WHEN CHARINDEX(',',#tempcols) > 0 THEN SUBSTRING(#tempcols,1,CHARINDEX(',',#tempcols)-1) ELSE #tempcols END
set #tempcols = CASE WHEN LEN(#col) = LEN(#tempcols) THEN '' ELSE SUBSTRING(#tempcols,LEN(#col)+2,10000000) END
declare #sql1 varchar(max)
set #sql1 = 'alter table #Boris add [' + #col + '] int null'
exec (#sql1)
end
declare #sql varchar(max)
set #sql = 'insert into #Boris (' + #cols + ') select ' + #cols + ' from sys.objects'
exec (#sql)
select * from #Boris
drop table #Boris
They key is to create the temp table in the outer scope, and then inner scopes (code running within EXEC statements) have access to the same temp table. The above worked on SQL Server 2008, but I don't have an Azure instance to play with, so not tested there.
If you create a temp table, it's visible from dynamic sql executed in your spid, if you create the table in dynamic sql, it's not visible outside of that.
There is a workaround. You can create a stub table and alter it in your dynamic sql. It requires a bit of string manipulation but I've used this technique to generate dynamic datasets for tsqlunit.
CREATE TABLE #t1
(
DummyCol int
)
EXEC(N'ALTER TABLE #t1 ADD foo INT')
EXEC ('insert into #t1(DummyCol, foo)
VALUES(1,2)')
EXEC ('ALTER TABLE #t1 DROP COLUMN DummyCol')
select *from #t1