Inserting into a user-defined table type via a dynamic query in SQL Server? - sql

I have a user-defined table type tyAnalysisNumbers. I need to populate my user defined data type within a stored procedure with a SELECT statement and I am struggling to get that working within my stored procedure.
The following ways I have tried do not work
DECLARE #MyTable tyAnalysisNumbers;
INSERT INTO #MyTable
EXEC ('SELECT * FROM ' + #someTable);
I get this error:
An INSERT EXEC statement cannot be nested
I am unsure how to insert into my custom table via a select statement.
Can anyone help me accomplish this?

An INSERT EXEC statement cannot be nested
Above error is self explanatory. Please look at below scenario:
For example, we have one procedure which inserts data in table type and return result.
CREATE PROCEDURE uspInsertData1
AS
BEGIN
DECLARE #MyTable tyAnalysisNumbers;
INSERT INTO #MyTable
EXEC ('SELECT * FROM someTable');
select * from #MyTable
END
Now, let's say we have another procedure which will call above procedure and again insert data in another table.
CREATE PROCEDURE uspInsertData2
AS
BEGIN
DECLARE #MyTable tyAnalysisNumbers;
INSERT INTO sometable
EXEC uspInsertData1
END
Now, if you execute 1st procedure it will work fine but if you execute second procedure you will get this error.
An INSERT EXEC statement cannot be nested.
Because now you have nested EXEC statements.
I suggest to finish your work in single stored procedure if possible.

Try it like this:
DECLARE #MyTable tyAnalysisNumbers;
SELECT * INTO #Temp FROM #MyTable;
DECLARE #tblName AS SYSNAME = (SELECT name FROM sys.tables WHERE name = #someTable);
EXEC ('INSERT INTO #Temp SELECT * FROM ' + #tblName);
This also addresses the SQL Injection problem.

Related

Getting query result into table variable

So I have declared a query within a varchar variable like:
DECLARE #sql VARCHAR(MAX) = 'select * from table'
I've also declared a temp table #Results that matches the column structure of the query.
I then call:
INSERT INTO #Results
EXEC (#sql)
The error I get is:
An INSERT EXEC statement cannot be nested.
I would also like to add that the query executes fine without the part
INSERT INTO #Results
What could be causing it? Any tips will be greatly appreciated
You can't stack together more than 1 INSERT INTO + EXEC, this is a limitation from SQL Server.
DECLARE #Test TABLE (Number INT)
INSERT INTO #Test (Number)
EXEC ('
CREATE TABLE #InnerTable (SomeColumn INT);
INSERT INTO #InnerTable (SomeColumn)
EXEC (''SELECT 1'');
SELECT 1;')
Msg 8164, Level 16, State 1, Line 4 An INSERT EXEC statement cannot be
nested.
If we remove the inner INSERT INTO + EXEC...
DECLARE #Test TABLE (Number INT)
INSERT INTO #Test (Number)
EXEC ('
CREATE TABLE #InnerTable (SomeColumn INT);
SELECT 1;')
Succeed!
There are multiple ways to workaround this limitation, however most of them will require modifying the EXEC content. You can find an exhaustive explanation here. The one I usually use with my procedures is sharing a temporary table. You need to create a temporary table outside the EXEC then load it inside. The table is still accessible outside the EXEC scope because it was created outside.
IF OBJECT_ID('tempdb..#Test') IS NOT NULL
DROP TABLE #Test
CREATE TABLE #Test (Number INT)
EXEC ('INSERT INTO #Test (Number) SELECT 1')
SELECT * FROM #Test
Downside of this approach is that the EXEC part might fail if the temporary table wasn't created or it was created with wrong column names or data types. Keep in mind that this won't work with variable tables, they need to be temporary (at least) to be accessible inside the EXEC scope.

Insert result of EXEC into table parameter

In a stored procedure, I have an EXEC statement; I want to store its results into a table.
First I create table parameter as:
DECLARE #MyTable AS TABLE
(
[Item1] INT,
[Item2] DECIMAL
)
Then I try to insert values as:
INSERT INTO #MyTable
EXEC [storedProcedure] #testitem = #testitem
My question: is this the right way to do that? Or do I need to use a dynamic query?
Because I read similar questions like this and they suggest to use a dynamic query.
You have to use a dynamic query.
DECLARE #Sql AS VARCHAR(MAX);
SET #Sql='EXEC storedProcedure #testitem = #testitem'
INSERT INTO #MyTable ([Item1], [Item2]) EXEC(#Sql)
SELECT * FROM #MyTable;
Asserting the above, I've been just tempted to read further... and found this older thread. I bet, it is helpful to analyze it further. Insert results of a stored procedure into a temporary table

Insert sql query result inside stored procedure in temp table

I have stored procedure in which i store whole query inside string and then execute that. Now i want to store that execute result into temporary table for further processing.
Something like below :
Exec #Mainsql -- this returns me query result and i need to insert its result to temp table
I tried something like this:
Select * Into #TempTable
From
Exec #MainSQL
But It is lacking in syntax i guess.
So, i need result of mainsql into temptable
Try this:
CREATE TABLE #TempTable AS
Exec #MainSQL
You must create Temp Table first, You have to define all columns which will be returned from procedure, if you need to insert data using Stored Procedure:
CREATE TABLE #TempTable (Col1 INT, Col2 VARCHAR(10))
INSERT INTO #TempTable
EXEC [ProcedureName]
Another option is to use OPENROWSET, if you do not know returned columns :
SELECT * INTO #TempTable
FROM OPENROWSET('SQLNCLI', 'Server=.;Trusted_Connection=yes;', 'EXEC DBName.Schema.ProcedureName')

How do I combine result sets from two stored procedure calls?

I have a following stored procedure
CREATE PROCEDURE [dbo].[MyStored]
#state int
AS
SELECT blahblahblah WHERE StoredState=#state LotsOfJoinsFollow;
RETURN 0
and I'd like to call that stored procedure with #state being 0 and 1 and have the result sets returned by both calls combined with UNION semantics so that I have a new resultset that has rows from both the first call and the second call.
Something like (imaginary SQL):
(EXEC MyStored 0) UNION (EXEC MyStored 1);
How do I achieve that?
This may be oversimplifying the problem, but if you have control over the sp, just use in rather than =:
CREATE PROCEDURE [dbo].[MyStored]
AS
SELECT blahblahblah WHERE StoredState IN (0,1) LotsOfJoinsFollow;
RETURN 0
If this is not an option, just push the results of both sproc calls into a temp table:
/*Create a table with the same columns that the sproc returns*/
CREATE TABLE #tempblahblah(blahblahblah NVARCHAR(50))
INSERT #tempblahblah ( blahblahblah )
EXEC MyStored 0
INSERT #tempblahblah ( blahblahblah )
EXEC MyStored 1
SELECT * FROM #tempblahblah
create table #table (
.....
)
insert into #table exec MyStored 0
insert into #table exec MyStored 1
select * from #table
drop table #table
Alternatively to a series of statements like these:
INSERT INTO #YourTempTable
EXEC MyStored 0;
INSERT INTO #YourTempTable
EXEC MyStored 1;
you could use one INSERT ... EXEC statement like below:
INSERT INTO #YourTempTable
EXEC ('
EXEC MyStored 0;
EXEC MyStored 1;
');
The results of the two calls to MyStored would be UNIONed (or, rather, UNION ALLed), just like with the former method.
A long way would be to create a wrapper that does this - a function that takes a list of states and adds them to a final table that would be returned.
You could also have whatever technology is calling this procedure do the concatination of records (i.e. having .NET append the result set of each state you are looking into)
If you're fine with passing in a list of states to your 'state' param, you could create a dynamic sql query
CREATE PROCEDURE [dbo].[MyStored]
#state nvarchar(150)
AS
-- #state needs to be pre-formatted in a list for an in-clause
-- i.e. 1,2,10 (if it was a string list, you'd need to do use double single quotes around the items - ''1'',''2'',''10''
DECLARE #SQL nVarChar(5000) = '
SELECT blahblahblah
FROM LotsOfJoins
WHERE StoredState in (' + #state + ')'
exec sp_executeSql #sql
This works great for simple procedures; although, it can get take longer to maintain if changes are needed down the road.
.
Here is a CodeProject Article and a MS SQL Tips Article that does a better job going into details
.
EDIT: The param #state will need to be a nVarChar since your passing in a comma delimited list of int values
If the stored procedure you are calling has a temp table with the same name as one in the calling procedure you will get this error.
e.g. sp1 has temp table #results
sp2 create table #results(fields)
then trying to insert into #results in sp2 the result of calling sp1 would fail with this error. change temp table in sp2 to #result and try again and you should see this now works.

How to query from a stored procedure in SQL Server?

Let say I have a simple Stored Procedure:
ALTER PROCEDURE [dbo].[myProc]
AS
BEGIN
SELECT * FROM myTable
END
How can I do a WHERE statement in Microsoft SQL Server Management Studio to the stored procedure? Something like that:
SELECT * FROM myProc WHERE x = 'a'; -- But that doesn't work...
It sounds like you're trying to make a "dynamic" stored procedure.
Something you might want to do is:
1) Insert the contents of your stored procedure into a temporary table
2) Use dynamic sql to apply a where condition to that temporary table.
Something like:
declare #as_condition varchar(500); --Your condition
create table #a
(
id bigint
)
insert into #a
execute sproc
declare #ls_sql varchar(max);
set #ls_sql = "select * from #a where " + #as_condition;
execute (#ls_sql);
SQL Server allows you to use INSERT INTO to grab a stored procedure's output. For example, to grab all processes with SPID < 10, use:
create table #sp_who (
spid smallint,
ecid smallint,
status nchar(30),
loginame nchar(128),
hostname nchar(128),
blk char(5),
dbname nchar(128),
cmd nchar(16),
request int)
insert into #sp_who execute sp_who
select * from #sp_who where spid < 10
You can't add a WHERE clause to a stored procedure like this.
You should put the clause in the sproc, like this:
ALTER PROCEDURE [dbo].[myProc]
#X VARCHAR(10)
AS
BEGIN
SELECT * FROM myTable WHERE x=#X
END
GO
The syntax for calling a stored procedure is through the use of EXECUTE not SELECT(e.g.):
EXECUTE dbo.myProc 'a'
I think you can't do that.
The command to execute a stored procedure is EXECUTE.
See some more examples of the EXECUTE usage.
I think its better to use a view or a table valued function rather than the suggested approach. Both allow you to pass parameters to the function
If you want the WHERE clause to be something you can "turn off" you can do this, passing in a predetermined value (e.g. -1) if the WHERE limitation is to be bypassed:
ALTER PROCEDURE [dbo].[myProc]
#X VARCHAR(10)
AS
BEGIN
SELECT * FROM myTable WHERE x=#X or #X = -1
END
GO
You must declare a variable in the store procedure which will be necessary to pass to run the stored procedure. Here is an example. Keep this in mind: Before AS you can simply declare any variable by using the # character, but after the AS you must write Declare to declare any variable, e.g., Declare #name nvarchar (50).
ALTER PROCEDURE [dbo].[myProc]
#name varchar (50)
AS
BEGIN
SELECT * FROM myTable
where name= #name
END