mysql: updating/adding to a column in the same table - mysql

I have a table
calls DATE(DATE) GENDER(VARCHAR(1)) NAME(VARCHAR(100))
I want to do this :
UPDATE calls WHERE GENDER="M" SET NAME = CONCAT("sir: ",NAME) ;
UPDATE calls WHERE GENDER="F" SET NAME = CONCAT("mrs: ",NAME) ;
but it is not working, How to do it ?

You can even do this in a single statement for both cases
update calls set name = case
when gender = 'f' then concat('mrs: ', name)
when gender = 'm' then concat('mr: ', name)
else name
end;
See this fiddle
https://www.db-fiddle.com/f/q2FtjGusyjdL2xPJuGtSJK/3

UPDATE calls SET NAME = CONCAT("sir: ",NAME) WHERE GENDER="M" ;
use set name before the where clause

Related

update a table after inserting a value in the same table using triggers [duplicate]

I am running a MySQL Query. But when a new row is added from form input I get this error:
Error: Can't update table 'brandnames' in stored function/trigger because it is
already used by statement which invoked this stored function/trigger.
From the code:
CREATE TRIGGER `capital` AFTER INSERT ON `brandnames`
FOR EACH
ROW UPDATE brandnames
SET bname = CONCAT( UCASE( LEFT( bname, 1 ) ) , LCASE( SUBSTRING( bname, 2 ) ) )
What does this error mean?
You cannot change a table while the INSERT trigger is firing. The INSERT might do some locking which could result in a deadlock. Also, updating the table from a trigger would then cause the same trigger to fire again in an infinite recursive loop. Both of these reasons are why MySQL prevents you from doing this.
However, depending on what you're trying to achieve, you can access the new values by using NEW.fieldname or even the old values --if doing an UPDATE-- with OLD.
If you had a row named full_brand_name and you wanted to use the first two letters as a short name in the field small_name you could use:
CREATE TRIGGER `capital` BEFORE INSERT ON `brandnames`
FOR EACH ROW BEGIN
SET NEW.short_name = CONCAT(UCASE(LEFT(NEW.full_name,1)) , LCASE(SUBSTRING(NEW.full_name,2)))
END
The correct syntax is:
FOR EACH ROW SET NEW.bname = CONCAT( UCASE( LEFT( NEW.bname, 1 ) )
, LCASE( SUBSTRING( NEW.bname, 2 ) ) )
A "BEFORE-INSERT"-trigger is the only way to realize same-table updates on an insert, and is only possible from MySQL 5.5+. However, the value of an auto-increment field is only available to an "AFTER-INSERT" trigger - it defaults to 0 in the BEFORE-case. Therefore the following example code which would set a previously-calculated surrogate key value based on the auto-increment value id will compile, but not actually work since NEW.id will always be 0:
create table products(id int not null auto_increment, surrogatekey varchar(10), description text);
create trigger trgProductSurrogatekey before insert on product
for each row set NEW.surrogatekey =
(select surrogatekey from surrogatekeys where id = NEW.id);
#gerrit_hoekstra wrote: "However, the value of an auto-increment field is only available to an "AFTER-INSERT" trigger - it defaults to 0 in the BEFORE-case."
That is correct but you can select the auto-increment field value that will be inserted by the subsequent INSERT quite easily. This is an example that works:
CREATE DEFINER = CURRENT_USER TRIGGER `lgffin`.`variable_BEFORE_INSERT` BEFORE INSERT
ON `variable` FOR EACH ROW
BEGIN
SET NEW.prefixed_id = CONCAT(NEW.fixed_variable, (SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'lgffin'
AND TABLE_NAME = 'variable'));
END
I have the same problem and fix by add "new." before the field is updated. And I post full trigger here for someone to want to write a trigger
DELIMITER $$
USE `nc`$$
CREATE
TRIGGER `nhachung_province_count_update` BEFORE UPDATE ON `nhachung`
FOR EACH ROW BEGIN
DECLARE slug_province VARCHAR(128);
DECLARE slug_district VARCHAR(128);
IF old.status!=new.status THEN /* neu doi status */
IF new.status="Y" THEN
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id;
ELSE
UPDATE province SET `count`=`count`-1 WHERE id = new.district_id;
END IF;
ELSEIF old.province_id!=new.province_id THEN /* neu doi province_id + district_id */
UPDATE province SET `count`=`count`+1 WHERE id = new.province_id; /* province_id */
UPDATE province SET `count`=`count`-1 WHERE id = old.province_id;
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id; /* district_id */
UPDATE province SET `count`=`count`-1 WHERE id = old.district_id;
SET slug_province = ( SELECT slug FROM province WHERE id= new.province_id LIMIT 0,1 );
SET slug_district = ( SELECT slug FROM province WHERE id= new.district_id LIMIT 0,1 );
SET new.prov_dist_url=CONCAT(slug_province, "/", slug_district);
ELSEIF old.district_id!=new.district_id THEN
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id;
UPDATE province SET `count`=`count`-1 WHERE id = old.district_id;
SET slug_province = ( SELECT slug FROM province WHERE id= new.province_id LIMIT 0,1 );
SET slug_district = ( SELECT slug FROM province WHERE id= new.district_id LIMIT 0,1 );
SET new.prov_dist_url=CONCAT(slug_province, "/", slug_district);
END IF;
END;
$$
DELIMITER ;
Hope this help someone

Use Case statement inside if else block in mysql triggers

I am new to the mysql triggers.
Let assume if i have a table name teachers contains
teacher_id,
teacher_name,
description,
student_id,
class,
student_year
I want to create a AFTER INSERT and AFTER UPDATE triggers on teachers table.
for that i have a table name called teacherslogs with id,teacher_id,student_year,class,student_id columns
so whenever record insert into teachers table it should insert into teacherslogs.(for this trigger able to write)
But for after update trigger facing issue.
Requirement:
whenever student_id changed in teachers table we need to insert a record into teacherslogs with along another columns changes in the teachers table for that record
for this i have written like this
IF ((NEW.student_id <=> OLD.student_id) = 0) Then
select student_id,class,student_year into student_id_,class_,year_ from `employees`.`teachers` where teacher_id = OLD.teacher_id;
Insert into `employees`.`teacherlogs`(teacher_id,student_year,class,student_id) values (OLD.teacher_id,year_,class_,student_id_);
END IF;
But whenever changes in other columns like class,student_year we need to update the teacherslogs table for that record where teacher_id and student_id
Final Trigger Query
create trigger `updateteacherlogs`
AFTER UPDATE ON `employees`.`teacher` FOR EACH ROW
BEGIN
DECLARE teacher_id_ int(11);
Declare student_id_ int(11);
Declare class_ varchar(150);
Declare year_ int(11);
Declare dummy tinyint;
IF ((NEW.student_id <=> OLD.student_id) = 0) Then
select student_id,class,student_year into student_id_,class_,year_ from `employees`.`teachers` where teacher_id = OLD.teacher_id;
Insert into `employees`.`teacherlogs`(teacher_id,student_year,class,student_id) values (OLD.teacher_id,year_,class_,student_id_);
ELSE
CASE WHEN (NEW.student_year <=> OLD.student_year) = 0
THEN update `teacherlogs` set student_year = NEW.student_year where student_id=OLD.student_id and teacher_id = OLD.teacher_id;
WHEN (NEW.class <=> OLD.class) = 0
THEN update `teacherlogs` set class = NEW.class where student_id=OLD.student_id and teacher_id = OLD.teacher_id
ELSE select #dummy END
end if;
END
But i am getting an exception at end if.
is that correct way to solve my problem or any other ways can we do?
The reason for your syntax error is that your CASE statement needs to end in END CASE;, not just END.
I don't think that the CASE statement actually works for your requirements though as if NEW.student_year <=> OLD.student_year then NEW.class will not get compared against OLD.class to see if that value also needs to be updated. That is because (from the manual):
For the second syntax, each WHEN clause search_condition expression is
evaluated until one is true, at which point its corresponding THEN
clause statement_list executes
You can get around that by just replacing the ELSE CASE ... with an ELSEIF clause:
ELSEIF NEW.student_year <=> OLD.student_year OR NEW.class <=> OLD.class THEN
UPDATE teacherlogs
SET student_year = NEW.student_year, class = NEW.class
WHERE student_id = OLD.student_id AND teacher_id = OLD.teacher_id;
This should work because (based on my understanding from your question of how your database is configured) the value of student_year and class in teacherlogs should be the same as OLD.student_year and OLD.class and if they are the same as NEW.student_year and NEW.class the values won't get updated.
If my understanding is incorrect, you will need modify the update to have conditions on each value:
ELSE
UPDATE teacherlogs
SET student_year = IF(NEW.student_year <=> OLD.student_year, NEW.student_year, student_year),
class = IF(NEW.class <=> OLD.class, NEW.class, class)
-- repeat for all columns
WHERE student_id = OLD.student_id AND teacher_id = OLD.teacher_id;
END IF;

change one table data when single column all data of another table is equal to some value in mysql

I have created 2 tables named snag_list and defect_list. I need to change the status field of snag_list to 2 when all the defect_list status should to be 2
Not sure if this helps but try to create a trigger for defect_list
and check the distinct count of status column if it is one and the value is 2 then update the snag_list a example would look like this
DELIMITER $$
CREATE TRIGGER checkstatus
AFTER UPDATE ON defect_list
FOR EACH ROW
BEGIN
DECLARE cnt INT
SELECT COUNT(DISTINCT status) FROM defect_list INTO cnt
DECLARE st INT
SELECT DISTINCT status FROM defect_list LIMIT 1 INTO st
IF(cnt = 1 AND st = 2)
UPDATE snag_list SET status = 2
ENF IF
END$$
DELIMITER ;
Your question is very vague but I guess this is what you may be looking for.
DECLARE
count_rec VARCHAR2(10);
data_rec VARCHAR2(10);
BEGIN
SELECT COUNT(DISTINCT status) INTO count_rec FROM defect_list;
SELECT DISTINCT status INTO data_rec FROM defect_list;
IF (count_rec = '1' AND data_rec = '2') THEN
UPDATE snag_list SET status = '2';
END IF;
END;
edit -> You can change the datatype of the 2 variables as required. Go with VARCHAR2 if you're unsure whether the data would be numeric.

How to retrieve all data from table in MySQL if column value providing null value?

I would like to retrieve all data from table in MySQL if column value providing null value?
I have a table like country.
How to write a query
If country = ' ' I need to display all data in table.
If country='algeria', it will display the particular data.
I need both queries in a single query.
i am getting result .but without providing variable how to write query...
declare #country1 varchar(30)
set #country1 = 'asd'
SELECT country_id, country
FROM country
WHERE ((#country1 = '') or (#country1 != '' and country.country= #country1));
nulls are different than empty strings (''), and should be checked explicitly with the is operator.
Assuming the variable you're passing is :country:
SELECT country_id, country
FROM country
WHERE (:country IS NULL) or (:country = country.country)
If you have an input like :country:
select
country.country_id, country.country
from
country
where
country.country = case when TRIM(:country) = '' or :country IS NULL then country.country else :country end
DELIMITER $$
CREATE PROCEDURE sp1 (x VARCHAR(30))
BEGIN
SELECT
country.country_id, country.country
FROM
country
WHERE
country.country = CASE WHEN TRIM(x) = '' OR x IS NULL THEN country.country ELSE x END;
END;
$$
DELIMITER ;
call sp1('COUNTRY');

How to change the column set in an update statement

I have a table that I need to update depending on whether a field is empty or not.
If it is empty, I need to set column b, else I need to set column c.
However, I can't seem to get it to work as the idea I had will result in a syntax error.
The following is the idea of the query that I have in mind:
UPDATE table_a SET
(IF a = '', 'b', 'c') = 'test';
I will also need to get a count of the rows updated, therefore I hope that I will be able to update the table by just using 1 update statement.
Thanks in advance
Use CASE statement like this:
UPDATE table_a
SET b =
CASE WHEN a = ''
THEN 'test'
ELSE b
END
, c =
CASE WHEN a <> ''
THEN 'test'
ELSE c
END
Working Demo: http://sqlfiddle.com/#!2/a823d/1
How it works:
Using CASE you check if a = '' then SET b = 'test otherwise SET b = b. Same is done with the column c.