Update column by calling function is very slow - how to improve? SQL Server - sql

I need to update some column by calling a function. It takes a too long time.
How can I improve it? What could be the reason it takes so long?
I realized that scalar-function takes more time than a table-function, but I have no idea how to convert this to a table function, is there perhaps another way to do this?
The code that updates:
UPDATE EDBNationalInsuranceMortgageLoad_tmp
SET IsDead = dbo.GetIsDead(IdentityNumber1, #FileId) -- the function
The code of the function:
ALTER FUNCTION [dbo].[GetIsDead]
(#IdentityNumber1 NVARCHAR(9),
#FileId INT)
RETURNS int
AS
BEGIN
DECLARE #mateIdentityNumber NVARCHAR(9);
DECLARE #fullRow1_tmp TABLE
(
IdentityNumber NVARCHAR(9),
MateIdentityNumber NVARCHAR(9),
DeathDate NVARCHAR(8)
);
DECLARE #fullRow2_tmp TABLE
IdentityNumber NVARCHAR(9),
MateIdentityNumber NVARCHAR(9),
DeathDate NVARCHAR(8)
);
DECLARE #countRows2 INT
DECLARE #isDead1 INT = 0
DECLARE #isDead2 INT = 0
SET #mateIdentityNumber = (SELECT TOP 1 MateIdentityNumber
FROM MortgageReturnParticipationBase
WHERE IdentityNumber = #IdentityNumber1
AND MortgageReturnParticipationStatusId = 1)
INSERT INTO #fullRow1_tmp
SELECT TOP 1 IdentityNumber1, IdentityNumber2, DeathDate
FROM EDBNationalInsuranceMortgageLoad_tmp
WHERE IdentityNumber1 = #IdentityNumber1
AND IsRowError = 0
AND FileId = #FileId
SET #isDead1 = (SELECT 1
FROM #fullRow1_tmp
WHERE DeathDate IS NOT NULL)
IF #mateIdentityNumber = 0
BEGIN
IF (#isDead1 = 1)
RETURN 0;
ELSE
RETURN 1;
END
ELSE
BEGIN
INSERT INTO #fullRow2_tmp
SELECT TOP 1 IdentityNumber1, IdentityNumber2, DeathDate
FROM EDBNationalInsuranceMortgageLoad_tmp
WHERE IdentityNumber1 = #mateIdentityNumber
AND IsRowError = 0
AND FileId = #FileId
SET #countRows2 = (SELECT COUNT(*) FROM #fullRow2_tmp)
IF #countRows2 = 0
RETURN 2;
SET #isDead2 = (SELECT 1 FROM #fullRow2_tmp WHERE DeathDate IS NOT NULL)
IF (#isDead1 IS NULL OR #isDead2 IS NULL OR #isDead1 = 0 OR #isDead2 = 0)
RETURN 1;
IF (#isDead1 = 1 AND #isDead2 = 1)
RETURN 0;
END
RETURN NULL;
END
I tried to convert it to a table-function, but it worked slowly:
ALTER FUNCTION dbo.GetIsDeadTableFunc (
#IdentityNumber1 nvarchar(9),
#FileId INT)
RETURNS TABLE AS RETURN
select (case when (b.MateIdentityNumber > 0 and b.MateIdentityNumber
not in (SELECT IdentityNumber1
from EDBNationalInsuranceMortgageLoad_tmp
where IsRowError=0
and FileId=#FileId))
then 2
when (b.MateIdentityNumber = 0
and DeathDate is null)
or (b.MateIdentityNumber > 0 and b.MateIdentityNumber in (SELECT IdentityNumber1
from EDBNationalInsuranceMortgageLoad_tmp
where IsRowError=0
and FileId=#FileId
and (DeathDate is null or DeathDate is not null))
and DeathDate is null)
or (b.MateIdentityNumber > 0 and b.MateIdentityNumber in (SELECT IdentityNumber1
from EDBNationalInsuranceMortgageLoad_tmp
where IsRowError=0
and FileId=#FileId
and DeathDate is null) -- אמור להיות עוד פונה והוא נמצא בקובץ חי
and DeathDate is not null) -- פונה 1 נפטר
then 1
else 0 end) as IsDead
from EDBNationalInsuranceMortgageLoad_tmp e
join MortgageReturnParticipationBase b on b.IdentityNumber = e.IdentityNumber1
WHERE e.IdentityNumber1 = #IdentityNumber1
and IsRowError=0
and FileId=#FileId
and b.MortgageReturnParticipationStatusId=1
GO

Related

adding two numeric values results null value in stored procedure

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.
:)

The MIN function requires 1 argument(s)

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

I want to create a function in SQL that by input parameter my query condition is changed

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

comparing three variables

I have three integer variables: firstCount, secondCount, thirdCount. I need to compare it and to output the result. I'm bad at SQL, but C# code is something like this:
if(firstCount == secondCount == thirdCount)
return true;
else
return false;
One way (2008 syntax).
SELECT CAST(CASE
WHEN COUNT(DISTINCT C) = 1 THEN 1
ELSE 0
END AS BIT)
FROM (VALUES (#firstCount),
(#secondCount),
(#thirdCount)) t (C)
declare #first int
, #second int
, #third int
select #first = 0
, #second = 0
, #third = 0
select case when (#first = #second) AND (#second = #third) THEN 1 ELSE 0 END
Following is one way to do it but after reading #meagar's comment, I find that solution to be more elegant. Just waiting for him to turn it into an answer...
DECLARE #firstcount INTEGER
DECLARE #secondcount INTEGER
DECLARE #thirdcount INTEGER
SET #firstcount = 1
SET #secondcount = 2
SET #thirdcount = 3
IF #firstcount <> #secondcount SELECT 0
ELSE IF #secondcount <> #thirdcount SELECT 0
ELSE SELECT 1
You are wanting to say If Firstcount is equal to second count, and secondcount is equal to third count return true.
You can just do
DECLARE #a INT = 2
DECLARE #b INT = 2
DECLARE #c INT = 2
IF (#a = #b AND #a = #c)
BEGIN
Print('true')
END
ELSE
BEGIN
Print('false')
END
Although it makes no difference you dont need to test B = C because A = C is exactly the same thing since all 3 values have to be the same.
Try the code ,
if ( (firstCount = secondCount) and (secondCount = thirdCount) and (firstCount = ThirdCount) )
return true;
else
return false;

An object or column name is missing or empty

I am getting the following error
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Add a name or single space as the alias name.
for the query show below:
CREATE PROC [dbo].[Sp_Table1] #ctlg_ipt_event_id int
AS
SET NOCOUNT ON
DECLARE #current_status NCHAR(1), #ready_status_code NCHAR(1)
DECLARE #current_action NCHAR(1), #ready_action_code NCHAR(1), #done_action_code NCHAR(1)
DECLARE #pst_user_id int
SELECT #current_status = status_code
,#current_action = action_code
,#pst_user_id = last_mod_user_id
FROM merch_ctlg_ipt_event
WHERE ctlg_ipt_event_id = #ctlg_ipt_event_id
Select #ready_status_code = 'o'
, #ready_action_code = 'a'
, #done_action_code = 'b'
IF #current_status <> #ready_status_code OR #current_action <> #ready_action_code
BEGIN
RETURN
END
BEGIN TRAN
declare #rows int
,#err int
,#i int
,#name nvarchar(50) --COLLATE SQL_AltDiction_Pref_CP850_CI_AS
,#resolved_View_Name_category_id int
,#xref_value int
,#availability_start_date datetime
,#availability_end_date datetime
,#status_code int
,#last_mod_user_id int
,#CT datetime
,#supplier_id int
,#View_Name_id int
select #i = 1
,#CT = current_timestamp
Select Distinct mc.name,
mc.resolved_View_Name_category_id,
mc.xref_value,
mc.availability_start_date,
mc.availability_end_date,
mc.status_code,
CASE WHEN mc.last_mod_user_id = 42
THEN #pst_user_id
ELSE mc.last_mod_user_id
END as last_mod_user_id,
CURRENT_tsp
,IDENTITY(int,1,1) as rn
,si.supplier_id
,si.View_Name_id
into #temp
FROM View_Name AS si
JOIN merch_ctlg_ipt_View_Name AS mc
ON mc.supplier_id = si.supplier_id
AND mc.resolved_View_Name_id = si.View_Name_id
AND mc.cat_imp_event_id = #ctlg_ipt_event_id
AND mc.accept_flag = 'y'
WHERE si.shipper_flag = 'n'
select #rows=##ROWCOUNT,#err=##error
if #rows > 0 and #err=0
Begin
While #i <=#rows
begin
SElect #name = name,
#resolved_View_Name_category_id = resolved_View_Name_category_id,
#xref_value = xref_value,
#availability_start_date = availability_start_date,
#availability_end_date = availability_end_date,
#status_code = mc.status_code,
#last_mod_user_id =last_mod_user_id ,
,#i=#i+1
,#supplier_id=supplier_id
,#View_Name_id=View_Name_id
from #temp
Where rn=#i
UPDATE View_Name
SET name = #name,
View_Name_category_id = #resolved_View_Name_category_id,
xref_value = #xref_value,
availability_start_date = #availability_start_date,
availability_end_date = #availability_end_date,
status_code = #status_code,
last_mod_user_id = #last_mod_user_id ,
last_mod_timestamp = #CT
Where #sup_id = supplier_id
AND #View_Name_id = View_Name_id
AND shipper_flag = 'n'
IF ##ERROR > 0
BEGIN
ROLLBACK TRAN
RETURN
END
End
End
UPDATE
merch_ctlg_ipt_event
SET action_code = #done_action_code,
last_mod_timestamp = #CT
WHERE ctlg_ipt_event_id = #ctlg_ipt_event_id
IF ##ERROR > 0
BEGIN
ROLLBACK TRAN
RETURN
END
COMMIT TRAN
Return
go
Could you please help ?
You have 2 commas in a row here
#last_mod_user_id =last_mod_user_id ,
,#i=#i+1
Also probably not relevant to the error message but you have a line
Where #sup_id = supplier_id
but the declared variable is #supplier_id