I'm trying to accomplish the IF ELSE statement in a SQL Server stored procedure but it seems that it won't follow the condition. I tried to declare a static value for me to check it but its still the same. My problem is it wont go to ELSE even if the condition is wrong
Here's the code:
ALTER PROCEDURE [dbo].[Amount_Computation]
(#OfficeID int,
#AccountID int,
#Amount int,
#NoOfMonths int,
#Percentage int,
#isRoundOf int,
#MaxAmount int,
#EmployeeType int)
AS
declare #TotalAmount table(TotalAmount int)
declare #Casual table(CasualSalary int, OfficeID int)
declare #Regular table(RegularSalary int, OfficeID int)
declare #basic int
BEGIN
SELECT
#Amount = 1, #OfficeID = 72,
#AccountID = 733, #Amount = 0,
#NoOfMonths = 12, #Percentage = 1.25,
#isRoundOf = 1, #MaxAmount = 35000,
#EmployeeType = 1
IF(#Amount = 0)
BEGIN
INSERT INTO #Casual
SELECT
CAST(((select LEFT(CONVERT(nvarchar,CAST((Case when (basic * 22 > #MaxAmount) then #MaxAmount ELSE Basic * 22 END) AS INT)),LEN(CONVERT(nvarchar,CAST((Case when (basic * 22 > #MaxAmount) then #MaxAmount ELSE Basic * 22 END) AS INT))) - 3)) + '000' ) AS INT ) * #Percentage / 100 * #NoOfMonths as Casual,
a.OfficeID
FROM
pmis.dbo.vw_RGPermanentAndCasual as a
LEFT JOIN
ifmis.dbo.tbl_R_BMSOffices as b ON b.PMISOfficeID = a.OfficeID
WHERE
a.OfficeID = #OfficeID AND a.EmploymentGroup = '2'
INSERT INTO #Regular
SELECT
CAST(((select LEFT(CONVERT(nvarchar,CAST((Case when (basic > #MaxAmount) then #MaxAmount ELSE Basic END) AS INT)),LEN(CONVERT(nvarchar,CAST((Case when (basic > #MaxAmount) then #MaxAmount ELSE Basic END) AS INT))) - 3)) + '000' ) AS INT ) * #Percentage / 100 * #NoOfMonths as Regular,
a.OfficeID
FROM
pmis.dbo.vw_RGPermanentAndCasual as a
LEFT JOIN
ifmis.dbo.tbl_R_BMSOffices as b ON b.PMISOfficeID = a.OfficeID
WHERE
a.OfficeID = #OfficeID AND a.EmploymentGroup = '1'
INSERT INTO #TotalAmount
SELECT
SUM(CasualSalary) + SUM(RegularSalary)
FROM
#Casual as a
LEFT JOIN
#Regular as b ON b.OfficeID = a.OfficeID
END
ELSE IF(#Amount = 1)
BEGIN
INSERT INTO #TotalAmount
SELECT SUM(CasualSalary) as ELSE_IF
FROM #Casual
END
END
/**SELECT CasualSalary FROM #Casual
SELECT RegularSalary FROM #Regular **/
SELECT TotalAmount FROM #TotalAmount
EDIT: Select #Amount should be
SELECT #Amount = 1,#OfficeID = 72,#AccountID = 733, #NoOfMonths = 12, #Percentage = 1.25, #isRoundOf = 1, #MaxAmount = 35000, #EmployeeType = 1
As you noticed yourself - #Amount is listed twice in your SELECT list, with two distinct values.
Easy fix. :)
Related
I have two stored procedures that they have the same where clause, one of them is use for pagination:
ALTER PROCEDURE [dbo].[ret_PayrollCalculations_GetPagedFilteredPersonnels]
(
#SortField varchar(512),
#PageNo int,
#PageSize int,
#CalculationCommandType int,
#StartWorkingPeriodId int,
#StartYear int,
#EndWorkingPeriodId int,
#EndYear int,
#Status int,
#SalariedGuid uniqueidentifier,
#SalariedType int,
#OfficeNumber varchar(64),
#SalariedResultSetId int,
#Keyword nvarchar(2024),
#OperationalUnitIds [dbo].[ListOfID] READONLY
)
AS
DECLARE #AccessibleSalariedGuids [dbo].[ListOfGuid]
IF EXISTS (SELECT * FROM #OperationalUnitIDs)
BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT FeatureGuid FROM prs_OperationalUnitFeatures
WHERE
OperationalUnitID in (SELECT * FROM #OperationalUnitIDs) AND
FeatureFlag IN (2,4)
END
ELSE BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT [Guid] FROM ret_vwSalaried
END
DECLARE #OffsetRows INT = CASE WHEN #PageNo = 1 THEN 0 ELSE (#PageNo - 1) * #PageSize END;
DECLARE #TotalCount INT;
WITH Result AS(
SELECT
CASE
WHEN #SortField = N'[FullName]' THEN ROW_NUMBER() OVER (ORDER BY salaried.[FullName])
WHEN #SortField = N'[FullName] DESC' THEN ROW_NUMBER() OVER (ORDER BY salaried.[FullName] DESC)
WHEN #SortField = N'[WorkingPeriodTitle]' THEN ROW_NUMBER() OVER (ORDER BY calcs.[Year],workingPeriods.[Index])
WHEN #SortField = N'[WorkingPeriodTitle] DESC' THEN ROW_NUMBER() OVER (ORDER BY calcs.[Year] DESC,workingPeriods.[Index] DESC)
WHEN #SortField = N'[PersonnelNo]' THEN ROW_NUMBER() OVER (ORDER BY salaried.[PersonnelNo])
WHEN #SortField = N'[PersonnelNo] DESC' THEN ROW_NUMBER() OVER (ORDER BY salaried.[PersonnelNo] DESC)
END AS [RowNumber],
calcs.[Guid],
calcs.[CalculationCommandGuid],
calcs.[SalariedGuid],
salaried.[PersonnelNo],
salaried.[FullName] AS [PersonnelFullName],
command.[Type] [CommandType],
salaried.[SalariedType],
workingPeriods.Title AS [WorkingPeriodTitle],
command.[MainYear] AS [Year],
command.[Approved],
command.[FinalApproved]
FROM
ret_PayrollCalculationCommands command INNER JOIN
ret_PayrollCalculations calcs ON calcs.[CalculationCommandGuid] = command.[Guid] INNER JOIN
ret_vwSalaried salaried ON calcs.[SalariedGuid] = salaried.[Guid] INNER JOIN
prs_workingPeriods workingPeriods ON workingPeriods.[Id] = command.[MainWorkingPeriodID]
WHERE
ISNULL(calcs.[MainCalculation],0) = 1 AND
ISNULL(command.[Deleted],0)=0 AND
(#Keyword = '' OR salaried.PersonnelNo = #Keyword OR salaried.FullName LIKE N'%' + #Keyword + '%' OR salaried.FullNameReversed LIKE N'%' + #Keyword + '%') AND
(ISNULL(#calculationCommandType, 0) = 0 OR command.[Type] = #calculationCommandType) AND
(ISNULL(#StartYear, 0) = 0 OR command.[MainYear] >= #StartYear) AND
(ISNULL(#StartWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] >= #StartWorkingPeriodId) AND
(ISNULL(#EndYear, 0) = 0 OR command.[MainYear] <= #EndYear) AND
(ISNULL(#EndWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] <= #EndWorkingPeriodId) AND
(ISNULL(#Status, -1) = -1 OR command.[Approved] = #Status) AND
(ISNULL(#SalariedType, -1) = -1 OR salaried.[SalariedType] = #SalariedType) AND
(ISNULL(#SalariedGuid,'00000000-0000-0000-0000-000000000000') = '00000000-0000-0000-0000-000000000000' OR calcs.[SalariedGuid] = #SalariedGuid) AND
(#OfficeNumber IS NULL OR salaried.[OfficeNumber] LIKE '%'+#OfficeNumber+'%') AND
(ISNULL(#SalariedResultSetId, -1) = -1 OR calcs.[SalariedGuid] IN (SELECT [SalariedGuid] FROM ret_SalariedResultSetItems WHERE SalariedResultSetID = #SalariedResultSetId)) AND
(calcs.[SalariedGuid] IN (SELECT * FROM #AccessibleSalariedGuids))
), TableForTotalCount AS (SELECT COUNT(*) As TotalCount FROM Result)
SELECT
(SELECT TOP 1 TotalCount FROM TableForTotalCount) AS TotalCount,
*
FROM Result
ORDER BY
[RowNumber]
OFFSET #OffsetRows ROWS
FETCH NEXT #PageSize ROWS ONLY
and another one supposed to return some Guids
ALTER PROCEDURE [dbo].[ret_PayrollCalculations_GetFilteredPersonnels]
(
#CalculationCommandType int,
#StartWorkingPeriodId int,
#StartYear int,
#EndWorkingPeriodId int,
#EndYear int,
#Status int,
#SalariedGuid uniqueidentifier,
#SalariedType int,
#OfficeNumber varchar(64),
#SalariedResultSetId int,
#Keyword nvarchar(2024),
#OperationalUnitIds [dbo].[ListOfID] READONLY
)
AS
DECLARE #AccessibleSalariedGuids [dbo].[ListOfGuid]
IF EXISTS (SELECT * FROM #OperationalUnitIDs)
BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT FeatureGuid FROM prs_OperationalUnitFeatures
WHERE
OperationalUnitID in (SELECT * FROM #OperationalUnitIDs) AND
FeatureFlag IN (2,4)
END
ELSE BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT [Guid] FROM ret_vwSalaried
END
SELECT
calcs.[Guid]
FROM
ret_PayrollCalculationCommands command INNER JOIN
ret_PayrollCalculations calcs ON calcs.[CalculationCommandGuid] = command.[Guid] INNER JOIN
ret_vwSalaried salaried ON calcs.[SalariedGuid] = salaried.[Guid]
WHERE
ISNULL(calcs.[MainCalculation],0) = 1 AND
ISNULL(command.[Deleted],0)=0 AND
(#Keyword = '' OR salaried.PersonnelNo = #Keyword OR salaried.FullName LIKE N'%' + #Keyword + '%' OR salaried.FullNameReversed LIKE N'%' + #Keyword + '%') AND
(ISNULL(#calculationCommandType, 0) = 0 OR command.[Type] = #calculationCommandType) AND
(ISNULL(#StartYear, 0) = 0 OR command.[MainYear] >= #StartYear) AND
(ISNULL(#StartWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] >= #StartWorkingPeriodId) AND
(ISNULL(#EndYear, 0) = 0 OR command.[MainYear] <= #EndYear) AND
(ISNULL(#EndWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] <= #EndWorkingPeriodId) AND
(ISNULL(#Status, -1) = -1 OR command.[Approved] = #Status) AND
(ISNULL(#SalariedType, -1) = -1 OR salaried.[SalariedType] = #SalariedType) AND
(ISNULL(#SalariedGuid,'00000000-0000-0000-0000-000000000000') = '00000000-0000-0000-0000-000000000000' OR calcs.[SalariedGuid] = #SalariedGuid) AND
(#OfficeNumber IS NULL OR salaried.[OfficeNumber] LIKE '%'+#OfficeNumber+'%') AND
(ISNULL(#SalariedResultSetId, -1) = -1 OR calcs.[SalariedGuid] IN (SELECT [SalariedGuid] FROM ret_SalariedResultSetItems WHERE SalariedResultSetID = #SalariedResultSetId)) AND
(calcs.[SalariedGuid] IN (SELECT * FROM #AccessibleSalariedGuids))
When a bug appears I have to fix the problem in both stored procedures, to avoid duplication I wanted Where clauses in a function and call the function in stored procedures,
But I don't know how?
This is how I would approach this:
If you're using Microsoft sql-server, you can make transact-sql code.
Convert your sql procedure into a string and make the Where clause a text variable that you declare elsewhere.
So it's creating a meta- procedure.
For eg.
DECLARE #whereClause LONGTEXT;
DECLARE #SQLString LONGTEXT;
SET #whereClause = 'i=1'
SET #SQLString = 'SELECT * FROM table WHERE' & #whereClause
sp_executesql SQLString
In a stored procedure I am trying to add two numeric values as shown
DECLARE #tradeamt1 NUMERIC(23,2)
DECLARE #tradeamt3 NUMERIC(23,2)
DECLARE #value NUMERIC(23,2)
if (#retVal1 = 0)
BEGIN
SELECT #row_count = count(1),
#tradeamt1=Sum(trade_amt) ,
#units= Sum(curr_shrs_num)
FROM [csr_staging].[dbo].[fi_impact_source] WITH(NOLOCK)
Where acct_id = 'BANKFEES'
and SD_ID >= EFF_DT
print #tradeamt1
END
if(#retVal3 > 0)
BEGIN
select #row_count = count(1) - #retVal3 + #row_count,#tradeamt3=Sum(trade_amt),#units= #units +Sum(curr_shrs_num) - #currshares
FROM [CSR_Staging].[dbo].[fi_impact_source] WITH(NOLOCK)
where (clearing_code = 'MBS'or clearing_code = 'CNS') and (SD_ID >= EFF_DT)
print #tradeamt3
END
set #value = #tradeamt1 +#tradeamt3
this value gives null instead of adding tradeamount1 =1.00 and tradeamount3 = 191432650.13
Maybe this could work for your SP:
declare #tradeamt1 numeric(23, 2) = 0
, #tradeamt3 numeric(23, 2) = 0
, #value numeric(23, 2) = 0
select #row_count = 0, #units = 0
if #retVal1 = 0
select #row_count = count(1)
, #tradeamt1 = isnull(sum(trade_amt), 0)
, #units = isnull(sum(curr_shrs_num), 0)
from [CSR_Staging].[dbo].[fi_impact_source] with (nolock)
where acct_id = 'BANKFEES'
and SD_ID >= EFF_DT
if #retVal3 > 0
select #row_count = #row_count + count(1) - #retVal3
, #tradeamt3 = isnull(sum(trade_amt), 0)
, #units = #units + isnull(sum(curr_shrs_num), 0) - #currshares
from [CSR_Staging].[dbo].[fi_impact_source] with (nolock)
where clearing_code in ('MBS', 'CNS')
and SD_ID >= EFF_DT
set #value = #tradeamt1 + #tradeamt3
Using isNull( ensures that both #tradeamt1 and #tradeamt3 are not null
This is most probably because when tradeamt1 and tradeamt3 are not initialised and for some reason also not assigned values.
You could initialise them with:
DECLARE #tradeamt1 NUMERIC(23,2) = 0
DECLARE #tradeamt3 NUMERIC(23,2) = 0
DECLARE #value NUMERIC(23,2) = 0
Let me know if that helps.
:)
Below is the code snippet in which MIN function using. When execute below code it is giving an error.
CREATE FUNCTION [dbo].[FN_TempCalcTransportExemp]
(
#EmployeeID varchar(20),
#PayElement varchar(20),
#Month varchar(10),
#FinYear varchar(10)
)
RETURNS decimal
AS
BEGIN
DECLARE #TarnsportExemption decimal(18,2) = 0
DECLARE #TDSIsFullExemption bit
DECLARE #PermanentPhysicalDisability decimal(18,2) = 0
DECLARE #UsingComapnyCar bit
DECLARE #Conveyance decimal(18,2) = 0
DECLARE #TransYes decimal(18,2) = 0
DECLARE #TransNo decimal(18,2) = 0
DECLARE #MinConveyance decimal(18,2) = 0
DECLARE #MinTransport decimal(18,2) = 0
SELECT
#TDSIsFullExemption = TDSDetailsFullExemption,
#TransYes = TDSDetailsYes,
#TransNo = TDSDetailsNo
FROM
tbl_TDSSettingDetails
WHERE
TDSSettingsDetailID = 2
SELECT
#Conveyance = #Month
FROM
tbl_Income
WHERE
EmployeeID = #EmployeeID
AND Element = #PayElement
AND FinancialYear = #FinYear
SELECT
#UsingComapnyCar = UsingCompanyCar,
#PermanentPhysicalDisability = PermanentPhysicalDisability
FROM
tbl_Employee_TDS
WHERE
EmployeeID = #EmployeeID
AND TDSFinancialYear = #FinYear
IF (#TDSIsFullExemption = 1)
BEGIN
SET #TarnsportExemption = #Conveyance
END
ELSE
BEGIN
IF (#UsingComapnyCar = 1)
BEGIN
IF (#Conveyance = 0)
BEGIN
SET #MinConveyance = 0
END
ELSE
BEGIN
SET #MinConveyance = #Conveyance
END
IF (#PermanentPhysicalDisability = 1)
BEGIN
SET #MinTransport = #TransYes
END
ELSE
BEGIN
SET #MinTransport = #TransNo
END
SET #TarnsportExemption = MIN(#MinConveyance, #MinTransport)
END
ELSE
BEGIN
SET #TarnsportExemption = 0
END
END
RETURN #TarnsportExemption
END
Error Message:
Msg 174, Level 15, State 1, Procedure FN_TempCalcTransportExemp, Line
66
The MIN function requires 1 argument(s).
set #TarnsportExemption = MIN(#MinConveyance,#MinTransport) - The MIN function is not what you think it is.
You probably want to do something like this:
set #TarnsportExemption = CASE WHEN #MinConveyance < #MinTransport THEN
#MinConveyance
ELSE
#MinTransport
END
Another option is this:
SELECT #TarnsportExemption = MIN(val)
FROM
(
SELECT #MinConveyance as val
UNION ALL
SELECT #MinTransport as val
)
And one more option is to use the values clause:
SELECT #TarnsportExemption = MIN(val)
FROM (VALUES ( #MinConveyance), (#MinTransport)) AS value(val)
Change your min statement like below MIN. Please refer MIN (Transact-SQL)
--fROM
set #TarnsportExemption = MIN(#MinConveyance,#MinTransport)
--To
SELECT #TarnsportExemption = MIN(A) FROM (
SELECT #MinConveyance A
UNION ALL
SELECT #MinTransport
)AS AA
In SQL, MIN function will return you minimum value of a column from selected list; so you can use MIN only in inline queries.
e.g. Select min(Salary) from Tbl_Employee
So, in your case either you can use case when then or union all to get minimum value from two variables as:-
SET #TarnsportExemption = CASE WHEN #MinConveyance < #MinTransport THEN #MinConveyance ELSE #MinTransport END
OR
SELECT #TarnsportExemption = MIN(TEMPS.[VALUE])
FROM (
SELECT #MinConveyance AS VALUE
UNION ALL
SELECT #MinTransport AS VALUE
) AS TEMPS
create function StudentExist(#nationalId nvarchar(10), #type as int)
returns bit
as
begin
declare #i as int
if(#type =1)
select #i = count(*) from BonyadShahidData..BonyadData where NationalCode = #nationalId and [type] = 'A'
if(#type =2)
select #i = count(*) from BonyadShahidData..BonyadData where NationalCode = #nationalId and [type] = 'B'
if(#type =3)
select #i = count(*) from BonyadShahidData..BonyadData where NationalCode = #nationalId and [type] = 'D'
if(#i > 0)
return 1
return 0
end
my answer will be as blunt as the question CASE (Transact-SQL)
create function StudentExist(#nationalId nvarchar(10), #type as int)
returns bit
as
begin
declare #i as int
if(#type =1)
select #i = count(*) from BonyadShahidData..BonyadData where NationalCode = #nationalId
and [type] = (case #type
when 1 then 'A'
when 2 then 'B'
when 3 then 'C'
end)
if(#i > 0)
return 1
return 0
end
in my following query i want to set 0, 0, 0 in #TMarks, #OMarks, #Percentage respectively if the select statement used with them returns nothing
create procedure [dbo].[TestRecordSelectMInfo]
#GRNo varchar(4),
#SessionId numeric(1),
#TestTypeId numeric(1),
#TMarks int output,
#OMarks numeric(4) output,
#Percentage numeric(4) output,
#Grade varchar(4) output
as
begin
SELECT Subjects.Subject, Marks.TotalMarks, Marks.PassingMarks, TestRecord.Marks, Result = case when TestRecord.Marks = 'A' then 'A' else case when cast(TestRecord.Marks as numeric) < Marks.PassingMarks then 'F' else 'P' end end FROM Subjects INNER JOIN Marks ON Subjects.SubjectId = Marks.SubjectId INNER JOIN TestRecord ON Subjects.SubjectId = TestRecord.SubjectId AND Marks.TestTypeId = TestRecord.TestTypeId where TestRecord.SessionId = #SessionId and TestRecord.TestTypeId = #TestTypeId and TestRecord.GRNo = #GRno
set #TMarks = (select sum(Marks.TotalMarks) from Marks inner join TestRecord on Marks.TestTypeId = TestRecord.TestTypeId and Marks.SubjectId = TestRecord.SubjectId where TestRecord.SessionId = #SessionId and TestRecord.TestTypeId = #TestTypeId and TestRecord.GRNo = #GRNo and TestRecord.Marks <> 'A' and cast(TestRecord.Marks as numeric) > Marks.PassingMarks )
set #OMarks = (select sum(cast(TestRecord.Marks as numeric)) from Marks inner join TestRecord on Marks.TestTypeId = TestRecord.TestTypeId and Marks.SubjectId = TestRecord.SubjectId where TestRecord.SessionId = #SessionId and TestRecord.TestTypeId = #TestTypeId and TestRecord.GRNo = #GRNo and TestRecord.Marks <> 'A' and cast(TestRecord.Marks as numeric) > Marks.PassingMarks)
set #Percentage = #OMarks / #TMarks * 100;
set #Grade = case
when #Percentage < 50
then
'NIL'
else
case
when #Percentage < 60
then
'C'
else
case
when #Percentage < 70
then
'B'
else
case
when #Percentage < 80
then
'A'
else
case
when #Percentage <= 100
then
'A+'
else
'FAIL'
end
end
end
end
end
end
GO
EDIT: An aggregate without a group by returns null for an empty set. You could work around this with insull:
select #TMarks = IsNull(sum(Marks.TotalMarks),0)
from Marks
inner join TestRecord
on Marks.TestTypeId = TestRecord.TestTypeId
and Marks.SubjectId = TestRecord.SubjectId
where TestRecord.SessionId = #SessionId
and TestRecord.TestTypeId = #TestTypeId
and TestRecord.GRNo = #GRNo
and TestRecord.Marks <> 'A'
and cast(TestRecord.Marks as numeric) > Marks.PassingMarks