mysql constraint or trigger - mysql

How to make sure that a couple of rows (A,B) values can be duplicated but can have only one corresponding value in row C in the same table ?
Suppose i am inserting these rows in this order this the output i want to have.
EDIT:
what i want is that when A,B,C is inserted for the first time value in C will be the unique possible value for the couple (A,B)
this means, if i, insert (0,0) with C = 1 when there is no other (0,0) couples in (A,B) then the row is accepted.But if i add (0,0) for the second(third ..) time; then C has to be equal to 1.
example :
A | B | C | D | F ...
_________________
0 | 0 |1
0 | 0 |1
0 | 0 |2 --> not allowed
1 | 0 |3 --> allowed
1 | 0 |2 --> not allowed
1 | 0 |3 --> allowed

try this trigger
DELIMITER $$
CREATE TRIGGER wtf_dupes BEFORE INSERT ON your_table
FOR EACH ROW
BEGIN
SET #ok := TRUE;
SELECT FALSE INTO #ok FROM your_table
WHERE
A = new.A
AND B = new.B
AND C <> new.C
LIMIT 1
;
IF NOT #ok THEN
SIGNAL SQLSTATE '23000' SET MESSAGE_TEXT = 'YourMessageAboutDupeError';
END IF;
END $$
DELIMITER ;
about how to trap signals you should do your own investigation:
http://dev.mysql.com/doc/refman/5.5/en/signal.html#signal-effects

Although there is a way to create a trigger that checks another table or view
for already existing value combinations, there is a question on canceling insert from within a trigger in MySQL and the accepted answer says that there is no such feature. So I think you have to implement this in application logic or move the insert to a procedure.

Related

Trigger to update a counter when data is entered in another table's column

Let's say I have a table named Count and a table named Records.
Count table:-
| countRecords | typeRecord |
|--------------|--------------------|
| 0 | type of record |
Records table:-
| ID | recordType |
|------------|------------------|
| id | type of record |
I want to update the countRecords as per the type in recordType in table Records. Whenever a user enters a recordType, I want to update the counter for it in Count table and whenever a user deletes a row/entry, I want to decrement the counter. How do I do this using a trigger?
Basically you need two triger
The insert trigger, as long as it only needs to update a row, can be done so.
If your database is more complex and you have fpor example an empty recordType , you need more code
CREATE TRIGGER after_recods_insert
AFTERINSERT
ON recods FOR EACH ROW
UPDATE count_table SET countRecords = countRecords +1 WHERE typeRecord = NEW.recordType ;
AN UPDATE Trigger ist somewhat more complex as you need to change teh count when the type changes
DELIMITER $$
CREATE TRIGGER after_recods_UPDATE
AFTER UPDATE
ON recods FOR EACH ROW
BEGIN
IF (OLD.recordType <> NEW.recordType) THEN
UPDATE count_table SET countRecords = countRecords -1 WHERE typeRecord = OLD.recordType ;
UPDATE count_table SET countRecords = countRecords +1 WHERE typeRecord = NEW.recordType ;
END IF;
END$$
DELIMITER ;
Serg is right, to complte the set
CREATE TRIGGER after_recods_delete
AFTER DELETE
ON recods FOR EACH ROW
UPDATE count_table SET countRecords = countRecords - 1 WHERE typeRecord = OLD.recordType ;

Trigger "AFTER INSERT" doesn't work, after insertion if I Add values in tables?

Purpose of trigger:
I should +add some number 50 to that user to table money where in table paym both columns table1 and table2 are not empty.
For example: User 'John' has both columns not empty and to him added 50 in table money.
Example in table below:
table: paym
ID username table1 Table2
+-------+-------------+-------------+-----------+
| 1 | John | Value | Value |
+-------+-------------+-------------+-----------+
| 2 | Alex | Null | Null |
+-------+-------------+-------------+-----------+
Table: money
ID username total_money
+-------+-------------+-------------+
| 1 | John | 50 |
+-------+-------------+-------------+
| 2 | Alex | 0 |
+-------+-------------+-------------+
Trigger below, works perfectly only when we insert all tables at one time. But it doesn't work if you insert only username two tables empty and after insertion, if you add values to empty tables table1 and table2 triggers not works at this point! Can we solve this problem???
Trigger should work even if we add value to the table After insertion!
DELIMITER $$
CREATE trigger update_money_after_paym
AFTER INSERT ON paym
FOR EACH ROW
BEGIN
IF (NEW.table1 IS NOT NULL AND NEW.table2 IS NOT NULL) THEN
UPDATE money SET total_money = total_money + 50 WHERE username = NEW.username;
END IF;
END;
$$
DELIMITER;
Not that trigger. It is an insert trigger, so it doesn't get called for an update.
If you want an update trigger, then define one:
DELIMITER $$
CREATE trigger update_money_after_paym
AFTER UPDATE ON paym
FOR EACH ROW
BEGIN
IF (NEW.table1 IS NOT NULL AND NEW.table2 IS NOT NULL) THEN
UPDATE money m
SET total_money = total_money + 50
WHERE m.username = NEW.username;
END IF;
END;
$$
DELIMITER;
This may not do exactly what you want. For instance, you might only want to add 50 when the previous values are both NULL:
DELIMITER $$
CREATE trigger update_money_after_paym
AFTER UPDATE ON paym
FOR EACH ROW
BEGIN
IF (NEW.table1 IS NOT NULL AND NEW.table2 IS NOT NULL AND
OLD.table1 IS NULL AND old.table2 IS NULL) THEN
UPDATE money m
SET total_money = total_money + 50
WHERE m.username = NEW.username;
END IF;
END;
$$
DELIMITER;

Mysql trigger when on update reserved cloumn sub capacity if statements

I want to set check class capacity if will be full class should be
confirm. When I update reserved it give error. Please help. Thank you.
CREATE TRIGGER `control_class_capacity`
AFTER UPDATE ON `learningcenter_class`
FOR EACH ROW BEGIN
IF NEW.capacity - NEW.reserved = 0 THEN BEGIN
UPDATE learningcenter_class SET isconfirm = 1 WHERE class_id = NEW.class_id;
END; END IF;
END
Assuming your class_id is unique you could change the trigger to a before trigger and set NEW.ISCONFIRM. BTW if statements in MYSQL do not require begin and end statements.
drop table if exists t;
create table t(class_id int ,capacity int, reserved int, isconfirm int);
insert into t values (1,1,0,0) , (2,1,0,0);
drop trigger if exists `control_class_capacity`;
delimiter $$
CREATE TRIGGER `control_class_capacity`
before UPDATE ON t
FOR EACH ROW BEGIN
IF NEW.capacity - NEW.reserved = 0 THEN
SET new.isconfirm = 1;
END IF;
END $$
delimiter ;
update t set reserved = 1 where class_id = 1;
select * from t;
+----------+----------+----------+-----------+
| class_id | capacity | reserved | isconfirm |
+----------+----------+----------+-----------+
| 1 | 1 | 1 | 1 |
| 2 | 1 | 0 | 0 |
+----------+----------+----------+-----------+
2 rows in set (0.00 sec)

SQL Trigger update on same table

I want to create a trigger in MySQL for the following table such that if the attribute of occurrences is greater than 100 the attribute of status updates to "popular".
The name of the table is trigger
Repo_ID |Occurences |Status
1 | 50 | Normal
2 | 70 | Normal
3 | 190 | Popular
I've tried the following thing. It didnt work. Any suggestions?
CREATE TRIGGER `A` after update
ON `trigger`
FOR EACH ROW BEGIN
IF (new.occurence > 100) THEN
SET new.STATUS = "popular";
ELSE SET new.STATUS = "normal";
END IF;
END
You want a before update trigger:
CREATE TRIGGER `A` before update ON `trigger`
FOR EACH ROW
BEGIN
SET new.STATUS = (CASE WHEN new.occurences > 100 THEN 'popular' ELSE 'normal' END);
END;
I also removed the IF because CASE seems more concise.

mysql update trigger: update "some" other rows

Table "Book":
bookid | title
1 | Java
2 | MySQL
3 | Zen
Table "BestPage":
pageid | bookid | isbestpage
1 | 1 | 0
2 | 1 | 0
3 | 1 | 1
4 | 2 | 0
5 | 2 | 1
6 | 2 | 0
So some books may have a "bestpage", but only one.
Now I would probably need a beforeupdate trigger so when I update the row with pageid 2, and set isbestpage = 1,
then all the other pages BUT ONLY FOR THAT BOOK will have isbestpage set to 0.
Something like:
for each row
begin
if old.isbestpage = 1 and -- here I want to tell that **only for the current book** !
then
set new.isbestpage = 0
or something like that.
That is, if I mark a page as bestpage, all other pages within this book should be set as not a best page.
Thanks.
Unfortunately you can't do that in a MySql trigger
According to E.1. Restrictions on Stored Programs
Within a stored function or trigger, it is not permitted to modify a
table that is already being used (for reading or writing) by the
statement that invoked the function or trigger.
What you can do though to alleviate some pain is to create a stored procedure like this
DELIMITER $$
CREATE PROCEDURE sp_update_bestpage(IN pid INT)
BEGIN
UPDATE bestpage p JOIN
bestpage p1 ON p.bookid = p1.bookid
SET p.isbestpage = 0
WHERE p1.pageid = pid AND p.pageid <> pid;
UPDATE bestpage
SET isbestpage = 1
WHERE pageid = pid;
END $$
DELIMITER ;
And then use it
CALL sp_update_bestpage(2);
SQLFiddle