MySQL Different Result on WebService Call and WorkBench Call - mysql

I made a Stored Procedure.
When i tested it with workbench call, it worked well. but if i called that
inside webservice call, i got an 1217 result. (defined in procedure)
myTable is made with 3 column (user_no, index, count)
and this procedure is for subtracting multiple row's count.
DECLARE _affected_count INT DEFAULT 0;
IF ( o_ouput1 < i_input1 ) THEN
SET o_result = 1211;
LEAVE proc_body;
ELSEIF ( i_input1 > 0 ) THEN
SET _affected_count = _affected_count + 1;
END IF;
IF ( o_ouput2 < i_input2 ) THEN
SET o_result = 1212;
LEAVE proc_body;
ELSEIF ( i_input2 > 0 ) THEN
SET _affected_count = _affected_count + 1;
END IF;
// Same for input3~input6
UPDATE myTable
SET count = CASE WHEN index = 1 AND i_input1 > 0 AND count >= i_input1 THEN count - i_input1
WHEN index = 2 AND i_input2 > 0 AND count >= i_input2 THEN count - i_input2
WHEN index = 3 AND i_input3 > 0 AND count >= i_input3 THEN count - i_input3
WHEN index = 4 AND i_input4 > 0 AND count >= i_input4 THEN count - i_input4
WHEN index = 5 AND i_input5 > 0 AND count >= i_input5 THEN count - i_input5
WHEN index = 6 AND i_input6 > 0 AND count >= i_input6 THEN count - i_input6
ELSE count END
WHERE user_no = i_user_no AND index IN ( 1, 2, 3, 4, 5, 6 );
IF ( ROW_COUNT() <> _affected_count ) THEN
SET o_result = 1217;
LEAVE proc_body;
END IF;
The Problem is.. If i call this procedure in workbench, it works well.
I can't understand why it's different when i called it with workbench and webmethod.
Is there anybody who can explain this?

I Found An Answer
Use Affected Rows Option in on with Workbench, but not with webservice default.
http://dev.mysql.com/doc/refman/5.5/en//information-functions.html#function_row-count

Related

WHILE conditions are not working properly in MYSQL query?

I am learning MySQL through self-practice. In a project, I want to create a transfer module using MySQL (phpMyAdmin). Unfortunately, the WHERE conditions are not working well. I execute the query using the XAMPP application. A part of the query is -
SELECT
*
FROM
(SELECT
`emp_id`,
`emp_name`,
`present_posting`,
`curr_zone`,
`office_ID1` AS `new_office`,
`Zone1` AS `new_zone`,
`office_ID1` AS `C1`,
`post`,
`preference`,
`curr_zone_id`
FROM
`transfer_applications`
WHERE
`Mutual Accepted` != 'Mutual Accepted'
ORDER BY `apID` ASC) `aa`
LEFT JOIN
(SELECT
`zone_ID`, `ZONE`, `office_ID`, `office_Vacancy`
FROM
`vacancy`) `ab` ON `aa`.`C1` = `ab`.`office_ID`
LEFT JOIN
(SELECT
`zid`, `max_min_vacancy`
FROM
`capping_vacancy`) `ac` ON `aa`.`new_zone` = `ac`.`zid`
WHERE
((`curr_zone_id` != `new_zone`
AND (`max_min_vacancy` < 150
AND `max_min_vacancy` > 1)
AND `station_Vacancy` > 0
AND `post` = 4
AND `apID` = x + 1)
OR (`curr_zone_id` = `new_zone`
AND `station_Vacancy` > 0))
The problem is that it allows transfer even if there is no vacancy available that is the minimum capping in WHERE ( max_min_vacancy > 1 ) is not working. I am unable to find out the reason why it skips this condition while all other conditions in the WHERE are working fine. Kindly help me to find out the mistake. Thanks.
The WHERE clause is connected by an OR, so if the first Boolean expression is FALSE (ie. max_min_vacancy <=1), it is still TRUE as long as the second boolean expression returns TRUE.
...
WHERE
(
(
`curr_zone_id` != `new_zone` AND
(
`max_min_vacancy` < 150 AND
`max_min_vacancy` > 1 -- if max_min_vacancy <= 1 --> FALSE
) AND
`station_Vacancy` > 0 AND
`post` = 4 AND
`apID` = x + 1
)
OR ( -- But this condition is TRUE
`curr_zone_id` = `new_zone` AND
`station_Vacancy` > 0
)
)

How to find greatest value in a column and display it with a "Greatest Value" Flag and display the rest of the new column value as "Not Greatest"

I have a table UnitCheck:
enter code here
I want to add a new column which will return me a value Greatest if the CostToRestaff value is the highest and should a return a value Not Greatest for every other value of`enter code here CostToRestaff.
CostToRestaff is a calculated column with the formula: 0 * FullDutyC + 10 * WoundedC + 25 * KilledC;
enter code here
edited:
I was trying more on these lines. Any idea where i am going wrong?
''''''
if Unit_ID = A then --A is the user parameter for my procedure
Set check1 = 0 * FullDutyC + 10 * WoundedC + 25 * KilledC;
end if;
if Unit_ID = B then --B is the user parameter for my procedure
Set check2 = 0 * FullDutyC + 10 * WoundedC + 25 * KilledC;
end if;
if Unit_ID = C then --C is the user parameter for my procedure
Set check3 = 0 * FullDutyC + 10 * WoundedC + 25 * KilledC;
end if;
if check1 > check2 AND check1 > check3 then
set Rejection = /* this is where i need the final answer which should be
the value itself for eg: 125 - since it is the highest value*/ where Unit_ID =
A;
elseif check2 > check3 AND check2 > check1 then
Set Rejection = /* this is where i need the final answer in this case since it is not the highest value then it should jump to the else condition*/ where
Unit_ID = B;
elseif check3 > check1 AND check3 > check2 then
Set Rejection = /* this is where i need the final answer in this case since it is not the highest value then it should jump to the else condition*/ where Unit_ID =
C;
else set Rejection = "Not Greatest"
end if;
''''''
Assuming MySQL 8.0, you can use window functions:
select
t.*,
(rank() over(order by CostToRestaff desc) = 1) isGreatest
from mytable t
This gives you a 0/1 flag that indicates if the current is has the greatest value of CostToRestaff across the whole table - which I find more meaningful that string '(Not) Greatest'. If there are top ties, they would all get the 1 flag.
If you want that as a string value:
select
t.*,
case when rank() over(order by CostToRestaff desc) = 1
then 'Greatest'
else 'Not Greatest'
end isGreatest
from mytable t
In earlier versions, you can use a subquery or a join to compute the maximum value:
select
t.*,
(select max(CostToRestaff) from mytable) = CostToRestaff isGreatest
from mytable t

SQL variable returning the same result multiple times

I have a query with two select statements. I need the second select statement to return a result based on the first statement. However the results returned by the second select statement are just the last result of the first selected statement, repeated.
Here is my query:
Declare
#Low numeric (13,0) = 50000,
#High numeric (13,0) = 60000,
#State varchar(2),
#Place varchar(5),
#Gid2 varchar(7);
SELECT
#State = State, #Place = Place
FROM
[SUB-EST2014_ALL]
WHERE
(NOT(SUMLEV = '50')) AND (NOT(COUNTY = 0)) AND (NOT(PLACE = '99990')) AND (ESTIMATESBASE2010 > #Low) AND (ESTIMATESBASE2010 < #High)
Set
#Gid2 = CONCAT((REPLICATE('0',2-LEN(#State)) + #State),(REPLICATE('0',5-LEN(#Place)) + #Place))
SELECT
#Gid2 AS Gid2
From
[SUB-EST2014_ALL]
WHERE
(NOT(SUMLEV = '50')) AND (NOT(COUNTY = 0)) AND (NOT(PLACE = '99990')) AND (ESTIMATESBASE2010 > #Low) AND (ESTIMATESBASE2010 < #High)
If you run the first select statement alone there are 270 results. What I am trying to accomplish is to get 270 unique results from the second query, but what I am getting are the results from the last record in the first query, repeated 270 times.
Can someone help me figure out what I did wrong?
i think this is what you are trying to do
Declare
#Low numeric (13,0) = 50000,
#High numeric (13,0) = 60000,
#Gid2 varchar(7);
SELECT
CONCAT((REPLICATE('0',2-LEN(State)) + State),(REPLICATE('0',5-LEN(Place)) + Place)) Gid2
FROM
[SUB-EST2014_ALL]
WHERE
(NOT(SUMLEV = '50')) AND (NOT(COUNTY = 0)) AND (NOT(PLACE = '99990')) AND (ESTIMATESBASE2010 > #Low) AND (ESTIMATESBASE2010 < #High)
Set
#Gid2 = CONCAT((REPLICATE('0',2-LEN(#State)) + #State),(REPLICATE('0',5-LEN(#Place)) + #Place))
SELECT
#Gid2 AS Gid2
From
[SUB-EST2014_ALL]
WHERE
(NOT(SUMLEV = '50')) AND (NOT(COUNTY = 0)) AND (NOT(PLACE = '99990')) AND (ESTIMATESBASE2010 > #Low) AND (ESTIMATESBASE2010 < #High)
that would just present the value of #Gid2 for any record returned from the query. try select * or select any column from that table

Update multiple rows, but only first row with different value

table
create table tst(locationId int,
scheduleCount tinyint(1) DEFAULT 0,
displayFlag tinyint(1) DEFAULT 0);
INSERT INTO tst(locationId,scheduleCount)
values(5,0),(2,0),(5,1),(5,2),(2,1),(2,2);
I update multiple rows and multiple columns with one query, but want to change the one of the columns only for the first row and keep the other things the same for that column.
I want to update all the rows with some location id and change displayFlag to 1 and increment scheduleCount of only the top entry with 1 , rest would remain the same
**Query **
update tst,(select #rownum:=0) r,
set tst.displayFlag =1,
scheduleCount = (CASE WHEN #rownum=0
then scheduleCount+1
ELSE scheduleCount
END),
#rownum:=1 where locationId = 5
But it gives error and does not set the user defined variable rownum, I am able to join the tables in a select and change the value of the rownum, is there any other way to update the values.
I'm not sure this is the correct way of doing such a thing, but it is possible to include the user variable logic in the CASE condition:
UPDATE tst
JOIN (SELECT #first_row := 1) r
SET tst.displayFlag = 1,
scheduleCount = CASE
WHEN #first_row = 1 AND ((#first_row := 0) OR TRUE) THEN scheduleCount+1
ELSE scheduleCount
END
WHERE locationId = 5;
I have used a #first_row flag as this is more inline with your initial attempt.
The CASE works as follows:
On the first row #first_row = 1 so the second part of the WHEN after AND is processed, setting #first_row := 0. Unfortunately for us, the assignment returns 0, hence the OR TRUE to ensure the condition as a whole is TRUE. Thus scheduleCount + 1 is used.
On the second row #first_row != 1 so the condition is FALSE, the second part of the WHEN after AND is not processed and the ELSE scheduleCount is used.
You can see it working in this SQL Fiddle. Note; I have had to set the column types to TINYINT(3) to get the correct results.
N.B. Without an ORDER BY there is no guarantee as to what the '1st' row will be; not even that it will be the 1st as returned by a SELECT * FROM tst.
UPDATE
Unfortunately one cannot add an ORDER BY if there is a join.. so you have a choice:
Initialise #first_row outside the query and remove the JOIN.
Otherwise you are probably better off rewriting the query to something similar to:
UPDATE tst
JOIN (
SELECT locationId,
scheduleCount,
displayFlag,
#row_number := #row_number + 1 AS row_number
FROM tst
JOIN (SELECT #row_number := 0) init
WHERE locationId = 5
ORDER BY scheduleCount DESC
) tst2
ON tst2.locationId = tst.locationId
AND tst2.scheduleCount = tst.scheduleCount
AND tst2.displayFlag = tst.displayFlag
SET tst.displayFlag = 1,
tst.scheduleCount = CASE
WHEN tst2.row_number = 1 THEN tst.scheduleCount+1
ELSE tst.scheduleCount
END;
Or write two queries:
UPDATE tst
SET displayFlag = 1
WHERE locationId = 5;
UPDATE tst
SET scheduleCount = scheduleCount + 1
WHERE locationId = 5
ORDER BY scheduleCount DESC
LIMIT 1;

How to make function execute faster in SQL?

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.