I have an SSRS report that is calling on one Stored Procedure to Execute, which updates a table in the database. Then I run a report on the data in the table utilizing another stored procedure.
What I would like to do be able to pass a parameter from the report to the Stored Procedure. Here is a sample of what I am doing.
StoredProcedure
Select
HospCode
TxnCode
TxnAmt
into
TxnData
From
Data
Where
TxnDate Between #Start and #End
Report-
Exec StoredProcedure
Select
HospCode
Sum(TxnAmt) Over(Partition By HospCode)
From
TxnData
Order By HospCode
Yes the Parameters are declared in the SP. I would like the User running the report to be able to choose the date range, then have that passed onto the Stored Procedure.
I can do this with individual Procedures very easily but The Stored Procedure is a building block that quite a few reports will use- so rather than have to copy and paste or retype, I would just like to call it up.
Is this possible.
Thanks,
Scott
Here is the logic but ensure the stored procedures are maintained if changes are required.
In SSRS you would pass Start date and End Date to base stored procedure which will be passed to sub stored procedure.
Test data generated for testing ..
create table Data (HospCode int, TxnCode int, TxnAmt money, TxnDate date)
insert into Data (HospCode, TxnCode, TxnAmt, TxnDate)
select 1, 1, 10, '2014-09-11'
union all
select 1, 1, 10, '2014-09-12'
union all
select 1, 2, 10, '2014-09-11'
union all
select 2, 2, 10, '2014-09-11'
Base Stored procedure: You will need to create a temp table to return data from the sub stored procedure. Ensure the temp table must have the same field and data types returned from the sub stored procedure.
CREATE PROC dbo.someSPbase(#StartDate DATE, #EndDate DATE)
AS
BEGIN
IF OBJECT_ID('TempDB.dbo.#TempData') IS NOT NULL
DROP TABLE #TempData;
CREATE TABLE #TempData(
HospCode int
, TxnCode int
, TxnAmt money
);
INSERT INTO #TempData(HospCode, TxnCode, TxnAmt)
EXEC dbo.someSPSub1 #StartDate, #EndDate
SELECT HospCode
, SUM(TxnAmt) OVER (Partition By HospCode) AS TxnAmtTotal
FROM #TempData;
END
Sub stored procedure called from base stored procedure above:
CREATE PROC dbo.someSPSub1(#StartDate DATE, #EndDate DATE)
AS
BEGIN
Select
HospCode
,TxnCode
,TxnAmt
From Data
Where TxnDate Between #StartDate and #EndDate
END
Related
We have a job with couple of steps and almost all of the steps use getdate(), but instead we want to get the date from a specific table and column. The table includes only two columns status as ready (doesn't change) and statusdate (dynamic). The plan is to create a stored procedure and replace the getdate() with that stored procedure.
How do I write the stored procedure? How do I declare a variable?
CREATE PROCEDURE SP_DATE
#StatusDate DATETIME
AS
BEGIN
SELECT StatusDate
FROM [DB_Name].[dbo].[Table_Name]
WHERE status = ready
END
Thank you!
Your jobs use getdate() function therefore in order to replace it with custom programmatic object you should use function as well and not a stored procedure. With a function like this
CREATE FUNCTION dbo.StatusDate ()
RETURNS DATETIME
AS
BEGIN
RETURN (SELECT
StatusDate
FROM Table_Name
WHERE status = 'ready')
END
you can replace getdate directly
SELECT
id
FROM Your_Job_List yjl
WHERE yjl.aDate < dbo.StatusDate()--getdate()
yet there are some questions to the design. One biggest single task of RDBMS is joining tables and perhaps a query similar to next one might be better
SELECT
id
FROM Your_Job_List yjl
,Table_Name tn
WHERE yjl.aDate < tn.StatusDate
AND tn.status = 'ready'
CREATE PROCEDURE spRunNextDate
AS
BEGIN
--SET NOCOUNT ON
declare #runDate datetime
select #runDate = MIN(StatusDate)
from [DB_Name].[dbo].[Table_Name]
where [status] = 'ready'
IF (#runDate IS NULL)
BEGIN
PRINT 'NO Dates in Ready State.'
RETURN 0
END
PRINT 'Will Run Date of ' + CAST(#runDate as varchar(20))
-- Notice the MIN or MAX usage above to get only one date per "run"
END
GO
There are huge holes and questions raised in my presumptuous sp above, but it might get you to thinking about why your question implies that there is no parameter. You are going to need a way to mark the day "done" or else it will be run over and over.
I have created a stored procedure where I an looping through data and inserting records based on the data. The inserts have the same format, but the data changes slightly.
The decision making is handled with IF/ELSE statements, and I have a dozen or so INSERT queries (one for each decision).
I'd like to put the INSERT into a function that I can just call with the variables that change.
I would like to create the function at the beginning of the stored procedure, and then DROP it at the end.
USE [DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Procedure [dbo].[DataParser]
AS
CREATE FUNCTION [dbo].[InsertFunc]
(#Number VARCHAR(40),
#Line_No INT,
#Topic VARCHAR(30),
#Note VARCHAR(4099),
#Bool VARCHAR(1))
RETURNS bit
AS
BEGIN
INSERT INTO Processing (Number, Line_No, Topic, Note, Activation_Date, Mandatory)
VALUES (#Number, #Line_No, #Topic, #Note,
CONVERT(VARCHAR(8), GETDATE(), 1), #Mandatory)
RETURN ##ROWCOUNT
END
...
...
Decision tree
...
...
InsertFunc(#oid, #lidCounter, 'StrVal1', #strVar2, 'Y')
Right now it will not let me save the stored procedure, and if I try to create the function outside of the stored procedure, I get the following error:
Msg 443, Level 16, State 15, Procedure DataParser, Line 12 [Batch Start Line 23]
Invalid use of a side-effecting operator 'INSERT' within a function.
Any help is appreciated.
The short answer is that in SQL Server you cannot perform INSERT / UPDATE / DELETE actions within a function.
Although I don't recommend an approach where you are creating and removing stored procedures dynamically, if you try your approach creating a stored procedure instead of a function it should work.
Below is stored procedure that may help you.
Create Table #Temp
(
Number varchar(40),
Line_No INT,
Topic VARCHAR(30),
Note VARCHAR(4099),
Bool VARCHAR(1),
Activation_Date datetime,
Mandatory varchar(10)
)
CREATE procedure [dbo].[InsertDataIntoTable]
(#Number VARCHAR(40),
#Line_No INT,
#Topic VARCHAR(30),
#Note VARCHAR(4099),
#Bool VARCHAR(1),
#Mandatory varchar(4))
AS
BEGIN
INSERT INTO #Temp (Number, Line_No, Topic, Note, Activation_Date, Mandatory)
VALUES (#Number, #Line_No, #Topic, #Note,
CONVERT(VARCHAR(8), GETDATE(), 1), #Mandatory)
END
I have 2 procedures proc_Data, proc_FetchData.
I'm calling proc_Data from within proc_FetchData. proc_Data returns 2 tables. I want to insert only the first table into a temp table in my second procedure and use it further.
The problem is I cannot change proc_Data in any way as this is a very old procedure used in various parts of our application.
Sample code for reference
create procedure proc_Data
As
Begin
select 'Apples'
select 'Oranges','Grapes'
end
create procedure proc_FetchData
As
Begin
create table #temp(Data varchar(30))
insert into #temp
exec Test_proc
select * from #temp
end
I'm using SQL Server 2014 - is there any way to achieve this? Thanks in advance.
You cant do it that way, you can split your first SP into 2 and call it in your second SP, like,
create procedure proc_Data1
As
Begin
select 'Apples'
end
GO
create procedure proc_Data2
As
Begin
select 'Oranges','Grapes'
end
GO
ALTER procedure proc_FetchData
As
Begin
create table #temp(
Data varchar(30)
)
insert into #temp
exec proc_Data1
select * from #temp
end
To insert only the first table you can use OPENROWSET.
create procedure proc_FetchData
As
Begin
declare #userData TABLE(Data NVARCHAR(30))
INSERT INTO #userData
SELECT * FROMOPENROWSET('SQLNCLI','Server=[server];Trusted_Connection=yes;','EXEC [database name].dbo.proc_Data')
select * from #userData
end
If you need to access all resultsets you will need to use SQLCLR proc: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/da5328a7-5dab-44b3-b2b1-4a8d6d7798b2/insert-into-table-one-or-multiple-result-sets-from-stored-procedure?forum=transactsql
I suggest you add a new input parameter with a default value to your procedure and return different datasets depended on its value.
ALTER procedure proc_Data
#Mode INT = 0
As
Begin
IF #Mode = 0 BEGIN
select 'Apples'
select 'Oranges','Grapes'
END
ELSE BEGIN
select 'Apples'
END
end
go
ALTER procedure proc_FetchData
As
Begin
create table #temp(Data varchar(30))
insert into #temp
exec proc_Data #Mode = 1
select * from #temp
end
After doing so, you will be able to use your proc_Data in any old queries without changes, whereas its output will be different with different #Mode values if you need.
I am trying to create a Crystal Report within VS2015 but I am having issues with a stored procedure. When I run my report without a stored procedure it gets all the data required and all the groups and formulas work fine. Below is my main SQL code.
SELECT type, description, hire_status, fleet_no, location, date_starting, time_finishing, date_finishing, type, week_number, changes
FROM XXXXXX INNER JOIN XXXXXX ON fleet_no= XXXXXX.fleet_no
WHERE week_number= #weekNo
When I try and add a stored procedure to the report I only get a blank report, I lose all the data from the report. The stored procedure is as follows:
USE [xxxxxx]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Procedure [XXXXXXX].[getCurrentLocation]
#fleet varchar(50) = NULL
AS
Begin
SELECT TOP 1 (dbo.tbl_job_planning.location)
FROM dbo.tbl_job_planning
WHERE (fleet_no = #fleet) AND (date_starting <= DATEADD(week, DATEDIFF(day, 0, GETDATE()) / 7, 5))
ORDER BY date_starting DESC
end;
I pass the parameter to this stored procedure in the record selection.
I want the stored procedure to display a location on each line of the report. When I run the report with just the stored procedure I only get 1 value returned and not a value for each item in the report which is what I need.
you are getting 1 value back because you are specifying
SELECT TOP 1 (dbo.tbl_job_planning.location). Just remove TOP 1 or set the 1 to however many results you want it limited to , but certainly not one as you specified
I have a stored procedure which takes a lot of time (around 5 minutes) to execute. This stored procedure fills up a table. Now I am retrieving the data from that table. I have created a job to execute this stored procedure every 15 minutes. But while the stored procedure is in execution, my table is empty and the front end shows no results at that time. My requirement is to show data at the front end side all the time.
Is there a way to cache the stored procedure results and use that result while the stored procedure executes?
Here is my stored procedure,
BEGIN
declare #day datetime
declare #maxdate datetime
set #maxdate = getdate()
set #day = Convert(Varchar(10),DATEADD(week, DATEDIFF(day, 0, getdate())/7, 0),110)
truncate table tblOpenTicketsPerDay
while #day <= #maxdate
begin
insert into tblOpenTicketsPerDay
select convert(varchar(20),datename(dw,#day)) day_name, count(*) Open_Tickets from
(select [status], createdate, closedate
FROM OPENROWSET('MSDASQL','DSN=SQLite','Select * from tickets') AS a
where createdate <= #day
except
select [status], createdate, closedate
FROM OPENROWSET('MSDASQL','DSN=SQLite','Select * from tickets') AS a
where closedate <= #day and [status] = 'closed') x
set #day = #day + 1
end
END
Any ideas will be helpful.
Thanks.
If I have understood correct then your main concern is: your stored procedure empties the table and then fills it up and since it takes time, your application have no data show.
In that case, you can have a secondary/auxiliary clone table; say tblOpenTicketsPerDay_clone and have your stored procedure fill that table instead like
insert into tblOpenTicketsPerDay_clone
select convert(varchar(20),datename(dw,#day)) day_name,
count(*) Open_Tickets from
That way your application will always have data to display since main table has the data. Once, the clone table is done filling up then transfer the same data to main table saying
delete from tblOpenTicketsPerDay;
insert into tblOpenTicketsPerDay
select * from tblOpenTicketsPerDay_clone;
No, but the problem is not caching, it isa totally bad approach to generate the data.
Generate new data into a temporary table, then MERGE The results (using the merge keyword) into the original table.
No sense in deleting the data first. That is a terrible design approach.