I'm having trouble calling a function and using the value from the function call within my stored procedure using mySQL. My function extracts a date value. I'm attempting to set the parameter values with my stored procedure call (parameters - data_transfer_id, mode). Is this possible?
Your help is appreciated. My code below is incorrect but is my start. The function name is kettle_data_transfer.f_DT_last_transfer (data_transfer_id, mode).
CREATE PROCEDURE `sproc_DT_consumer_answer_data`
(IN data_transfer_id bigint (20),
IN `mode` varchar(25)
)
BEGIN
DECLARE last_transfer date kettle_data_transfer.f_DT_last_transfer(data_transfer_id, mode);
SELECT
CEQ.consumer_ID
, EM.event_mapping_ID
, F.footprint_ID
, F.create_DTM as footprint_create_DTM
, EM.event_ID
, EL.brand_ID
, RELAT.activity_type_ID
, ED.event_ID as footprint_event_ID
FROM kettle_data_transfer.Event_Mappings EM
JOIN kettle_data_transfer.Consumer_Event_Queue CEQ ON CEQ.event_ID = EM.event_ID
JOIN efn.Footprints F ON F.consumer_ID = CEQ.consumer_ID
LEFT OUTER JOIN efn.Event_Days ED on ED.event_day_ID = F.event_day_ID
LEFT OUTER JOIN efn.R_Event_Location_Activity_Type RELAT ON RELAT.r_elat_ID = F.r_elat_ID
LEFT OUTER JOIN efn.Event_Locations EL on EL.event_location_ID = RELAT.event_location_ID
LEFT OUTER JOIN kettle_data_transfer.Records RR on RR.consumer_ID = CEQ.consumer_ID
WHERE EM.active_flag = 1
AND F.sample_flag = 0
AND RR.failure_code = 0
AND RR.`ignore` = 0
and (CEQ.modify_DTM > last_transfer OR EM.create_DTM > last_transfer)
and (RR.mode = `mode` OR EM.mode = `mode`)
and (RR.data_transfer_ID = data_transfer_id OR EM.data_transfer_ID = data_transfer_id )
and (RR.consumer_ID = CEQ.consumer_ID)
AND (ED.event_ID = CEQ.event_ID OR ED.event_ID is null)
GROUP BY CEQ.consumer_ID, EL.brand_ID
END
The syntax for stored program variable declarations:
DECLARE var_name [, var_name] ... type [DEFAULT value]
DEFAULT value is not saying "default value goes here." It's the keyword DEFAULT, followed by an expression containing the initial value for the variable.
You are trying to set the default initial value of the variable, but you have omitted the DEFAULT keyword after the variable name.
Adding it should resolve the issue.
https://dev.mysql.com/doc/refman/5.6/en/declare-local-variable.html
Related
I have the following stored procedure:
CREATE DEFINER=`sleuser`#`%` PROCEDURE `PCDD`(
in ProjectID int,
in MonthName varchar(50),
in ServiceCode varchar(50),
in ProjectName varchar(50)
)
BEGIN
SET #PCProjID = ProjectID;
SET #PCSN1 = "020." + ServiceCode + ".000";
SET #Month = MonthName;
SET #ImpCostID = ProjectName;
SET #ImpCostTask1 = "020." + ServiceCode + ".000";
SELECT
project.project_id,
'FP' as Phase,
ImportCost.OriginalCommitments,
ImportCost.ApprovedCommitmentChanges,
sum(RegisteredChangeOrders) + sum(OriginalContractPrice) as CurrentAssigned,
sum(ProjectCostBudget.PendingChangeOrders) as PendingScopeChanges,
FROM `RCLY-DEV`.ProjectCostBudget
inner join project on project.project_id =
ProjectCostBudget.ProjectID
inner join ImportCost on ImportCost.ProjectID = project.pmis
where ImportCost.ProjectID = #ImpCostID and
ImportCost.Task = #PCSN1 and
ProjectCostBudget.ProjectID = #PCProjID and
ProjectCostBudget.ServiceNumber = #ImpCostTask1
which i call using:
call PCDD(2,'September%2018','0000','RLCY-BB-01')
Where '0000' needs to vary from '0000' to '6000'. When I run the SP for '0000' it returns the expected results, but when I change it to anything else it just returns all nulls. I tried updating #PCSN1 and #ImpCostTask1 to:
SET #PCSN1 = ("020.", ServiceCode, ".000");
SET #ImpCostTask1 = ("020.", ServiceCode, ".000");
But i get the error
"Operand should contain 1 column(s).
What am i doing wrong here? Why does it work for one ServiceCode but not the others?
You need to use ' enqoute string literal and CONCAT instead of '+' for string concatenation:
SET #PCSN1 = "020." + ServiceCode + ".000";
=>
SET #PCSN1 = CONCAT('020.', ServiceCode, '.000');
Same for:
SET #ImpCostTask1 = "020." + ServiceCode + ".000";
=>
SET #ImpCostTask1 = CONCAT('020.', ServiceCode, '.000');
We recently found the re-declaration issue in Mysql. If the query or procedure is called repeatedly in loop it retained last values.
SET #ToolType = 'test-Tool1';
SET #ToolType = (select Tool_type from IBP__Tool_type aa inner join IBP__xTool_set bb on aa.Tool_type_id=-1) ;
select #ToolType;
SET #ToolType = 'test-Tool1';
select #ToolType:=Tool_type from IBP__Tool_type aa inner join IBP__xTool_set bb on aa.Tool_type_id=-1;
select #ToolType; -- = OR :=
SET #ToolType = 'test-Tool2';
select Tool_type into #ToolType from IBP__Tool_type aa inner join IBP__xTool_set bb on aa.Tool_type_id=-1;
select #ToolType;
Above code will have Results : (when -1 is not present in tables so the output should be null in all cases)
null
test-tool1
test-tool2
what is the best way to resolve This Issue.
assign the variable to null before using it each time in query. User Session issues will always store the variable value in Mysql server and cause these issues.
SET #ToolType = null;
UPDATE FD DCS
SET DCS.F_DISTANCE =
(SELECT FD.F_DISTANCE
FROM TMP FD
WHERE FD.DATE_SID = DCS.DATE_SID
AND FD.SID = DCS.SID
AND FD.DA_SID = DCS.DASID
AND FD.AA_SID = DCS.AA
AND FD.F_DISTANCE IS NOT NULL
)
WHERE DCS.BATCH_ID=BATCH_ID;
The inner SQl query is updating all the satisfied values to the FD table's column F_distance but where subquery didn't match it is updating the FD table F_Distance values to null. I don't want to update the values to null.
please suggest what to do.
In ORACLE you can use NVL
UPDATE FD DCS
SET DCS.F_DISTANCE = NVL(
(SELECT FD.F_DISTANCE
FROM TMP FD
WHERE FD.DATE_SID = DCS.DATE_SID
AND FD.SID = DCS.SID
AND FD.DA_SID = DCS.DASID
AND FD.AA_SID = DCS.AA
AND FD.F_DISTANCE IS NOT NULL
), DCS.F_DISTANCE)
WHERE DCS.BATCH_ID=BATCH_ID;
In this case if the result is null the NVL return 0 (you cna change with the value you prefer)
I am using function to update to one column , like
DetailedStatus = dbo.fn_GetProcessStageWiseStatus(PR.ProcessID, PR.ProcessRunID, getdate())
Here 500,000 records are continuously UPDATED in this line. Its like like a loop
So using this function for few records its executing fast but when its 500,000 records executing it becomes very slow...
What can I do to make this execute faster using many records?
Any measures to be taken or any split to be used?
Function:
CREATE FUNCTION [dbo].[fn_GetProcessStageWiseStatus]
(
#ProcessID INT
,#ProcessRunID INT
,#SearchDate SMALLDATETIME
)
RETURNS VARCHAR(100)
AS
BEGIN
DECLARE
#iLoopCount SMALLINT
,#iRowCount SMALLINT
,#StepProgress VARCHAR(100)
,#StepCount SMALLINT
IF EXISTS(
SELECT TOP 1 1
FROM dbo.Step S WITH(NOLOCK)
JOIN dbo.vw_FileGroup FG
ON S.FileConfigGroupID = FG.FileConfigGroupID
WHERE S.ProcessID = #ProcessID
AND S.Active = 1
AND FG.FileConfigGroupActive = 1
AND FG.Direction = 'Inbound'
)
BEGIN
SET #StepProgress = 'Not Received'
END
ELSE
BEGIN
SET #StepProgress = 'Not Started'
END
DECLARE #StepRunDetailsTable TABLE
(
KeyNo INT IDENTITY(1,1)
,StepID INT
,StepStartTime SMALLDATETIME
,StepEndTime SMALLDATETIME
,SourceEnv VARCHAR(100)
,DestEnv VARCHAR(100)
)
INSERT INTO #StepRunDetailsTable
SELECT
S.StepID
,MAX(isnull(SR.StepStartTime, '06/06/2079'))
,MAX(isnull(SR.StepEndTime, '06/06/2079'))
,isnull(SENV.EnvironmentName, '')
,isnull(DENV.EnvironmentName, '')
FROM dbo.ProcessRun PR WITH(NOLOCK)
JOIN dbo.StepRun SR WITH(NOLOCK)
ON SR.ProcessRunID = PR.ProcessRunID
JOIN dbo.vw_StepHierarchy SH
ON SR.StepID = SH.StepID
AND SH.Active = 1
JOIN dbo.Step S WITH(NOLOCK)
ON SH.StepID = S.StepID
JOIN dbo.WorkFlow WF WITH(NOLOCK)
ON S.WorkFlowID = WF.WorkFlowID
AND WF.Active = 1
JOIN dbo.Environment SENV WITH(NOLOCK)
ON SENV.EnvironmentID = WF.SourceEnvironmentID
AND SENV.Active = 1
JOIN dbo.Environment DENV WITH(NOLOCK)
ON DENV.EnvironmentID = WF.DestinationEnvironmentID
AND DENV.Active = 1
WHERE PR.ProcessRunID = #ProcessRunID
GROUP BY S.StepID, SENV.EnvironmentName, DENV.EnvironmentName, SH.StepOrder
ORDER BY SH.StepOrder ASC
SELECT #StepCount = COUNT(*)
FROM dbo.ProcessRun PR WITH(NOLOCK)
JOIN dbo.Step S WITH(NOLOCK)
ON PR.ProcessID = S.ProcessID
AND PR.ProcessRunID = #ProcessRunID
AND S.Active = 1
SELECT #iRowCount = COUNT(DISTINCT StepID) FROM #StepRunDetailsTable
SET #iLoopCount = 0
WHILE (#iRowCount > #iLoopCount)
BEGIN
SET #iLoopCount = #iLoopCount + 1
SELECT
#StepProgress =
CASE
--WHEN #SearchDate BETWEEN StepStartTime AND StepEndTime
WHEN #SearchDate >= StepStartTime AND #SearchDate <= StepEndTime
THEN DestEnv + ' Load in Progress'
WHEN #SearchDate > StepEndTime AND #iLoopCount < #StepCount
THEN 'Waiting on next step - Loaded to ' + DestEnv
WHEN #SearchDate > StepEndTime AND #iLoopCount = #StepCount
THEN 'Completed'
WHEN #SearchDate < StepStartTime AND #iLoopCount = 1
THEN 'Load Not Started'
ELSE #StepProgress
END
FROM #StepRunDetailsTable
WHERE KeyNo = #iLoopCount
END
RETURN #StepProgress
END
Thanks in advance.
Seems like you have a change in execution plan when you try to update 500k rows.
You can try and set forceseek hint on the from clause to force using seeks instead of scans.
Also, WHILE (#iRowCount > #iLoopCount) should be replaced with if exists, because you basically check for certain conditions on the results table and you need to return as early as possible.
I see that you use nolock hint everywhere to allow dirty reads, you can set isolation level read uncommitted in the calling stored procedure and remove all of those; or consider to change the database to set read_committed_snapshot on to avoid locks.
By the way, scalar function calls in SQL Server are very expensive, so if you have some massive updates/selects happening in a loop where you call a function you have to avoid using functions as much as possible.
After you declare a variable of type Datetime, the result as the query is successful. But also, I get the following error in end-stage Tiger2 Logo.
"incorrect syntax near the keyword 'declare' Native error:42000(156)"
The code is as follows.
DECLARE #Tarih1 DATETIME
DECLARE #Tarih2 DATETIME
SET #Tarih1 = Convert(DATETIME,'01.08.2011',104)
SET #Tarih2 = Convert(DATETIME,'30.09.2099',104)
SELECT
Convert(Varchar,PLN.DATE_,104) AS 'Vade_TARİHİ',
Convert(Varchar,PLN.PROCDATE,104) AS 'İşlem_TARİHİ',
PLN.PAYNO AS 'Ö.D.P.SATIR NO',
CL.TRANNO AS 'Fiş_No',
BANK.CODE AS BANKA_KODU,
BANK.DEFINITION_ AS BANKA,
HESAP.CODE AS HESAP_KODU,
HESAP.DEFINITION_ AS HESAP_AÇIKLAMASI,
CC.CODE AS Öğrenci_No,
CC.DEFINITION_ AS ÜNVANI,
PLN.TOTAL AS 'HS.Düşmesi_Gereken',
CL.AMOUNT AS 'POS_dan_Çekilen'
FROM LG_011_01_PAYTRANS AS PLN
JOIN LG_011_BANKACC AS HESAP ON HESAP.LOGICALREF=PLN.BANKACCREF
JOIN LG_011_BNCARD AS BANK ON BANK.LOGICALREF = HESAP.BANKREF
JOIN LG_011_CLCARD AS CC ON CC.LOGICALREF=PLN.CARDREF
LEFT OUTER JOIN LG_011_01_CLFLINE AS CL ON CL.LOGICALREF=PLN.FICHEREF
WHERE PLN.TRCODE=70 AND PLN.DATE_ BETWEEN #Tarih1 AND #Tarih2