stored procedure an insert exec statement cannot be nested - sql

I have the following stored procedure which calls another stored procedure dbo.[spGetResult]
;WITH CTE
AS
(
SELECT 0 AS [Level],PNLId , PNLParentId, PNLName
FROM [dbo].[DimPNL]
WHERE PNLParentId IS NULL
UNION ALL
SELECT CTE.[Level] + 1 ,T1.PNLId,T1.PNLParentId,T1.PNLName
FROM [dbo].[DimPNL] AS T1
INNER JOIN CTE
ON T1.PNLParentId = CTE.PNLId
)
-- order the results into a #temp table
SELECT *
INTO ##temp
FROM CTE
ORDER BY level desc
DECLARE #PNLName As varchar(MAX)
DECLARE db_cursor CURSOR FOR
SELECT PNLName
FROM ##temp
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #PNLName
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO dbo.[test1]//from here I have a problem
Exec dbo.[spGetResult] #PNLName
FETCH NEXT FROM db_cursor INTO #PNLName
END
CLOSE db_cursor
DEALLOCATE db_cursor
I always get
stored procedure an insert exec statement cannot be nested
I have a look here But I didn't understand very much how to resolve the problem ?

Your best bet is to rewrite the stored procedure to a table function. Performance-wise an inline function works best, but it's usually more difficult to functionally rewrite a procedure like this.
Most stored procs can easily be rewritten to a table valued function though.
Take a look here for more info: http://technet.microsoft.com/en-us/library/ms187650(v=sql.105).aspx
Once you've rewritten it, you can nest the insert into/select statements.
INSERT INTO [TABLE] (col1, col2, ...) SELECT tvfcol1, tvfcol2, ...
from dbo.func_TVF_blabla(#param1, #param2, ...)

Related

Use table columns in Exec stored procedure command SQL Server

I have a command:
exec [Database].[dbo].DepartmentChangeLevel , Department, Date, Level;
I currently specify the values manually and explicitly like this:
exec [Database].[dbo].DepartmentChangeLevel , 'Catering', '20180101 08:01:00', 3;
However, I want to run the same command and use values from a table - like this:
exec [Database].[dbo].DepartmentChangeLevel
select
[Department], [Date], [Level]
from
[Database].[dbo].[DepartmentChange]
The error message I get is
Expects parameter #department which is not supplied
Please help
You can use a Cursor instead:
Create a Cursor on your table and pass all three columns into three variables
and execute proc in the cursor.
Example :
declare db_cursor cursor
for select
[Department], [Date], [Level]
from
[Database].[dbo].[DepartmentChange];
declare #department int --your column data type
,#date datetime --your column data type
,#level varchar(10) --your column data type
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #department, #date, #level;
WHILE ##FETCH_STATUS = 0
BEGIN
exec [Database].[dbo].DepartmentChangeLevel #department, #date, #level;
DELETE FROM [Database].[dbo].DepartmentChangeLevel ---or you can store values from DepartmentChangeLevel table into temporary table then delete those values from temporary table
WHERE [Department]=#department
and [Date]=#date
and [Level]=#level
FETCH NEXT FROM db_cursor INTO #department,#date, #level
END
CLOSE db_cursor;
DEALLOCATE db_cursor;

How to insert records in a existing table using Cursor

Declare Userrole_Cursor Cursor For
Select (User_Role_id,
Pos_entity_Id,
User_role_code,
User_Role_description,
Print_Sequence,
Update_date,
Tx_id,
Add_date,
Add_Username,
Update_Username,
Active_Flag) from User_Role_Tb where pos_entity_id = (pos_entity_id)
Open Cursor
FETCH NEXT FROM UserRole_Cursor into
the above is the Cursor creation i have written, now need to insert in all the mentioned columns in a User_role_tb. please help. this is the first time i am using cursor.
This simple example can help you
-- assume this is your table
create table #tmp (MyDbName varchar(100), MyDbId int, MyStatus int)
-- you need to have a variable for each field.
DECLARE #MyDbName varchar(100)
DECLARE #MyDbId int
DECLARE #MyDbStatus int
DECLARE db_cursor CURSOR FOR
SELECT name, [dbid], [status]
FROM master.dbo.sysdatabases
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #MyDbName, #MyDbId, #MyDbStatus
WHILE ##FETCH_STATUS = 0
BEGIN
-- insert data into your table using variables
insert into #tmp (MyDbName, MyDbId, MyStatus)
values (#MyDbName, #MyDbId, #MyDbStatus)
-- fetch next row from cursor
FETCH NEXT FROM db_cursor INTO #MyDbName, #MyDbId, #MyDbStatus
END
CLOSE db_cursor
DEALLOCATE db_cursor
-- select from your table to make sure data is there
select * from #tmp

need to assign values from sql query in single instance

I am executing the below query in sql-server-2008-R2 which gives me output as I wanted(i.e, number of rows) but, I want to store the result in form of a multi-columned row(s) in a variable.
declare #rCount int
declare #kuri nvarchar(max)
declare #IDs nvarchar(max)
select #rCount=10
set #kuri='select top '+cast(#rCount as varchar)+' FLD295,FLD9 from tableName (nolock) ORDER BY NEWID()'
execute(#kuri)
I had done this earlier but it was different query where I need to concatenate the result of both the queries in to one column (assigning and display)
select #IDs=CAST(isnull(#IDs ,'')as varchar)+CAST(COALESCE(fld9,',')as varchar) from table1307 (nolock) ORDER BY NEWID()
DECLARE #T1 TABLE (
FLD9 bigint
, FLD295 nVARCHAR(max)
)
insert into #T1(,FLD295,FLD9)
select top(#rCount) FLD295,FLD9 from tableName (nolock)
ORDER BY NEWID()
select * from #T1
select #IDs=CAST(isnull(#IDs ,'')as varchar)+CAST(COALESCE(fld9,',')as varchar) from #T1
I think you're missing the face that you can do
declare #i int=3
select top(#i) .... –
2008 does support dynamic top
I hope you know that result should be single. , otherwise , it can't be possible (unless you're doing insert into...
if you're asking about how to concatenate ( cte is jsut table , ignore it)
You can use cursor for access result set:
declare #rCount int
declare #kuri nvarchar(max)
declare #IDs nvarchar(max)
declare #FLD295 int
declare #FLD9 int
select #rCount=10
set #kuri='declare cursor curs for select top '+cast(#rCount as varchar)+' FLD295,FLD9 from tableName (nolock) ORDER BY NEWID()'
exec sp_executesql #kuri
open curs
fetch from curs
into #FLD295, #FLD9
while ##fetch_status = 0
BEGIn
fetch from curs
into #FLD295, #FLD9
END
close curs
deallocate curs

Append result of stored procedure to earlier executed stored procedure

I have a stored procedure which takes a single parameter containing single value.
I want to pass a collection of values to the procedure one by one and get the combined result into one table . Is this possible ?
Currently I am using cursor to execute procedure in loop but only result from passing first value in the collection is obtained.
declare #clientid varchar(10)
create table #tmpp(secid varchar(10))
insert into #tmpp values(2319)
insert into #tmpp values(2855)
insert into #tmpp values(1303)
declare cur CURSOR LOCAL for
select secid from #tmpp
open cur
fetch next from cur into #seclientid
while ##FETCH_STATUS = 0 BEGIN
exec getReportforclient #clientid
fetch next from cur into #clientid
END
close cur
deallocate cur
drop table #tmpp
If this is too obfuscated / unclear/ silly, can somebody please provide me an alternative ?
Any help is most appreciated . Thanks.
There probably is a way to this without using cursors, but without taking a look at your stored procedure we can't help too much on that. You can create a table (temporary or not) that has the same structure that the results of your sp and insert the results into it. Something like this:
DECLARE #clientid VARCHAR(10)
CREATE TABLE #tmpp(secid VARCHAR(10))
INSERT INTO #tmpp VALUES(2319)
INSERT INTO #tmpp VALUES(2855)
INSERT INTO #tmpp VALUES(1303)
CREATE TABLE #Results(col1 INT, col2.... -- create the table that will hold your
-- results
DECLARE cur CURSOR LOCAL for
SELECT secid
FROM #tmpp
OPEN cur
FETCH NEXT FROM cur INTO #seclientid
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #Results
exec getReportforclient #clientid
FETCH NEXT FROM cur INTO #clientid
END
CLOSE cur
DEALLOCATE cur
DROP TABLE #tmpp
SELECT *
FROM #Results
Loop without CURSOR
IF OBJECT_ID('tempdb.dbo.#tmpp') IS NOT NULL DROP TABLE #tmpp
CREATE TABLE #tmpp(Clientid varchar(10))
INSERT #tmpp values(2319), (2855), (1303)
IF OBJECT_ID('tempdb.dbo.#Results') IS NOT NULL DROP TABLE #Results
CREATE TABLE #Results(--output columns of procedure)
DECLARE #Clientid int = (SELECT MIN(Clientid) FROM #tmpp)
WHILE (#Clientid IS NOT NULL)
BEGIN
INSERT INTO #Results
EXEC getReportforclient #Clientid
SELECT #Clientid = MIN(Clientid) FROM #tmpp WHERE Clientid > #Clientid
END
Simple example on SQLFiddle

Using EXEC inside SELECT statement in SQL Server

I need to use exec inside of select clause. The query for the exec is created according to the columns of the table to on which select clause if used. What i want to do is something like following:
SELECT distinct
MTMain.[TableName],
MTMain.[TableFKey],
(select IsActive (exec GetStringForIsActive MTMain.[TableName],MTMain.[TableFKey]))
FROM
[MasterTableForLanguage] MTMain
Here, GetStringForIsActive is the stored procedure I want to execute for every row selected from MasterTableForLanguage.
The stored procedure will use EXEC to execute the following string
select IsActive from [TableName] where PKID= cast([TableFKey] as int)
TableName and TableFKey will be inputs of the stored procedure.
If you can modify your Stored Procedure GetStringForIsActive to return TableName, TableFKey and IsActive, you can use a cursor to get execute it for each row and add the results to a temp table.
ie:
exec GetStringForIsActive 'TableName', 'TableFKey'
returns
select [TableName], [TableFKey], IsActive from [TableName] where PKID= cast([TableFKey] as int)
The code would be like this:
declare #TableName nvarchar(50)
declare #TableFKey nvarchar(50)
declare #Results table (TableName nvarchar(50), TableFKey nvarchar(50), IsActive bit)
declare TableCursor cursor fast_forward for
select TableName, TableFKey from MasterTableForLanguage
open TableCursor
fetch next from TableCursor into #TableName, #TableFKey
if ##FETCH_STATUS <> -1
print 'MasterTableForLanguage check'
while (##FETCH_STATUS <> -1)
begin
insert into #Results
exec GetStringForIsActive #TableName, #TableFKey
fetch next from TableCursor into #TableName, #TableFKey
end
close TaleCursor
deallocate TableCursor
select * from #Results
use Functions instead of Stored procedures in SELECT clause.
Edited:
create that function
CREATE FUNCTION function1 (#TableName nvarchar(10),#TableFKey nvarchar(10))
RETURNS nvarchar(100) AS
BEGIN
-- do whatever here
END
then
SELECT distinct
MTMain.[TableName],
MTMain.[TableFKey],
function1(MTMain.[TableName],MTMain.[TableFKey])
FROM
[MasterTableForLanguage] MTMain
Does this make sense?
Well, I think to answer the full question, I don't believe a stored procedure would EXEC a SELECT statement, it would simply perform the SELECT.
You EXEC your current proc and pass it vars, and it returns a value BASED ON the select statement it runs. It's not EXEC'ing that statement, simply performing a select. I have several stored procs I use daily in some SQL agent processes, they all perform selects to query various tables, and none of them call an EXEC to perform those actions. This is my own example:
CREATE PROCEDURE [myproc]
#job_ident INT
AS
BEGIN
SET NOCOUNT ON;
...
SELECT TOP(1) #filter_type = filter_type FROM [place] WHERE [ident] = #job_ident
...
END
As mentioned previously, the most effective way to perform your query would be to perform that select inside a function, something similar to this I think will do:
CREATE FUNCTION ThisFunction (
#TableName nvarchar(10),
#TableFKey nvarchar(10)
)
RETURNS nvarchar(100)
AS
BEGIN
RETURN
(
select IsActive from [TableName] where PKID= cast([TableFKey] as int)
)
END
You could then do exactly as you want...
SELECT distinct
MTMain.[TableName],
MTMain.[TableFKey],
ThisFunction(MTMain.[TableName],MTMain.[TableFKey])
FROM
[MasterTableForLanguage] MTMain