Executing an update statement with a select subquery clause in C - mysql

I have the following sql that I run in C:
snprintf(sql, 200, "update rec set name = (select name from pers where id = %d )
where id = %d",rec_id , emp_id );
mysql_query(conn, sql) returns a successful result but it's putting 1 in the "rec" table in the "name" field instead of the name, but when I printf the output and use it in MySQL it's working fine.
update rec set name = (select name from pers where id = 104 ) where id = 43
Is there something wrong with my sprintf? Or something has to be added?
I also tried static sql command like this
snprintf(sql,"update rec set name = (select name from pers where id = 104 ) where id = 43");
and it also put 1 in the rec.name

Is that due to count of record returned by the sub query? Can you verify by putting a condition which returns e.g. 2 records so that the name is set to 2? if this is the reason then (though less performing approach) try splitting the queries and see if it works this time.

Related

How do i batch multiple select query calls into a single mysql query or procedure

I have this function which checks friendship status between 2 users using their userIds and it is working fine.
function checkFriendShipBetweenUsers(user1Id, user2Id) {
var checkFriendShipBetweenUsersQuery = "SELECT status FROM friends WHERE (user1Id=? AND user2Id =?) OR (user1Id=? AND user2Id =?)"
var queryParameterList = [user1Id, user2Id, user2Id, user1Id]
}
I have a case in which i need to check friendship status between a user and other 3 users.
I can call above function 3 times, one for each other user to get desired result but i would like to make it with a single db call using a single query or using a mysql procedure.
function checkFriendShipBetweenUsers(user1Id, userIdList) {
var checkFriendShipBetweenUsersQuery = ""
var queryParameterList = []
}
So this query/procedure call should return 3 integers indicating user1's friendship status with users in userIdList.
Here is an example db fiddle:
db-fiddle.com/f/p5RP61V3AcawRgJcogeXey/1
given user1Id : 'a8t57h6p8n2efden' and
userIdList : ['typ3vg6xb1vt7nw2', 'cy6mqqyykpldc2j1g5vm5cqsi6x1dgrl', '0bw87kprb97pes1crom8ceodi07r2kd0']
How do i write such query or procedure?
DEMO
-- source data
CREATE TABLE test (
id INT,
user1Id VARCHAR(100),
user2Id VARCHAR(100),
status INT
);
INSERT INTO test (id,user1Id,user2Id,status) VALUES
(1,'a8t57h6p8n2efden','typ3vg6xb1vt7nw2',0),
(2,'cy6mqqyykpldc2j1g5vm5cqsi6x1dgrl','a8t57h6p8n2efden',1),
(3,'0bw87kprb97pes1crom8ceodi07r2kd0','a8t57h6p8n2efden',2),
(4,'a8t57h6p8n2efden','ap21wzbew0bprt5t',0);
SELECT * FROM test;
id
user1Id
user2Id
status
1
a8t57h6p8n2efden
typ3vg6xb1vt7nw2
0
2
cy6mqqyykpldc2j1g5vm5cqsi6x1dgrl
a8t57h6p8n2efden
1
3
0bw87kprb97pes1crom8ceodi07r2kd0
a8t57h6p8n2efden
2
4
a8t57h6p8n2efden
ap21wzbew0bprt5t
0
-- searching parameters
SET #user1Id := 'a8t57h6p8n2efden';
SET #userIdList := '[
"typ3vg6xb1vt7nw2",
"cy6mqqyykpldc2j1g5vm5cqsi6x1dgrl",
"0bw87kprb97pes1crom8ceodi07r2kd0",
"absent value"
]';
SELECT jsontable.userid, test.status
FROM JSON_TABLE( #userIdList,
'$[*]' COLUMNS ( rowid FOR ORDINALITY,
userid VARCHAR(255) PATH '$'
)) jsontable
LEFT JOIN test
ON (#user1Id, jsontable.userid) IN ( (test.user1Id, test.user2Id),
(test.user2Id, test.user1Id)
)
userid
status
typ3vg6xb1vt7nw2
0
cy6mqqyykpldc2j1g5vm5cqsi6x1dgrl
1
0bw87kprb97pes1crom8ceodi07r2kd0
2
absent value
null
fiddle
If you do not need status value for the IDs which are not found then use INNER JOIN.
If you want to receive the output as one solid value then add according GROUP BY and aggregation. Use jsontable.rowid for to provide needed values ordering.
PS. If you won't use an aggregation then you may do not obtain rowid value - simply remove rowid FOR ORDINALITY, in this case.

Update query in SQL: command not ended properly

update fare_strategy set sales_date_to = ’07-SEP-22’
where dep_date_to is not null
and market_id in
(select market_id
from fare_strategy_markets
where set_type = ‘STANDARD’
);
In the following query, I'm getting error as SQL command not properly ended.
try to change like this because in your query you used ’ this is not valid so i just change it to ' so it's works fine
update fare_strategy set sales_date_to = '07-SEP-22' where dep_date_to is
not null and market_id in (select market_id from
fare_strategy_markets where set_type = 'STANDARD');

MySQL user-defined function returns incorrect value when used in a SELECT statement

I met a problem when calling a user-defined function in MySQL. The computation is very simple but can't grasp where it went wrong and why it went wrong. Here's the thing.
So I created this function:
DELIMITER //
CREATE FUNCTION fn_computeLoanAmortization (_empId INT, _typeId INT)
RETURNS DECIMAL(17, 2)
BEGIN
SET #loanDeduction = 0.00;
SELECT TotalAmount, PeriodicDeduction, TotalInstallments, DeductionFlag
INTO #totalAmount, #periodicDeduction, #totalInstallments, #deductionFlag
FROM loans_table
WHERE TypeId = _typeId AND EmpId = _empId;
IF (#deductionFlag = 1) THEN
SET #remaining = #totalAmount - #totalInstallments;
IF(#remaining < #periodicDeduction) THEN
SET #loanDeduction = #remaining;
ELSE
SET #loanDeduction = #periodicDeduction;
END IF;
END IF;
RETURN #loanDeduction;
END;//
DELIMITER ;
If I call it like this, it works fine:
SELECT fn_computeLoanAmortization(3, 4)
But if I call it inside a SELECT statement, the result becomes erroneous:
SELECT Id, fn_computeLoanAmortization(Id, 4) AS Amort FROM emp_table
There's only one entry in the loans_table and the above statement should only result with one row having value in the Amort column but there are lots of random rows with the same Amort value as the one with the matching entry, which should not be the case.
Have anyone met this kind of weird dilemma? Or I might have done something wrong from my end. Kindly enlighten me.
Thank you very much.
EDIT:
By erroneous, I meant it like this:
loans_table has one record
EmpId = 1
TypeId = 2
PeriodicDeduction = 100
TotalAmount = 1000
TotalInstallments = 200
DeductionFlag = 1
emp_table has several rows
EmpId = 1
Name = Paolo
EmpId = 2
Name = Nikko
...
EmpId = 5
Name = Ariel
when I query the following statements, I get the correct value:
SELECT fn_computeLoanAmortization(1, 2)
SELECT Id, fn_computeLoanAmortization(Id, 2) AS Amort FROM emp_table WHERE EmpId = 1
But when I query this statement, I get incorrect values:
SELECT Id, fn_computeLoanAmortization(Id, 2) AS Amort FROM emp_table
Resultset would be:
EmpId | Amort
--------------------
1 | 100
2 | 100 (this should be 0, but the query returns 100)
3 | 100 (same error here)
...
5 | 100 (same error here up to the last record)
Inside your function, the variables you use to retrieve the values from the loans_table table are not local variables local to the function but session variables. When the select inside the function does not find any row, those variables still have the same values as from the previous execution of the function.
Use real local variables instead. In order to do that, use the variables names without # as a prefix and declare the variables at the beginning of the function. See this answer for more details.
I suspect the problem is that the variables in the INTO are not re-set when there is no matching row.
Just set them before the INTO:
BEGIN
SET #loanDeduction = 0.00;
SET #totalAmount = 0;
SET #periodicDeduction = 0;
SET #totalInstallments = 0;
SET #deductionFlag = 0;
SELECT TotalAmount, PeriodicDeduction, TotalInstallments, DeductionFlag
. . .
You might just want to set them to NULL.
Or, switch your logic to use local variables:
SET v_loanDeduction = 0.00;
SET v_totalAmount = 0;
SET v_periodicDeduction = 0;
SET v_totalInstallments = 0;
SET v_deductionFlag = 0;
And so on.

Error creating a SP with temporal table inside and subquery

I've created this temporal table in my store procedure, as you can see I have more than 1 records for the same ID:
#tmpTableResults
TmpInstallerID TmpConfirmDate TmpConfirmLocalTime
============== ============== ===================
173 2011-11-08 11:45:50
278 2011-11-04 09:06:26
321 2011-11-08 13:21:35
321 2011-11-08 11:44:54
483 2011-11-08 11:32:00
483 2011-11-08 11:31:59
645 2011-11-04 10:03:15
645 2011-11-04 07:03:15
That is the result of the query to create #tmpTableResults
DECLARE #tmpTableResults TABLE
(
TmpInstallerID int,
TmpConfirmDate date,
TmpConfirmLocalTime time
)
DECLARE #tmpTableQuery VarChar(800)
SET #tmpTableQuery = 'select FxWorkorder.INSTALLERSYSID, FxWorkorder.CONFIRMDATE, FxWorkorder.CONFIRMLOCALTIME from FxWorkorder
join install on FxWorkorder.INSTALLERSYSID = install.sysid
join RouteGroupWorkarea on FxWorkorder.WORKAREAGROUPSYSID = RouteGroupWorkarea.IWORKAREA_ID
join RoutingGroup on RouteGroupWorkarea.IRG_ID = RoutingGroup.IRG_IDENTITY
where FxWorkorder.SCHEDULEDDATE > = #StartDate and FxWorkorder.SCHEDULEDDATE <= #EndDate
and FxWorkorder.Jobstatus <> "Unassign"
and FxWorkorder.Jobstatus <> "Route"
and install.FOXTELCODE <> ""
and FxWorkorder.CONFIRMLOCALTIME is not null
and FxWorkorder.CONFIRMDATE <> ""
group by FxWorkorder.INSTALLERSYSID, FxWorkorder.CONFIRMDATE, FxWorkorder.CONFIRMLOCALTIME
order by FxWorkorder.INSTALLERSYSID, FxWorkorder.CONFIRMDATE, FxWorkorder.CONFIRMLOCALTIME desc '
INSERT INTO #tmpTableResults EXEC(#tmpTableQuery)
I'm creating another query to get data from another table and only the first record from the temporal table for the same INSTALLERSYSID
SELECT RoutingGroup.SDESCRIPTION, FxWorkorder.INSTALLERSYSID, FxWorkOrder.JOBSTATUS, Install.FOXTELCODE,
install.NAME, FxWorkOrder.ScheduledDate,
count(*) as TotalJobs, COUNT(CONFIRMDATE) as ConfirmedJobs,
(select TmpInstallerID, TmpConfirmDate, TmpConfirmLocalTime from #tmpTableResults where TmpInstallerID = FxWorkorder.INSTALLERSYSID)
from FxWorkorder
join install on fxworkorder.INSTALLERSYSID = install.sysid
join RouteGroupWorkarea on FxWorkOrder.WORKAREAGROUPSYSID = RouteGroupWorkarea.IWORKAREA_ID
join RoutingGroup on RouteGroupWorkarea.IRG_ID = RoutingGroup.IRG_IDENTITY
where FxWorkorder.SCHEDULEDDATE > = #StartDate and FxWorkorder.SCHEDULEDDATE <= #EndDate
and FxWorkOrder.Jobstatus <> 'Unassign'
and FxWorkOrder.Jobstatus <> 'Route'
and Install.FOXTELCODE <> ''
group by RoutingGroup.SDESCRIPTION,FxWorkOrder.INSTALLERSYSID, FxWorkOrder.JOBSTATUS, Install.FOXTELCODE,install.NAME, FxWorkOrder.ScheduledDate,FxWorkOrder.WORKAREAGROUPSYSID
When I tried to save the sp I got the error
"Only one expression can be specified in the select list when the subquery is not introduced with EXISTS."
I can't see why I got this error. But if I run the query in sql that works. Can someone see the error?
I don't know how your second query works for you ‘in sql’ (where is that supposed to be? do you mean SSMS = SQL Server Management Studio?), but I'm sure it cannot possibly work in any version of SQL Server that exists at the moment. It's because of this subquery in the SELECT list:
(select TmpInstallerID, TmpConfirmDate, TmpConfirmLocalTime from #tmpTableResults where TmpInstallerID = FxWorkorder.INSTALLERSYSID)
The thing is, every expression in the SELECT clause should be scalar, but this subquery returns a row of more than one value. Even if it's only one row, it is illegal there, because it returns several columns. The subquery in that context should return no more than one value, i.e. it should be one column and the result produced should contain either no rows or just one.
You could try this query instead (although I'm not entirely sure without knowing more details about your schema):
SELECT
RoutingGroup.SDESCRIPTION,
FxWorkorder.INSTALLERSYSID,
FxWorkOrder.JOBSTATUS,
Install.FOXTELCODE,
install.NAME, FxWorkOrder.ScheduledDate,
count(*) as TotalJobs, COUNT(CONFIRMDATE) as ConfirmedJobs,
tmp.TmpInstallerID,
tmp.TmpConfirmDate,
tmp.TmpConfirmLocalTime
from FxWorkorder
join install on fxworkorder.INSTALLERSYSID = install.sysid
join RouteGroupWorkarea on FxWorkOrder.WORKAREAGROUPSYSID = RouteGroupWorkarea.IWORKAREA_ID
join RoutingGroup on RouteGroupWorkarea.IRG_ID = RoutingGroup.IRG_IDENTITY
join #tmpTableResults tmp ON tmp.TmpInstallerID = FxWorkorder.INSTALLERSYSID
where FxWorkorder.SCHEDULEDDATE > = #StartDate
and FxWorkorder.SCHEDULEDDATE <= #EndDate
and FxWorkOrder.Jobstatus <> 'Unassign'
and FxWorkOrder.Jobstatus <> 'Route'
and Install.FOXTELCODE <> ''
group by
RoutingGroup.SDESCRIPTION,
FxWorkOrder.INSTALLERSYSID,
FxWorkOrder.JOBSTATUS,
Install.FOXTELCODE,install.NAME,
FxWorkOrder.ScheduledDate,
FxWorkOrder.WORKAREAGROUPSYSID
tmp.TmpInstallerID,
tmp.TmpConfirmDate,
tmp.TmpConfirmLocalTime
That is, I added one more join, the one to #tmpTableResults, as well as added the columns you were trying to pull to the SELECT clause and to the GROUP BY clause.
Also, if I were you I would consider using short aliases for tables, like this:
SELECT
…
wo.INSTALLERSYSID,
wo.JOBSTATUS,
…
from FxWorkorder wo
join …
That might make your queries more readable.

How do I update a table with fields selected from another table?

Although there are many questions similar to this, such as
"Updating a record from another table", but i could not get this working.
I have a query that selects and updates table sem_stdexamfinresmark. The select subquery returns multiple rows of data whose size may not be equal to the table being updated, but the update is now working.
The query looks like :
update sem_stdexamfinresmark sr,
(select
se.currsession,
str.studentid,
str.classid,
str.subjectid,
str.aggScore*(select gbtp.percentage from gb_termpercentage gbtp where gbtp.termname = se.examtype)/100 as aggPer,
str.aggGrade
from
sem_stdexamtermresr str,
sem_exam se
where
str.examid=se.examid and
se.examtype = 'Second Term' and
se.currsession =1 and classid='8'
) s
set
sr.SecondTermMark = s.aggPer and
sr.SecondTermGrade = s.aggGrade
where
sr.studentid=s.studentid and
sr.subjectid=s.subjectid and
s.currsession = s.currsession and
sr.classid='8';
EDIT:
update sem_stdexamfinresmark
set
sr.SecondTermMark = s.aggPer and
sr.SecondTermGrade = s.aggGrade
from
(select
se.currsession,
str.studentid,
str.classid,
str.subjectid,
str.aggScore*(select gbtp.percentage from gb_termpercentage gbtp where gbtp.termname = se.examtype)/100 as aggPer,
str.aggGrade
from
sem_stdexamtermresr str,
sem_exam se
where
str.examid=se.examid and
se.examtype = 'Second Term' and
se.currsession = 1 and classid='8'
) s
where
sr.studentid=s.studentid and
sr.subjectid=s.subjectid and
s.currsession =1 and
sr.classid='8';
select * from sem_exam;
update sem_exam set currsession =1;
try something that looks more like:
update foo
set col = bar.col
from bar
where ...
This is what happens when one loses sleep :( I just did a silly mistake here and added "and"