Execute stored procedure output script - sql

I have a stored procedure that produces a script of insert statements as result.
I want to execute those statements so that I can fill the data in my table
For example :
SET NOCOUNT ON
INSERT INTO table ([UID], [Name])
VALUES ('1000002', 'name'),
('1000004', 'name2')
The stored procedure return this as result, I want to execute this script how do I do it?

If I understand correctly, the above code is printed out when the stored procedure runs.
I would start by modifying the stored procedure to take an output parameter. Stored procedures "return" integer values, not messages. They happen to print things out, but it is not good to depend on that behavior.
Then, you can simply do:
declare #str nvarchar(max);
exec <stored procedure> #str output;
exec #str;
I suspect there might be a better way to structure the code. Having stored procedures return code should only be done when you really understand what you are doing. I don't think I've ever written code where a stored procedure would return an insert statement. It seems better to run dynamic SQL in the stored procedure itself.
EDIT:
You can capture the output of the stored procedure as well:
declare #t table (id int identity, line nvarchar(max));
insert into #t(line)
exec(<stored procedure>);
Then, you can concatenate the values. You can use XML for this purpose, but I think this will work:
declare #str nvarchar(max);
set #str = '';
select #str = #str + line + ' '
from #t
order by id;
exec #str;

Thanx All of you but following is the way i should have done
USE db1;
SELECT *
INTO [table]
FROM [db2].[dbo].[table]
it helps me to copy a table

Related

Select results from stored procedure into a table

I have a stored procedure, usp_region and it has a select statement with 50 columns as the result set. This procedure is called by multiple other stored procedures in our application.
Most of the stored procedure pass a parameter to this procedure and display the result set that it returns. I have one stored procedure, usp_calculatedDisplay, that gets the columns from this stored procedure and inserts the values into a temp table and does some more calculations on the columns.
Here's a part of the code in usp_calculatedDisplay.
Begin Procedure
/* some sql statements */
Declare #tmptable
(
-- all the 50 columns that are returned from the usp_region procedure
)
Insert Into #tmptable
exec usp_region #regionId = #id
Select t.*, /* a few calculated columns here */
From #tmptable t
End of procedure
Every time I add a column to the usp_region procedure, I'll also have to make sure I have to add it to this procedure. Otherwise it breaks. It has become difficult to maintain it since it is highly possible for someone to miss adding a column to the usp_calculatedDisplay procedure when the column is added to the usp_region.
In order to overcome this problem, I decided to do this:
Select *
Into #tmptable
From OPENROWSET('SQLNCLI',
'Server=localhost;Trusted_Connection=yes;',
'EXEC [dbo].[usp_region]')
The problem is 'Ad Hoc Distributed Queries' component is turned off. So I can't use this approach to overcome this issue. I was wondering if there are any other ways of overcoming this problem. I would really appreciate any help. Thank you!
Every time I add a column to the usp_region procedure
SQL Server is a structured database and it does not meant to solve such cases that you need to change your structure every day.
If you add/remove columns so often then you probably did not choose the right type of database, and you better re-design your system.
It has become difficult to maintain it since it is highly possible for someone to miss adding a column to the usp_calculatedDisplay procedure when the column is added to the usp_region.
There are two simple solutions for this (1) using DDL Triggers - very bad idea but simple to implement and working. (2) Using my trick to select from stored procedure
Option 1: using DDL trigger
You can automate the entire procedure and ALTER the stored procedure usp_calculatedDisplay every time that the stored procedure usp_region is changed
https://learn.microsoft.com/en-us/sql/relational-databases/triggers/ddl-triggers
The basic approach is
CREATE OR ALTER TRIGGER NotGoodSolutionTrig ON DATABASE FOR ALTER_PROCEDURE AS BEGIN
DECLARE #var_xml XML = EVENTDATA();
IF(
#var_xml.value('(EVENT_INSTANCE/DatabaseName)[1]', 'sysname') = 'tempdb'
and
#var_xml.value('(EVENT_INSTANCE/SchemaName)[1]', 'sysname') = 'dbo'
and
#var_xml.value('(EVENT_INSTANCE/ObjectName)[1]', 'sysname') = 'usp_region'
)
BEGIN
-- Here you can parse the text of the stored procedure
-- and execute ALTER on the first SP
-- To make it simpler, you can design the procedure usp_region so the columns names will be in specific row or between to comment which will help us to find it
-- The code of the Stored Procedure which you need to parse is in the value of:
-- #var_xml.value('(EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'NVARCHAR(MAX)'))
-- For example we can print it
DECLARE #SP_Code NVARCHAR(MAX)
SET #SP_Code = CONVERT(NVARCHAR(MAX), #var_xml.value('(EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'NVARCHAR(MAX)'))
PRINT #SP_Code
-- In your case, you need to execute ALTER on the usp_calculatedDisplay procedure using the text from usp_region
END
END
Option 2: trick to select from stored procedure using sys.dm_exec_describe_first_result_set
This is simple and direct way to get what you need.
CREATE OR ALTER PROCEDURE usp_calculatedDisplay AS
-- Option: using simple table, so it will exists outsie the scope of the dynamic query
DROP TABLE IF EXISTS MyTable;
DECLARE #sqlCommand NVARCHAR(MAX)
select #sqlCommand = 'CREATE TABLE MyTable(' + STRING_AGG ([name] + ' ' + system_type_name, ',') + ');'
from sys.dm_exec_describe_first_result_set (N'EXEC usp_region', null,0)
PRINT #sqlCommand
EXECUTE sp_executesql #sqlCommand
INSERT MyTable EXECUTE usp_region;
SELECT * FROM MyTable;
GO
Note!!! Both solutions are not recommended in production. My advice is to avoid such needs by redesign your system. If you need to re-write 20 SP so do it and don't be lazy! Your goal should be what best for the database usage.

Alternate way to use 'INSERT tempTable EXEC storedProcedure' to get data

I have a new stored procedure that contain of following script:
Insert into #tmpTable
Exec dbo.SP_GetData '2016-11-01'
and above script causes a SQL Server error message
An INSERT EXEC statement cannot be nested.
because there is another INSERT EXEC inside the SP_GetData stored procedure and according to a few hours of reading on this error message, I can't have two INSERT EXEC or I will get that error.
I found several alternatives such as using inline query to insert into temp table and modify the existing SP_GetData stored procedure but both way can't work for me. In my case, it's a must to depend on SP_GetData as it involve many complicated process and must not be changed.
I just need to retrieve all data from the SP_GetData in my new stored procedure and return.
Please let me know what is my alternatives on this.
DECLARE #Query VARCHAR(100),#Date VARCHAR(100)
SELECT #Date = '2016-11-01'
SELECT #Query = 'dbo.SP_GetData '''+#Date+''''
INSERT INTO #tmpTable
EXEC (#Query)

SQL. Trying to create a stored procedure on SQL, but not sure if I have the right query

Create a SQL stored procedure that parses a string into previously unknown number of fields. The inputs would be
a text string of undetermined length;
a delimiter, passed as a string;
a nullable column that, if relevant, would pass the text indicator as a single character string.
The resulting table would be entirely dependent on the string used as an input
Please help because I cannot figure this out. I know this is wrong, but I had no clue where to begin.
Here is what I have tried so far:
DECLARE #l INT, #c VARCHAR(MAX) = ''
SELECT #l = MAX(LEN(n)) FROM AdventureWOrk
DECLARE #s NVARCHAR(MAX) = '
;WITH cte AS
)
Insert INTO #Values (1, 'CGID', 'EENumber', 'EEYID', 'SSN' )
SELECT
[Value],
[Value],
Prod_Attributes.value('/Attribute[1]','varchar(MAX)') AS [CGID],
Prod_Attributes.value('/Attribute[2]','varchar(MAX)') AS [EENUMBER],
Prod_Attributes.value('/Attribute[3]','varchar(MAX') AS [EYEID],
Prod_Attributes.value('/Attribute[4]','varchar(MAX') AS [SSN]
You can create a stored procedure by using the following syntax:
CREATE PROCEDURE usp_YourProcedure
AS
BEGIN
-- Your logic
END
You would put the code you already have within the BEGIN statement.
To execute the stored procedure you can do:
EXEC usp_YourProcedure
To add parameters, simply state them after the CREATE PROCEDURE declaration.
CREATE PROCEDURE usp_YourProcedure
(
#TextField VARCHAR(MAX),
#Delimeter VARCHAR(1),
#TextIndicator CHAR(1) = NULL
)
AS
BEGIN
END
Then to execute with parameters:
EXEC usp_YourProcedure 'String literal, with commas, which will, be stripped out by the delimiter', ','
Further details are outlined at MSDN.
As an additional note, try keeping your variable names descriptive and consistent, also check the casing.
CREATE PROCEDURE <ProcedureName>
-- Add the parameters for the stored procedure here
<Param1>, <Param2> ...
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
END
GO

SQL INSERT INTO calling Stored Procedure instead

I would like to do something like this in SQL
Insert Into storedproc2
SELECT column1, column2 from Tablename
My goal is to have each row of data in tablename processed using the storedproc2 stored procedure, which itself handles any insertion necessary in the logic flow.
Well as others said, you can't do that on a single statement. (that's just the way things work)
If what you wan't is to call a proc with the results you can first select and then call the proc using a cursor.
The cursor would perform a row by row code and you would be able to call the proc passing the correct values. But beware cursors are slow use Flags like FAST_FORWARD.
The other way would be to change your proc to accept a whole table, as a table valued parameter, if that is possiblel, that would perform really better.
Hope this helps.
DECLARE CallingProcCursor CURSOR
FAST_FORWARD
FOR
SELECT database_id,name from sys.databases
DECLARE #database_id int, #name sysname
OPEN CallingProcCursor
FETCH NEXT FROM CallingProcCursor INTO #database_id, #name
WHILE (##fetch_status <> -1)
BEGIN
IF (##fetch_status <> -2)
BEGIN
EXEC PROCX #database_id, #name
END
FETCH NEXT FROM CallingProcCursor INTO #database_id, #name
END
CLOSE CallingProcCursor
DEALLOCATE CallingProcCursor
GO
You can't insert into a stored procedure. You can only insert into a table (and in some cases a view, depending on the DB platform and whether the view is updateable.)
You can use a stored procedure to insert data as shown here: http://www.codeproject.com/KB/cs/tariqaziz.aspx
This is NOT meant to be insulting, but rather helpful...
It sounds like you need to go read up on stored procedures, since your question shows that you don't get the basics.
http://databases.about.com/od/sqlserver/a/storedprocedure.htm
As David said, you can't do this the way you want.
What you CAN do is feed the stored proc a table as a parameter, and have it perform it's logic on each row in that table. It will involve some Dynamic SQL but it is doable.
you can put insert statement inside stored proc and pass the values as parameters e.g.
following is just an example, on each row you can call your stored proc and it should be fine
CREATE PROC BDD_AddMessageLogItem(
#BusinessDevelopmentItemId INT,
#MessageLog NVARCHAR(MAX),
#PostedBy SMALLINT,
#PostedOfficeId TINYINT,
#PostedDepartmentId TINYINT,
#PostedMessageLogType TINYINT)
AS
BEGIN
DECLARE #BusinessDevelopmentMessageLogId SMALLINT
INSERT INTO dbo.BusinessDevelopmentItemMessageLogs
( BusinessDevelopmentItemId ,
MessageLog ,
DatePosted,
PostedBy,
PostedOfficeId,
PostedDepartmentId,
PostedMessageLogType,
BusinessDevelopmentMessageLogId
)
VALUES ( #BusinessDevelopmentItemId , -- BusinessDevelopmentItemId - int
#MessageLog , -- Message - nvarchar(100)
GETDATE(),
#PostedBy,
#PostedOfficeId,
#PostedDepartmentId,
#PostedMessageLogType,
#BusinessDevelopmentMessageLogId
)
END
You can't pass data sets to stored procedures, only parameters. You could:
Pass the table name to the stored procedure and then construct the select.
Pass the whole query as a parameter.
And then execute it with sp_executesql. If you use this method you should read The Curse and Blessings of Dynamic SQL.

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