Here's a issue I have with a stored procedure (using SQL Server 2005), inside this stored procedure it calls another stored procedure putting the data into a temp table.
INSERT INTO #tmpTable (Column1, Column2, Column3)
EXEC psp_rptInsideStoredprocedure 2
This inside stored procedure has a mode parameter that determines which columns get passed out. In this mode (Mode2) only 3 columns get passed out, when this inside stored procedure is used for another report (Mode1) 4 columns gets passed out. Sometimes the parent stored procedure complains about trying to insert the 4 column and sometimes not.
I know it's always passing in mode 2 but it's like SQL Server knows that sometimes this stored procedure has passed back 4 columns.
Any thoughts on a solution?
Thanks
Don
Make the child procedure always return the same number and type of columns, use NULL if necessary. If the results are so different for the two versions, that you can't combine them like this, you should consider making two different procedures.
I'm just guessing at your procedure, but you could create a #ResultSet temp table and populate it based on your type parameter, but always return all columns, etc. If you are returning lots of rows this becomes bad, as the temp table is overhead. in that case, just make sure your result sets return the same number of columns:
IF #version=1
BEGIN
SELECT col1, col2, NULL FROM ... WHERE ...
END
ELSE
BEGIN
SELECT col1, col2, col3 FROM ... WHERE ...
END
Then when both parents call it, accept all the columns, but they can ignore what they don't need.
Daisy chaining stored procedures is generally not a great idea. I would remove the call to the sproc and type out the t-sql for exactly what you need. If your really set on calling another sproc. Make a new sproc that does exactly what you need for this one situation.
It's all about the Single Responsibility Principle
Related
I'm looking to call a stored procedure on SQL Server via Excel. The reason I'm using Excel is because there are values being input by users which get passed in as parameters to the stored procedure and executed to return the resulting datasets in a new data tab. However, the stored procedure has about 6-7 select statements responsible for generating 6-7 result sets. Aside from creating separate stored procedures for each result set, which isn't feasible as its timely and the result sets build upon each other, what is the best way to handle this or solution to look into? Is it something I need to build into the logic of the stored procedure or something I can configure in Excel?
My stored procedure would look something like this to give you an idea
CREATE PROCEDURE Test
AS
BEGIN
SET NOCOUNT ON;
SELECT TOP 10 PersonType,NameStyle,Title
FROM [AdventureWorks2016CTP3].[Person].[Person]
SELECT TOP 10 PersonType,Firstname,Lastname
FROM [AdventureWorks2016CTP3].[Person].[Person_json]
SELECT ****
.
.
.
SELECT ****
END
GO
In the stored procedure give same column names to all the select statements and use UNION between them and then have an additional column to each select statement to identify which table the data is coming from, ideally use table name.
Then call the stored procedure into a main tab once and then reference that data into other tabs and filter them.
I have recently used both to fetch result of a stored procedure. I have noticed that fetchrow_array returns the output of rows I select inside the stored procedure. Whereas fetchall_arrayref returns status of the stored procedure in the last row, along with selected rows in stored procedure.
Why we have this difference and is there a way to avoid getting the status of stored procedure inside fetchall_arrayref?
My stored Procedure
CREATE PROCEDURE [dbo].[check_date_proc]
#dateStart DATETIME
AS
BEGIN
SELECT
check_date
FROM
date_Table
WHERE
data_date = #dateStart
END;
GO
and i call it like this
exec check_date_proc '20160920';
fetchrow_array returns
20160920
fetchall_arrayref returns
20160920
0
Thanks
Depending on which database type you are working with (and depending on the Perl DBD driver), it is likely that you are getting multiple result sets.
There is a way for processing multiple result sets (For ex., if you have executed two statements which have resulted in two result sets; and you want both of them).
Look here for sample code.
Since, in your case, you want to ignore the status of the stored procedure, you may feel it convenient just to fetch the results as hashes (all rows in one pull OR each one one by one), and then use the names of the columns to get the data.
I have 2 systems that use the same stored procedure.
The problem is that one system needs data as normal select statement inside the stored procedure, while the other needs the data in XML format
I just looking for best practice,
do I have to create 2 stored procedures so each system read from its own stored procedure?
or I create one stored procedurefor normal data and the other stored procedure read data from the first one and fill it in temp table using OPENROWSET?
or add a parameter for data output so if I want data i pass 1 if I want xml I pass 2?
any other suggestions?
Thanks
Depends on the details of the stored procedure but as a rule of thumb I prefer to add a parameter to determine the output type. In this way you will avoid to maintain two procedures and the risk of going out of sync at some point in the future.
I would suggest Two Stored Procedures. as using OPENROWSET might have some performance issues.
When you say you need data in XML format, this query will look very different from the query which returns data in rowset and both queries will have a very different execution plan.
So if you decide to embed this non-XML procedure inside a OPENROWSET query and then try to pull XML OUTPUT from that query might result in a very inefficient query plan.
I would say simply create Two Separate procedures and have two separate Execution plans for each procedure which can possibly result in a better performance.
Another Option that comes to my mind is that you can add a Parameter to your Procedure like #XML_OUTPUT and at run time check the value of Parameter and run respective queries, something like this...
CREATE PROCEDURE Get_DATA
#Param1 DataType,
#Param2 DataType,
#XML_OUTPUT BIT
AS
BEGIN
SET NOCOUNT ON;
IF (#XML_OUTPUT = 1)
BEGIN
SELECT *
FROM TABLE
FOR XML PATH('')..... bla bla
END
ELSE
BEGIN
SELECT *
FROM TABLE ... bla bla
END
END
And at run time if #XML_OUTPUT was set to 1 , the procedure will return XML Data, else it will return non-xml data.
i have a stored proc A that contains a stored proc B.
stored proc B does an insert and returns a row of information.
is there a way to access that info in stored proc A?
You can execute the stored procedure and selected it into a temp table.
Create #table ()....
INSERT INTO #table EXEC your_procedure
The only time when it really becomes difficult (and maybe impossible, I've never seen it done) is when the stored procedure returns multiple recordsets (not multiple records) and the recordsets have different fields.
EDIT:
You can can also use a table variable (DECLARE #my_table TABLE()) to do the same thing. In your situation you'll want to try both and see which is better.
http://www.sql-server-performance.com/2007/temp-tables-vs-variables/
You could create a temp table and then insert-exec from the inner procedure call.
Share Data
Scroll down to the Insert-Exec section.
I will recommend you to create a Table variable and insert the row information into it
EDIT:
Please note that it will be useful if not under Transaction and not joining it with other tables and just acting as a intermediate for containing row information as you just said in the query.
I have a Stored Procedure that rolls-back a series of operations. I want to call this from within another SP.
The problem is that the inner SP returns a record set with a single value that indicates the degree of success.
This approach worked well and has some advantages in our context, but in retrospect, I would have done it the conventional way with a Return value or an Output parameter.
I could always change this SP to use this approach and modify the calling code, but a) I don't want to dabble with any more code than I have to, and b) at an intellectual level, I'm curious to see what alternative solution there may be, if any.
How (if at all) can I call this SP and determine the value of the singleton recordset returned?
Thanks
A stored procedure returns a record set like any other, so you can actually do this:
INSERT INTO MyTable (
MyValue
)
EXEC dbo.MyStoredProcedure
The EXEC takes the place of a SELECT statement. To get the value, just SELECT from the table you inserted into. Typically, this would be a temp table.
The other option is to convert the stored procedure that returns a recordset into a function that returns a table.
Ant's approach is probably best if you want to minimize the changes to your system.
Normally you would use a temporary table for that approach since you can't use an exec statement to insert into a table variable.
Here's a variation which will work well if you need to use this for MULTIPLE recordsets.
CREATE TABLE #outsidetable (...)
exec spInsideProcedure
SELECT * FROM #outsidetable
inside spInsideProcedure
INSERT INTO #outsidetable SELECT <blah blah blah>
I tried Ant's approach and it worked a treat:
Declare #Success tinyint
Declare #Response Table (Success int)
Insert into #Response(Success)
Exec Fix_RollbackReturn 12345, 15
Select #Success=Success from #Response
As you can see I used a Table Variable rather than a temporary table because slightly more efficient than a temporary table.
Thanks for all your help guys.
EDIT: It appears that Dave was right after all. That is, my Exec-into-Table-variable approach worked on my SQL2005 development machine, but when moved to the Live (SQL2000) machine it objected, so I had to change to the temporary table approach.
It's a little annoying, especially since in a couple of weeks we are upgrading to SQL2005 across the board(!).