I am just wondering if it is possible to use a variable within a stored procedure. For Example:
CASE #productType
WHEN 1 THEN
DECLARE #table = ‘products1’
WHEN 2 THEN
DECLARE #table = ‘products2’
END
SELECT * FROM #table;
Obviously this does not work, just wondering if there is a way to accomplish this.
Yes, there is a way. You can use dynamic sql.
DECLARE #productType INT = 1
DECLARE #table NVARCHAR(MAX)
DECLARE #sql NVARCHAR(MAX)
SELECT #table =
CASE #productType
WHEN 1 THEN 'products1'
WHEN 2 THEN 'products2'
END
SELECT #sql = 'SELECT * FROM ' + QUOTENAME(#table);
EXEC(#sql)
You can simply use a if else if statement :
DECLARE #productType INT = 2
IF #productType = 1
SELECT * FROM products1
ELSE IF #productType = 2
SELECT * FROM products2
Or Using sp_executesql:
DECLARE #productType INT = 1;
DECLARE #table NVARCHAR(MAX);
DECLARE #sql NVARCHAR(MAX);
SELECT #table =
CASE #productType
WHEN 1 THEN 'products1'
WHEN 2 THEN 'products2'
END;
SELECT #sql = 'SELECT * FROM ' + QUOTENAME(#table);
EXEC sp_executesql #sql;
Related
I have a piece of dynamic SQL I need to execute, I then need to store the result into a variable.
I know I can use sp_executesql but can't find clear examples around about how to do this.
If you have OUTPUT parameters you can do
DECLARE #retval int
DECLARE #sSQL nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
DECLARE #tablename nvarchar(50)
SELECT #tablename = N'products'
SELECT #sSQL = N'SELECT #retvalOUT = MAX(ID) FROM ' + #tablename;
SET #ParmDefinition = N'#retvalOUT int OUTPUT';
EXEC sp_executesql #sSQL, #ParmDefinition, #retvalOUT=#retval OUTPUT;
SELECT #retval;
But if you don't, and can not modify the SP:
-- Assuming that your SP return 1 value
create table #temptable (ID int null)
insert into #temptable exec mysp 'Value1', 'Value2'
select * from #temptable
Not pretty, but works.
DECLARE #vi INT
DECLARE #vQuery NVARCHAR(1000)
SET #vQuery = N'SELECT #vi= COUNT(*) FROM <TableName>'
EXEC SP_EXECUTESQL
#Query = #vQuery
, #Params = N'#vi INT OUTPUT'
, #vi = #vi OUTPUT
SELECT #vi
DECLARE #tab AS TABLE (col1 VARCHAR(10), col2 varchar(10))
INSERT into #tab EXECUTE sp_executesql N'
SELECT 1 AS col1, 2 AS col2
UNION ALL
SELECT 1 AS col1, 2 AS col2
UNION ALL
SELECT 1 AS col1, 2 AS col2'
SELECT * FROM #tab
Return values are generally not used to "return" a result but to return success (0) or an error number (1-65K). The above all seem to indicate that sp_executesql does not return a value, which is not correct. sp_executesql will return 0 for success and any other number for failure.
In the below, #i will return 2727
DECLARE #s NVARCHAR(500)
DECLARE #i INT;
SET #s = 'USE [Blah]; UPDATE STATISTICS [dbo].[TableName] [NonExistantStatisticsName];';
EXEC #i = sys.sp_executesql #s
SELECT #i AS 'Blah'
SSMS will show this
Msg 2727, Level 11, State 1, Line 1
Cannot find index 'NonExistantStaticsName'.
If you want to return more than 1 value use this:
DECLARE #sqlstatement2 NVARCHAR(MAX);
DECLARE #retText NVARCHAR(MAX);
DECLARE #ParmDefinition NVARCHAR(MAX);
DECLARE #retIndex INT = 0;
SELECT #sqlstatement = 'SELECT #retIndexOUT=column1 #retTextOUT=column2 FROM XXX WHERE bla bla';
SET #ParmDefinition = N'#retIndexOUT INT OUTPUT, #retTextOUT NVARCHAR(MAX) OUTPUT';
exec sp_executesql #sqlstatement, #ParmDefinition, #retIndexOUT=#retIndex OUTPUT, #retTextOUT=#retText OUTPUT;
returned values are in #retIndex and #retText
Declare #variable int
Exec #variable = proc_name
DECLARE #ValueTable TABLE
(
Value VARCHAR (100)
)
SELECT #sql = N'SELECT SRS_SizeSetDetails.'+#COLUMN_NAME+' FROM SRS_SizeSetDetails WHERE FSizeID = '''+#FSizeID+''' AND SRS_SizeSetID = '''+#SRS_SizeSetID+'''';
INSERT INTO #ValueTable
EXEC sp_executesql #sql;
SET #Value='';
SET #Value = (SELECT TOP 1 Value FROM #ValueTable)
DELETE FROM #ValueTable
This worked for me:
DECLARE #SQL NVARCHAR(4000)
DECLARE #tbl Table (
Id int,
Account varchar(50),
Amount int
)
-- Lots of code to Create my dynamic sql statement
insert into #tbl EXEC sp_executesql #SQL
select * from #tbl
Here's something you can try
DECLARE #SqlStatement NVARCHAR(MAX) = ''
,#result XML
,#DatabaseName VARCHAR(100)
,#SchemaName VARCHAR(10)
,#ObjectName VARCHAR(200);
SELECT #DatabaseName = 'some database'
,#SchemaName = 'some schema'
,#ObjectName = 'some object (Table/View)'
SET #SqlStatement = '
SELECT #result = CONVERT(XML,
STUFF( ( SELECT *
FROM
(
SELECT TOP(100)
*
FROM ' + QUOTENAME(#DatabaseName) +'.'+ QUOTENAME(#SchemaName) +'.' + QUOTENAME(#ObjectName) + '
) AS A1
FOR XML PATH(''row''), ELEMENTS, ROOT(''recordset'')
), 1, 0, '''')
)
';
EXEC sp_executesql #SqlStatement,N'#result XML OUTPUT', #result = #result OUTPUT;
SELECT DISTINCT
QUOTENAME(r.value('fn:local-name(.)', 'VARCHAR(200)')) AS ColumnName
FROM #result.nodes('//recordset/*/*') AS records(r)
ORDER BY ColumnName
This was a long time ago, so not sure if this is still needed, but you could use ##ROWCOUNT variable to see how many rows were affected with the previous sql statement.
This is helpful when for example you construct a dynamic Update statement and run it with exec. ##ROWCOUNT would show how many rows were updated.
Here is the definition
I have table like this:
Table Name|Number of columns
How to dynamically create temporary tables inside stored procedure with names from first table, and variable columns named e.g. col1, col2, etc..
I also need to insert values to them and make another logic on them.
Example:
Table1|3
Table1(col1 nvarchar(max), col2 nvarchar(max), col3 nvarchar(max))
You will need to use dynamic sql like below:
declare #counter int = 1
declare #numberOfCols int = 3 -- OR you can use ->(select numberofcolumns from firsttable)
declare #dynamic nvarchar(max) = ''
declare #sql nvarchar(max) = 'CREATE TABLE #TEMP (';
while #counter <= #numberofCols
begin
set #dynamic = #dynamic + 'col'+cast(#counter as nvarchar(5))+' nvarchar(max) ';
if(#counter <> #numberOfCols)
begin
set #dynamic = #dynamic + ', ';
end
set #counter = #counter + 1
end
set #sql = #sql + #dynamic + ') select * from #temp'
select #sql
EXECUTE sp_executesql #sql
I have created a stored procedure regarding your question. I wish it can help you.
ALTER PROCEDURE P_ProcedureName
#NumberOfColumns INT=2 --expected 1 or more column
AS
DECLARE #SQLString VARCHAR(MAX)=''
DECLARE #Seq INT=2
IF #NumberOfColumns=0
BEGIN
SELECT 'Please add valid number of column'
RETURN
END
CREATE TABLE #Table
(
Id INT NOT NULL IDENTITY(1,1)
,Column1 VARCHAR(MAX)
)
WHILE #Seq<=#NumberOfColumns
BEGIN
SET #SQLString=#SQLString+'ALTER TABLE #Table ADD Column'+CAST(#Seq AS VARCHAR)+' VARCHAR(MAX)'+char(13)
PRINT(#SQLString)
SET #Seq +=1
END
EXEC(#SQLString)
SELECT * FROM #Table
GO
P_ProcedureName 5
Is it possible to print the Dynamic select statement after passing the parameters values.When i print the SELECT #SQL.It is giving only select statement without parameter values.In my below procedure the dynamic select statement not giving correct output after passing the parameters.But when i directly passing the the parameter values into the select statement it is giving correct output.In my below procedure splitting function is working fine.Else part in
if statement is not working properly.
CREATE TYPE TableVariable AS TABLE
(
id int identity(1,1),
field_ids INT,
value VARCHAR(MAX)
)
Alter PROCEDURE Testing
(
#TableVar TableVariable READONLY,
#Catalog_id INT
)
AS
Declare #maxPK INT
Declare #pk INT
Declare #fid INT
Declare #is_List SMALLINT
Declare #val VARCHAR(MAX)
Declare #field_Type VARCHAR(50)
Declare #Where VARCHAR(MAX)
Declare #SQL NVARCHAR(MAX);
Set #pk = 1
BEGIN
BEGIN TRY
SET NOCOUNT ON;
Select #maxPK = count(*) From #TableVar
SELECT #Catalog_id
Set #SQL = 'SELECT DISTINCT v1.entity_id from values v1 inner join listings l ON v1.entity_id = l.entity_id WHERE l.c_id=#Catalog_id'
While #pk <= #maxPK
BEGIN
SELECT #fid= field_ids FROM #TableVar where id=#pk;
SELECT #val= value FROM #TableVar where id=#pk;
SELECT #field_Type=type,#is_List=is_list FROM FIELD WHERE ID=#fid
IF (#is_List = 0)
BEGIN
SET #SQL += ' and exists (select 1 from values v'+convert(varchar(15),#pk+1)+' where v1.entity_id = v'+convert(varchar(15),#pk+1)+'.entity_id and v'+convert(varchar(15),#pk+1)+'.field_id=#fid and(value IN(SELECT val FROM spliting(#val,'',''))))'
SELECT #fid
END
else IF (#is_List = 1 OR #field_Type = 'xy')
BEGIN
SET #SQL += ' and exists (select 1 from values v'+convert(varchar(15),#pk+1)+' where v1.entity_id = v'+convert(varchar(15),#pk+1)+'.entity_id and v'+convert(varchar(15),#pk+1)+'.field_id=#fid and(value in(#val)))'
SELECT #fid
END
Select #pk = #pk + 1
END
EXECUTE SP_EXECUTESQL #SQL, N'#Catalog_id int,#fid int,#val varchar(max)',#Catalog_id=#Catalog_id,#fid=#fid,#val=#val
SELECT #SQL
END TRY
BEGIN CATCH
END CATCH
END
DECLARE #DepartmentTVP AS TableVariable;
insert into #DepartmentTVP values(1780,'Smooth As Silk Deep Moisture Shampoo,Smooth As Silk Deeper Moisture Conditioner')
--insert into #DepartmentTVP values(1780,'Smooth As Silk Deeper Moisture Conditioner')
insert into #DepartmentTVP values(1782,'037-05-1129')
insert into #DepartmentTVP values(2320,'["fairtrade","usda_organic","non_gmo_verified"]')
SELECT * FROM #DepartmentTVP
EXEC Testing #DepartmentTVP,583
Yes right before the statment:
EXECUTE SP_EXECUTESQL #SQL, N'#Catalog_id int,#fid int,#val varchar(max)',#Catalog_id=#Catalog_id,#fid=#fid,#val=#val
type:
print #SQL
I want get the value from Exec(#sql) and assign to #Rowcount(int)
Here is my query:
'SET #RowCount = (select count(*)
FROM dbo.Comm_Services
WHERE CompanyId = '+cast(#CompanyId as char)+' and '+#condition+')'
On the one hand you could use sp_executesql:
exec sp_executesql N'select #rowcount=count(*) from anytable',
N'#rowcount int output', #rowcount output;
On the other hand you could use a temporary table:
declare #result table ([rowcount] int);
insert into #result ([rowcount])
exec (N'select count(*) from anytable');
declare #rowcount int = (select top (1) [rowcount] from #result);
DECLARE #nReturn int = 0
EXEC #nReturn = Stored Procedure
Was playing with this today... I believe you can also use ##ROWCOUNT, like this:
DECLARE #SQL VARCHAR(50)
DECLARE #Rowcount INT
SET #SQL = 'SELECT 1 UNION SELECT 2'
EXEC(#SQL)
SET #Rowcount = ##ROWCOUNT
SELECT #Rowcount
Then replace the SELECT 1 UNION SELECT 2 with your actual select without the count. I'd suggest just putting 1 in your select, like this:
SELECT 1
FROM dbo.Comm_Services
WHERE....
....
(as opposed to putting SELECT *)
Hope that helps.
that's my procedure
CREATE PROC sp_count
#CompanyId sysname,
#codition sysname
AS
SET NOCOUNT ON
CREATE TABLE #ctr
( NumRows int )
DECLARE #intCount int
, #vcSQL varchar(255)
SELECT #vcSQL = ' INSERT #ctr FROM dbo.Comm_Services
WHERE CompanyId = '+#CompanyId+' and '+#condition+')'
EXEC (#vcSQL)
IF ##ERROR = 0
BEGIN
SELECT #intCount = NumRows
FROM #ctr
DROP TABLE #ctr
RETURN #intCount
END
ELSE
BEGIN
DROP TABLE #ctr
RETURN -1
END
GO
If i understand you correctly, (i probably don't)
'SELECT #RowCount = COUNT(*)
FROM dbo.Comm_Services
WHERE CompanyId = ' + CAST(#CompanyId AS CHAR) + '
AND ' + #condition
It is possible to write a generic function/procedure/select/somethingElse to cross-join a table against himself 'n' times? (yes, 'n' is a given parameter : )
How would you do it?
Example
Having this table:
Value
-------
1
2
3
cross join it 2 times, would return:
Value | Value
------------------
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Using dynamic SQL, SQL Server 2005+ (#table_name and #numCrossJoins are stored procedure parameters):
DECLARE #upperLimit INT
SET #upperLimit = 1
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = 'SELECT * FROM '+ #table_name +' '
BEGIN
WHILE (upperLimit <= #numCrossJoins)
BEGIN
SET #SQL = #SQL + 'CROSS JOIN '+ QUOTENAME(#table_name) +' '
SET #upperLimit = #upperLimit + 1
END
EXEC sp_executesql #SQL
END
You can generate dynamic sql to output as many cross joins as you need:
create table #t (value int)
insert into #t values (1)
insert into #t values (2)
insert into #t values (3)
declare #n int
set #n = 4
declare #sql varchar(max)
set #sql = 'SELECT * FROM #t t'
declare #i int
set #i = 0
while (#i <= #n)
begin
set #sql = #sql + ' cross join #t t' + CAST(#i as varchar)
set #i = #i + 1
end
print #sql
execute(#sql)
drop table #t
Try this:
SET #SQL = 'SELECT * FROM ' + replicate('[' + #table_name + '],', #N);
set #SQL = LEFT(LEN(#SQL) - 1);
EXEC sp_executesql #SQL;
If you need to come up with all possible permutations, here is an example:
All Permutations For A String