MySQL create trigger on insert in tbl1 also insert to tbl2 - mysql

I'm currently working with a client that wants their database to duplicate info into a second table in a different format when it is initially inserted.
Basically like the following:
Table 1
| ID | NAME | EMAIL | password |
--------------------------------------
| 1 | david | x#x.co | asx234 |
| 2 | anthony | y#x.co | 24gss3 |
| 3 | jillian | z#x.co | hdfg5d |
Every time a row gets inserted into table 1 they also want to take that information from table 1 and add it to Table 2
Table 2
| ID | NAME | EMAIL | password | signature | level | lastenter | register_date |
-----------------------------------------------------------------------------------------------
| 1 | david | x#x.co | asx234 | text | 3 | 0000-00-00 | Date of insert |
| 2 | anthony | y#x.co | 24gss3 | text | 3 | 0000-00-00 | Date of insert |
| 3 | jillian | z#x.co | hdfg5d | text | 3 | 0000-00-00 | Date of insert |
How do I set up a trigger to insert the data into Table 2 whenever a row is inserted into table 1?
Thanks!

Some thoughts below, but the trigger would look something like this:
DELIMITER $$
DROP TRIGGER IF EXISTS trgMyNewTrigger $$
CREATE TRIGGER trgMyNewTrigger AFTER INSERT ON Table1
FOR EACH ROW
BEGIN
INSERT into Table2 (ID,NAME,EMAIL,`password`,signature,`level`,lastenter,register_date) VALUES (
new.ID, new.NAME, new.EMAIL, new.password, 'text', 3, '0000-00-00', CURDATE() );
END $$
DELIMITER ;
This is not a great solution. Triggers in general can cause some nasty issues and limit your capabilities down the road. It would be better to reconsider the design of the table to be inclusive of the data you need, have the application perform the extra step or use some sort of ETL process to get the data at set intervals.
I will all assume the clear text passwords are for the example.

Related

NOT IN not working in mysql procedure

I have this table that represents friendships
+--------+--------+
| user_1 | user_2 |
+--------+--------+
| 1 | 5 |
| 2 | 67 |
| 3 | 23 |
| ... | ... |
+--------+--------+
My goal is to create a procedure that returns friends of friends of a user (that does not include friends).
I started by creating a procedure to return friends for a given user
CREATE DEFINER=`user`#`localhost` PROCEDURE `getFriends`(IN `myuser` BIGINT(20))
NO SQL
BEGIN
DROP TABLE IF EXISTS friends;
CREATE TEMPORARY TABLE friends
SELECT user_2
FROM fb_friends
WHERE user_1=myuser;
END
This procedure, for user 534477793, creates the following temporary table
+------------+
| user_2 |
+------------+
| 527419864 |
| 580101923 |
| 620972114 |
| 651861323 |
| 662123645 |
| 676185145 |
| 682866129 |
| 718761310 |
| 729611272 |
| 1036862839 |
+------------+
Then I created another procedure that calls the first one and return friends of friends
CREATE DEFINER=`user`#`localhost` PROCEDURE `getFriendsOfFriends`(IN `myuser` BIGINT(20))
BEGIN
-- Creates the table friends
CALL getFriends(myuser);
SELECT DISTINCT(fb.user_2)
FROM fb_friends fb, friends f
-- This works
WHERE fb.user_1 IN (f.user_2)
-- This doesn't
AND fb.user_2 NOT IN (f.user_2);
END
And the query returns the following:
+------------+
| user_2 |
+------------+
| 729611272 |
| 527419864 |
| 651861323 |
| 676185145 |
| 1036862839 |
| 502741322 |
| 546744626 |
| 636845886 |
| 652813833 |
| 663713246 |
| 682866129 |
| 781419583 |
| 845134109 |
| 1355751897 |
| 1359286892 |
| 1275961636 |
| 620972114 |
| 509609160 |
| 662123645 |
| 1460283586 |
+------------+
So it's clear that the NOT IN didn't work since all values from getFriends are in the second results set.
I managed to get the results I wanted by doing ugly stuff but still, I'd like to understand what's wrong here. And there's no NULL value anywhere by the way.
Thanks!
That's because f.user_2 in your NOT IN is just a single user, not the entire set.
The correct way to do it is
SELECT DISTINCT(fb.user_2)
FROM fb_friends fb, friends f
WHERE fb.user_1 IN (f.user_2)
AND fb.user_2 NOT IN (SELECT * FROM friends);
Note the the first IN can be replaced with an = operator, because again there's only one element in the IN list.
Or you can completely remove the join to make the query consistent (but it will probably regress the performance)
SELECT DISTINCT(fb.user_2)
FROM fb_friends fb
WHERE fb.user_1 IN (SELECT * FROM friends)
AND fb.user_2 NOT IN (SELECT * FROM friends);
I thought the problem might be with temporary table and I was right. By executing the query in MySQLWorkbench the following error was ouput:
Error Code: 1137. Can't reopen table: 'friends'
So I went online to check if there was a limit on the number of times a temporary table can be used in the same query and in fact there is.
So I might just the temporary table into a permanent one (and drop it every time beforehand) and all will work as expected. sigh

MySQL second auto increment field based on foreign key

I've come across this problem numerous times but haven't found a "MySQL way" to solve the issue as such - I have a database that contains users and reports. Each report has an id which I display as a report number to my users.
The main complaint is that users are confused as to why reports have gone missing from their system. This is not actually the case. It is actually that they are recognizing a gap between their IDs and assume that these are missing reports, when in actual fact, it is simply becasue another user has filled in this auto-incrementing gap.
I need to know if there is a way to do this in MySQL:
Is it possible that I can have a second auto-increment field called report_number which is based on a user_id field which has a different set of auto-increments per user?
e.g.
|------|---------|---------------|
| id | user_id | report_number |
|------|---------|---------------|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 1 |
| 5 | 1 | 4 |
| 6 | 1 | 5 |
| 7 | 2 | 2 |
| 8 | 3 | 1 |
| 9 | 3 | 2 |
|------|---------|---------------|
I am using InnoDB for this as it is quite heavily weighted with foreign-keys. It appears to complain when I add a second auto increment field, but I wasn't sure if there was a different way to do this?
MyISAM supports the second column with auto increment, but InnoDB doesn't.
For InnoDB you might create a trigger BEFORE INSERT to get the max value of the reportid and add one to the value.
DELIMITER $$
CREATE TRIGGER report_trigger
BEFORE INSERT ON reports
FOR EACH ROW BEGIN
SET NEW.`report_id` = (SELECT MAX(report_id) + 1 FROM reports WHERE user_id = NEW.user_id);
END $$
DELIMITER ;
If you can use MyISAM instead, in the documentation of MySQL page there is an example:
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
Which returns:
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
Right one with IFNULL:
DELIMITER $$
CREATE TRIGGER salons_trigger
BEFORE INSERT ON salon
FOR EACH ROW BEGIN
SET NEW.salon_id = IFNULL((SELECT MAX(salon_id) + 1 FROM salon WHERE owner = NEW.owner), 1);
END $$
DELIMITER ;
I think mysql doesnt support two auto_increment columns. you can create report number using information schema.
select NULL from information_schema.columns
MySQl does not support two auto incremented fields, if you need then create another table, set the other field which you want to be as auto incremented and you must set up a relationship with these two tables.

mySQL cross table field linking

Basically I have two tables A and B. These are linked by unique ID's where the entries in B point to one entry in A. The entries in A and B also have a 'status' field denoting if the entry is active or not...
My questions is therefore; is it possible to link the status field of the entries in B and have them update, every time the 'status' field in A (pointed to by the unique ID) is updated? I could do this fairly easy with an SQL command however I'm wondering if there is a more automatic solution. Example:
table A
|------ID------|----status----|
| 1 | on |
| 2 | on |
|---------------|----------------|
table B
|-----eID------|------ID------|----status----|
| 1 | 1 | on |
| 2 | 1 | on |
| 3 | 2 | on |
|---------------|---------------|----------------|
I then run:
UPDATE `A` SET `status` = 'off' WHERE `ID` = 1;
And the result would be:
table A
|------ID------|----status----|
| 1 | off |
| 2 | on |
|---------------|---------------|
table B
|-----eID------|------ID------|----status----|
| 1 | 1 | off |
| 2 | 1 | off |
| 3 | 2 | on |
|---------------|---------------|----------------|
Is that possible?
Many Regards,
Andreas
i hope this trigger code can help u.
CREATE TRIGGER `abc` AFTER UPDATE ON `tablea` FOR EACH ROW BEGIN UPDATE tableb SET STATUS = new.status WHERE id = new.id;
END

How to create trigger which increment colum value after inserting the row?

I have a database in MySQL. Here is SQL query to create it http://paste.org.ru/?xzctqi
Here is main table books. All I need to do is when I add some book, I choose publisher ID for it. After adding books, I need loop through all records in this table and increment column publisher_books_amount for all rows, which has same publisher as in currently added row.
+----+-------+--------+------------------------+-----------+
| id | title | author | publisher_books_amount | publisher |
+----+-------+--------+------------------------+-----------+
| 1 | Book1 | 1 | 0 | 1 |
| 2 | Book2 | 2 | 0 | 1 |
| 3 | Book3 | 1 | 0 | 2 |
| 4 | Book4 | 3 | 0 | 3 |
| 5 | Book1 | 3 | 0 | 1 |
+----+-------+--------+------------------------+-----------+
I've created trigger
DROP TRIGGER IF EXISTS `insert_trigger`;
DELIMITER |
CREATE TRIGGER `insert_trigger` AFTER INSERT ON books
FOR EACH ROW
BEGIN
UPDATE books SET publisher_books_amount = (publisher_books_amount + 1)
WHERE publisher = NEW.publisher;
END;
|
DELIMITER ;
But when I'm trying to add book, MySQL provides me with an error.
Can't update table 'books' in stored function/trigger because it is
already used by statement which invoked this stored function/trigger.
Don't ask me why do I have denormalized DB. I just need structure described above.
BTW I need to create same triggers after deleting and updating rows. If there are some problems with that, could you help me with it too?
Sincerely, Dmitriy.
Update inside a loop is not allowed, because it goes to infinite loop.
Try your triiger without update,with only set value this=this.

MySQL Multi Duplicate Record Merging

A previous DBA managed a non relational table with 2.4M entries, all with unique ID's. However, there are duplicate records with different data in each record for example:
+---------+---------+--------------+----------------------+-------------+
| id | Name | Address | Phone | Email | LastVisited |
+---------+---------+--------------+---------+------------+-------------+
| 1 | bob | 12 Some Road | 02456 | | |
| 2 | bobby | | 02456 | bob#domain | |
| 3 | bob | 12 Some Rd | 02456 | | 2010-07-13 |
| 4 | sir bob | | 02456 | | |
| 5 | bob | 12SomeRoad | 02456 | | |
| 6 | mr bob | | 02456 | | |
| 7 | robert | | 02456 | | |
+---------+---------+--------------+---------+------------+-------------+
This isnt the exact table - the real table has 32 columns - this is just to illustrate
I know how to identify the duplicates, in this case i'm using the phone number. I've extracted the duplicates into a seperate table - there's 730k entires in total.
What would be the most efficient way of merging these records (and flagging the un-needed records for deletion)?
I've looked at using UPDATE with INNER JOIN's, but there are several WHERE clauses needed, because i want to update the first record with data from subsequent records, where that subsequent record has additional data the former record does not.
I've looked at third party software such as Fuzzy Dups, but i'd like a pure MySQL option if possible
The end goal then is that i'd be left with something like:
+---------+---------+--------------+----------------------+-------------+
| id | Name | Address | Phone | Email | LastVisited |
+---------+---------+--------------+---------+------------+-------------+
| 1 | bob | 12 Some Road | 02456 | bob#domain | 2010-07-13 |
+---------+---------+--------------+---------+------------+-------------+
Should i be looking at looping in a stored procedure / function or is there some real easy thing i've missed?
U have to create a PROCEDURE, but before that
create ur own temp_table like :
Insert into temp_table(column1, column2,....) values (select column1, column2... from myTable GROUP BY phoneNumber)
U have to create the above mentioned physical table so that u can run a cursor on it.
create PROCEDURE myPROC
{
create a cursor on temp::
fetch the phoneNumber and id of the current row from the temp_table to the local variable(L_id, L_phoneNum).
And here too u need to create a new similar_tempTable which will contain the values as
Insert into similar_tempTable(column1, column2,....) values (Select column1, column2,.... from myTable where phoneNumber=L_phoneNumber)
The next step is to extract the values of each column u want from similar_tempTable and update into the the row of myTable where id=L_id and delete the rest duplicate rows from myTable.
And one more thing, truncate the similar_tempTable after every iteration of the cursor...
Hope this will help u...