Select statement with a Split function - sql

I am using a select split function in stored procedure to pass a multiple selection IDS like below .
SELECT Status AS ClientInbox, COUNT(submitTime) AS CountStatus
FROM dbo.ClientInbox with (nolock) join debtor with (nolock) on ClientInbox.debtorid = debtor.id
WHERE (submitTime >= #fromDate and submittime <= #toDate)
and debtor.clientid IN (SELECT ID FROM [dbo].[split_IDs] (#clientid,','))
GROUP BY Status
Where [dbo].[split_IDs] is a function. My problem is while testing, when i replcae the variable #clientid with a set of setrings like ('1,2,3,4,5'), the query returns the required records. But when i run the procedure from VS, it does not return the exact records. I try to figure out what the problem is by executing the procedure in the SQL server as below
USE [Volare_2005]
GO
DECLARE #return_value int
DECLARE #fromDate datetime
DECLARE #toDate datetime
EXEC #return_value = [dbo].[GetSMSReportDate]
#fromDate = '2000-04-06T12:23:45',
#toDate = '2013-10-22T21:10:12',
#option = 0 ,
#collectorid = 0,
#supervisorid = 0,
#clientid = N'95,1'
--SELECT 'Return Value' = #return_value
GO
It fails the return the records as well. However it works fine when i run the query by replcaing the variable #clientid in the procedure. I am not sure were i go wrong. Please any help would be appreciate

Related

How can i execute a stored procedure inside another stored procedure in SQL Server?

I´m working with SQLServer and I have two storedprocedures
The first one:
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
DECLARE #FECHAFIN AS datetime;
SET #FECHAFIN = #FECHAINICIO + '23:59:59.999'
-- Insert statements for procedure here
SELECT
HC.idCorrida AS Referencia,
T.part AS Parte,
T.idTrabajo AS Trabajo,
HC.cantidadFabricado AS Piezas,
HC.cantidadRechazado AS Rechazo,
CONVERT(varchar(8), HC.tiempoProduccion) AS TiempoDeProduccion,
CONVERT(varchar(8), HC.tiempoMuerto) AS TiempoMuerto,
HC.fechaInicio AS Fecha,
U.nombreUsuario AS Usuario,
MA.nombre AS NombreMaquina,
TR.nombre AS NombreTripulacion,
TXM.idTurno AS Turno,
FROM [Produccion].[HistorialCorridas] AS HC
INNER JOIN [Produccion].[Trabajos] AS T
ON HC.idTrabajo = T.idTrabajo
INNER JOIN [Administracion].[Usuarios] AS U
ON U.idUsuario = HC.idUsuario AND U.idTripulacion = #IDTRIPULACION
INNER JOIN [Administracion].[Tripulaciones] AS TR
ON U.idTripulacion = TR.idTripulacion
WHERE HC.idTurnoXMaquina = #IDTURNOXMAQUINA
AND HC.fechaInicio >= #FECHAINICIO AND HC.fechaInicio <= #FECHAFIN
GROUP BY HC.idCorrida, T.part, T.idTrabajo, HC.cantidadFabricado, HC.cantidadRechazado,
HC.tiempoProduccion, HC.tiempoMuerto, HC.fechaInicio, U.nombreUsuario, MA.nombre, TR.nombre, TXM.idTurno
END
The second one:
BEGIN
SET NOCOUNT ON
SELECT
CONVERT(VARCHAR(8), DATEADD(SECOND,SUM(DATEDIFF(SECOND, '00:00:00', TiempoMuerto)),0),114) AS TotalTiempoMuerto,
P.etiqueta AS TipoParo
FROM [Produccion].[TiemposMuertos]
INNER JOIN [Administracion].[ParosXMaquina] AS PM
ON PM.id = idParoXMaquina
INNER JOIN [Administracion].[Paros] AS P
ON P.idParo = PM.idParo
WHERE idCorrida = #IDCORRIDA
GROUP BY P.etiqueta
END
The second one receives as a parameter a field called Referencia from the first stored procedure. What I want to do, is execute the second stored procedure from the first one, passing that parameter.
How could I achieve this? Is it possible to get the result in just one query?
Thanks in advance!!!
To call a PROCEDURE from another PROCEDURE that returns a value as output, you must use the out keyword for the output, which may be a table or other data type.
The following two procedures are defined.
In test1 procedure, the return parameter is specified with out.
In the second procedure, the first procedure is called as follows:
DECLARE #result int
EXEC test1 #result OUTPUT
CREATE PROCEDURE test1
(#outID int output)
AS
BEGIN
SET #outID = (select top 1 ID from table1)
END
CREATE PROCEDURE test2
AS
BEGIN
BEGIN
DECLARE #result int
EXEC test1 #result OUTPUT
SELECT ID from table2 where ID = #result
END;
END
GO
EXEC test2

Multiple parameters error while creating function in SQL Server

I created a function, now rather passing static value I want to add parameter in the function but after calling function it start throwing an error:
Procedure or function dbo.hello has too many arguments specified.
Function :
Create Function dbo.hello
(#InputstartDate Date, #InputendDate Date)
Returns #attendanceTemp table(STUD_NAME VARCHAR(50),
ATTD_DATE DATE ,
attd_DATEs DATE,
Attendance VARCHAR(20))
As
Begin
Declare #startDate DATE
SET #startDate = #InputstartDate
Declare #endDate Date
SET #endDate = #InputendDate
Declare #dateDifference INT
SET #dateDifference = DATEDIFF(day, #startDate,#endDate) ;
Declare #count INT
SET #count = 0
DECLARE #myTable TABLE (STUD_ID int,
countdd int,
STUD_NAME varchar(50),
AttDate Date
)
While #count <= #dateDifference
Begin
Insert Into #myTable (STUD_ID, countdd, STUD_NAME, AttDate)
Values (1, 123, 'HAIDER', #startDate)
Set #count = #count +1
Set #startDate = DATEADD(day, 1, #startDate)
End
Insert Into #attendanceTemp
Select
tb.STUD_NAME, ATTD_DATE, tb.AttDate,
Case
When att.DETAIL Is Null
Then 'ABSENT'
When att.DETAIL = 'ATTENDACE'
Then 'PRESENT'
End As Attendance
from
#myTable tb
Left Join
ATTENDANCE att on tb.AttDate = att.ATTD_DATE
Where
att.STUD_ID = 1 or att.STUD_ID IS NULL
Return
END
Calling the function:
select *
from dbo.hello('2014-04-01', '2014-04-10');
Error:
Procedure or function dbo.hello has too many arguments specified
Possibly you first created the function with only one parameter.
Then made changes to the 'create function' script, and forgot to deploy?
I would;
1. DROP FUNCTION dbo.hello
2. CREATE FUNCTION dbo.hello, with you script
3. Try executing your function again.
The function seems to work fine (Though I cannot run a full test due to not having table 'ATTENDANCE')

MSSQL says I am trying to convert a varchar to a string when I'm not

So I have this fairly long procedure at Work that I just made. What it does it not that important, but the end result is what matters.
I need to count some different types of descriptions in a table and that Works fine. I then need to take the two things that I Count and put them in a string that I return to my software. However, every time I run this procedure it gives me this:
Msg 245, Level 16, State 1, Procedure WorkDays, Line 43 Conversion
failed when converting the varchar value
'FlightDeck:161,CabinCrew:189' to data type int.
I just can't figure out why it keeps telling me this when I am not trying to convert a varchar to an int but rather ints to a single varchar.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[WorkDays] #requestedDate nchar(10)
AS
SET ANSI_WARNINGS OFF
DECLARE #date as nchar(10) = ''
DECLARE #returnVal as varchar(30) = ''
DECLARE #flightDeck as int = 0
DECLARE #cabinCrew as int = 0
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SET #date = #requestedDate
SELECT
#flightDeck = SUM(CASE WHEN dbo.Crew_Category.Description LIKE 'Flight Deck' THEN 1 END),
#cabinCrew = SUM(CASE WHEN dbo.Crew_Category.Description LIKE 'Cabin Crew' THEN 1 END)
FROM
dbo.CrewMember INNER JOIN
dbo.Crew_Category ON dbo.CrewMember.CrewCategorySeqNo = dbo.Crew_Category.CrewCategorySeqno
WHERE
(dbo.Crew_Category.Description = N'Flight Deck' OR
dbo.Crew_Category.Description = N'Cabin Crew') AND
(dbo.CrewMember.EmploymentEndDate > #date)
AND dbo.CrewMember.CrewSeqno NOT IN (
SELECT
CrewMember_1.CrewSeqno
FROM
dbo.CrewMember AS CrewMember_1 INNER JOIN
dbo.CrewReqAsg ON CrewMember_1.CrewSeqno = dbo.CrewReqAsg.crewSeqno INNER JOIN
dbo.activity ON dbo.CrewReqAsg.act_seqno = dbo.activity.act_seqno INNER JOIN
dbo.ActivityType ON dbo.activity.actType_seqno = dbo.ActivityType.actType_seqno INNER JOIN
dbo.ActivityCategory ON dbo.ActivityType.ActCat_seqno = dbo.ActivityCategory.actCat_seqno INNER JOIN
dbo.Crew_Category AS Crew_Category_1 ON CrewMember_1.CrewCategorySeqNo = Crew_Category_1.CrewCategorySeqno
WHERE (
dbo.ActivityCategory.Category = N'Ferie' OR
dbo.ActivityCategory.Category = N'Fridage' OR
dbo.ActivityCategory.Category = N'Sygdom') AND (Crew_Category_1.Description = N'Flight Deck' OR
Crew_Category_1.Description = N'Cabin Crew') AND (LEFT(dbo.activity.Start,10) LIKE #date));
SET #returnVal = 'FlightDeck:'+CAST(#flightDeck AS varchar);
SET #returnVal += ',CabinCrew:'+CAST(#cabinCrew AS varchar);
END
RETURN #returnVal
It's been a while since I've had to do this so perhaps I just forgot something fundamental. Please help me figure out why this happens? :)
Yes, you forgot something fundamental. To return data to the caller, use SELECT, not RETURN.
You need
SELECT #returnVal

Performance issue with stored procedure [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
I have a stored procedure that uses the while loop temp table and cursor by which I gets the aging balance of customer, however my SP is working fine but I have some performance concerns as its take 15 sec to produce results from a small chunk of data. I am looking for a more efficient way to do this.
Thanks in advance.
Here is my stored procedure.
CREATE TABLE #Customer_Temp (
AccountCode varchar(50),
AccountTitle varchar(50),
CurrentBalance int,
FirstBalance int,
SecondBalance int,
ThirdBalance int,
FourthBalance int,
FifthBalance int,
SixthBalance int,
SeventhBalance int,
EighthBalance int,
OpeningBalance int
)
INSERT INTO #customer_temp (AccountCode, AccountTitle, OpeningBalance)
SELECT
Customer.AccountCode,
Customer.Name,
COA.OpeningBalance
FROM Customers AS Customer
INNER JOIN ChartOfAccount AS COA
ON COA.CompanyId = #Companyid
AND COA.BusinessUnitId = #BusinessUnitId
AND COA.ChartAccount = Customer.AccountCode
--Create Table And Duplicate Customers Data In it ENDED
DECLARE #DrAmount AS int
DECLARE #CrAmount AS int
DECLARE #Balance AS int
DECLARE #FBalance AS int
DECLARE #SBalance AS int
DECLARE #TBalance AS int
DECLARE #FoBalance AS int
DECLARE #FIBalance AS int
DECLARE #SIBalance AS int
DECLARE #SEBalance AS int
DECLARE #EBalance AS int
DECLARE #FSDate AS date
DECLARE #FLDate AS date
DECLARE #SSDate AS date
DECLARE #SLDate AS date
DECLARE #TSDate AS date
DECLARE #TLDate AS date
DECLARE #FOSDate AS date
DECLARE #FOLDate AS date
DECLARE #FISDate AS date
DECLARE #FILDate AS date
DECLARE #SISDate AS date
DECLARE #SILDate AS date
DECLARE #SESDate AS date
DECLARE #SELDate AS date
DECLARE #ESDate AS date
SET #FSDate = DATEADD(DAY, -1, #StartDate)
SET #FLDate = DATEADD(DAY, -6, #FSDate)
SET #SSDate = DATEADD(DAY, -1, #FLDate)
SET #SLDate = DATEADD(DAY, -6, #SSDate)
SET #TSDate = DATEADD(DAY, -1, #SLDate)
SET #TLDate = DATEADD(DAY, -14, #TSDate)
SET #FOSDate = DATEADD(DAY, -1, #TLDate)
SET #FOLDate = DATEADD(DAY, -14, #FOSDate)
SET #FISDate = DATEADD(DAY, -1, #FOLDate)
SET #FILDate = DATEADD(DAY, -14, #FISDate)
SET #SISDate = DATEADD(DAY, -1, #FILDate)
SET #SILDate = DATEADD(DAY, -29, #SISDate)
SET #SESDate = DATEADD(DAY, -1, #SILDate)
SET #SELDate = DATEADD(DAY, -89, #SESDate)
SET #ESDate = DATEADD(DAY, -1, #SELDate)
DECLARE #TempCCode AS varchar(50)
DECLARE #TempOBalance AS float
DECLARE CustomerCursor CURSOR FOR
SELECT
AccountCode,
OpeningBalance
FROM #Customer_Temp
OPEN CustomerCursor
FETCH NEXT FROM CustomerCursor INTO #TempCCode, #TempOBalance
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC #FBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#FSDate,
#FLDate,
#Fyear
EXEC #SBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#SSDate,
#SLDate,
#Fyear
EXEC #TBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#TSDate,
#TLDate,
#Fyear
EXEC #FoBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#FOSDate,
#FOLDate,
#Fyear
EXEC #FIBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#FISDate,
#FILDate,
#Fyear
EXEC #SIBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#SISDate,
#SILDate,
#Fyear
PRINT #SESDate
PRINT #SELDate
EXEC #SEBalance =
GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#SESDate,
#SELDate,
#Fyear
EXEC #EBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#ESDate,
#EndDate,
#Fyear
EXEC #Balance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#StartDate,
#EndDate,
#Fyear
UPDATE #Customer_Temp
SET CurrentBalance = (#Balance + #TempOBalance),
FirstBalance = #FBalance,
SecondBalance = #SBalance,
ThirdBalance = #TBalance,
FourthBalance = #FoBalance,
FifthBalance = #FIBalance,
SixthBalance = #SIBalance,
SeventhBalance = #SEBalance,
EighthBalance = #EBalance
WHERE AccountCode = #TempCCode
FETCH NEXT FROM CustomerCursor INTO #TempCCode, #TempOBalance
END
CLOSE CustomerCursor
DEALLOCATE CustomerCursor
AND here is the called store procedure in cursor
CREATE PROCEDURE [dbo].[GetBalanceOfAgingOnDate]
#BusinessUnitId int,
#Companyid int,
#ChartAccount as varchar (50),
#StartDate as DateTime,
#EndDate as DateTime,
#Fyear as varchar(50)
AS BEGIN
Declare #DrAmount as int
Declare #CrAmount as int
Declare #Balance as int
set #DrAmount=(select sum(Dr_Amount) from AccountVocherMaster AS AM ,
AccountVocherChild AS AC Where AM.CompanyId = #Companyid AND
AM.BusinessUnitId = #BusinessUnitId AND AM.FYear = #Fyear AND
AM.VocherId = AC.VocherId AND AC.AccountCode=#ChartAccount AND
AC.CreatedOn Between #EndDate AND #StartDate);
set #CrAmount=(select sum(Cr_Amount) from AccountVocherMaster AS AM ,
AccountVocherChild AS AC Where AM.CompanyId = #Companyid AND
AM.BusinessUnitId = #BusinessUnitId AND AM.FYear = #Fyear AND
AM.VocherId = AC.VocherId AND AC.AccountCode=#ChartAccount AND
AC.CreatedOn Between #EndDate AND #StartDate);
set #Balance = #DrAmount - #CrAmount ;
return ISNULL(#Balance,0)
END
make cursor a local variable DECLARE #CustomerCursor CURSOR, ensure it is not dynamic and does not reflect updates to cursor's source tables SET #CustomerCursor = CURSOR FAST_FORWARD FOR, in the end update by current cursor position, avoid additional search UPDATE #Customer_Temp SET ... WHERE CURRENT OF #CustomerCursor
obtain aggregates of different columns for similar conditions by a single select select #DrAmount = sum(Dr_Amount), #CrAmount = sum(Cr_Amount)
and more of it: select #Balance = sum(Dr_Amount) - sum(Cr_Amount)
avoid ancient-style joining by comma, write inner or outer joins, put joining conditions into ON clause, put filtering into WHERE clause
avoid thinking of SQL as a regular programming language like PHP or Pascal; it is result-set oriented; try making INLINE TABLE FUNCTION instead of procedure (GetBalanceOfAgingOnDate) - this will make you able to join to that from your queries; tip: do not make it scalar-valued or table-valued function. Look at your aggregation sp and how it is used. For each row (company) you call that sp again and again, and aggregate some values inside it. Why not to GROUP BY company and BusinessUnitID, run a single select from AccountVocherMaster and join it to your #Customer_Temp? Why not to aggregate summary for different periods by a single query? Look again: you have a list of companies, an aggregation query that provides some summarized values grouped by companies... why do you still have a cursor at all? it's a single query job
if you have lots of data and filtering by dates is the only way that makes it run fast - make not a single query, make 10 queries. this anyway will be much better than 10*2*[N companies] Actually period required is well determined - max range is [#StartDate-180, #StartDate] - and it looks like a single query is a good idea again. In some cases, if your data is very big, cursor and filtering by a scalar values may still be a good change to improve performance, thus you may still want to filter by a single CompanyID - ok, but the data you aggregate is still located in fixed date range in the same two tables - AccountVocherMaster and AccountVocherChild; loop through companies, run single aggregation query inside the cursor
there is absolutely nothing smart in your GetBalanceOfAgingOnDate's sources - don't know why you keep it as a separate module
there must be a transaction around it
Your problem is that you do not think SQL and try to be smart - you write procedural code, which SQL Server has to execute one by one INSTEAD of working in set and letting the query optimizer figure out how to do that most efficient.
Cursors and procedures are generally slow elements. You are better to forumulate this in as few atomic SQL statements as possible, even if the statements are a page or two long. Then the query optimizer can figure out how to achieve this result most efficient.
In your case, the second SP gets called repeatedly in the cursor - there are likely ways to achieve this better. In one or a lot less calls.
Hopefully this can start you down the path. There is a lot in your question, so I may not (a) understand everything here and (b) address every part, but hopefully you can take it from here. I don't see the need for any procedures or loops. Give this a try, I've commented some for context:
/* Construct a temp table to store all balance dates (and respective names) */
CREATE TABLE #BalanceDates (BalanceName VARCHAR(20), StartDate DATETIME, EndDate DATETIME);
INSERT INTO BalanceDates VALUES ('FirstBalance',DATEADD(DAY,-1,#StartDate),DATEADD(DAY,-6,#StartDate));
-- And so on with remaining inserts...
/* Create a denormalized table of all balances */
SELECT
[FirstBalance],
[SecondBalance],
...
INTO
#Balances
FROM
(
SELECT
BD.BalanceName,
ISNULL(SUM(Dr_Amount) - SUM(Cr_Amount),0) AS BalanceAmount
FROM
#BalanceDates BD
LEFT JOIN
AccountVocherChild AC
ON (AC.CreatedOn BETWEEN BD.StartDate AND BD.EndDate)
LEFT JOIN
AccountVocherMaster AM
ON (AM.VocherId = AC.VocherId)
WHERE
AM.CompanyId = #Companyid AND
AM.BusinessUnitId = #BusinessUnitId AND
AM.FYear = #Fyear AND
AC.AccountCode = #ChartAccount
GROUP BY
BD.BalanceName
) data
PIVOT
(
AVG(BalanceAmount)
FOR BalanceName IN ([FirstBalance],[SecondBalance],...)
) pvt;
/* Update the table accordingly */
UPDATE tgt
SET
FirstBalance = src.FirstBalance,
SecondBalance = src.SecondBalance,
...
FROM #Customer_Temp tgt
JOIN #Balances src
ON (1 = 1);

ssrs Ignoring variable which is not declared

This is my part of the query which i am using in the Dataset in SSRS2008
DECLARE #SERVER VARCHAR(20) = null;
Declare #curDATEFIRST as Integer = ##DATEFIRST;
SET DATEFIRST 1;
IF #a=0 AND #b>1
BEGIN
DECLARE #NewStartDate DateTime = (SELECT TOP 1 StartDate FROM UserManagerDates WHERE EmployeeID=#b ORDER BY StartDate DESC);
IF #NewStartDate>#StartDate SET #StartDate = #NewStartDate;
END
Question:
I was copying my query into dataset from ssms and when i hit refresh in dataset i only get prompted for #a and #b in define query parameters. Actually i wasn't even declaring #startdate so i was expecting #startdate variable in define query parameters tab. What changes should i make to to get prompted for #startdate along with the other two variables?
You are setting the #startdate parameter, it is supposed to be populated by SSRS instead of your query, that could be the reason you are not being prompted.
I think you want to use #startdate to populate #NewStartDate, if so try this:
DECLARE #SERVER VARCHAR(20) = null;
Declare #curDATEFIRST as Integer = ##DATEFIRST;
SET DATEFIRST 1;
IF #a=0 AND #b>1
BEGIN
DECLARE #NewStartDate DateTime =
(SELECT TOP 1 StartDate FROM UserManagerDates
WHERE EmployeeID=#b ORDER BY StartDate DESC);
IF #NewStartDate>#StartDate SET #NewStartDate = #startdate;
END