Copy to another table on mysql update - mysql

I have a mysql table that whenever there is an add, modify/update, or delete, I want to take the row and add it to an "archive" table (before it is updated or deleted). This is for a historical archive (i.e. what happened). Is there a way to do this in the database layer "automatically"? Is there a better way...

You'll need a group of triggers that cover all operations (insert, update, delete).
Let's say you have a table
CREATE TABLE table1
(
table1_id int not null auto_increment primary key,
column1 varchar(32)
);
and you created the following history table for it
CREATE TABLE table1_history
(
history_id int not null auto_increment primary key,
dt datetime not null,
operation varchar(6) not null,
table1_id int not null,
column1 varchar(32) not null
);
Now your triggers might look something like
CREATE TRIGGER tg_ai_table1
AFTER INSERT ON table1
FOR EACH ROW
INSERT INTO table1_history (dt, operation, table1_id, column1)
VALUES(NOW(), 'insert', NEW.table1_id, NEW.column1);
CREATE TRIGGER tg_au_table1
AFTER UPDATE ON table1
FOR EACH ROW
INSERT INTO table1_history (dt, operation, table1_id, column1)
VALUES(NOW(), 'update', NEW.table1_id, NEW.column1);
CREATE TRIGGER tg_bd_table1
BEFORE DELETE ON table1
FOR EACH ROW
INSERT INTO table1_history (dt, operation, table1_id, column1)
VALUES(NOW(), 'delete', OLD.table1_id, OLD.column1);
If we issue the following DML statements against table1
INSERT INTO table1 (column1) VALUES ('value1'), ('value2');
UPDATE table1 SET column1 = 'value11' WHERE table1_id = 1;
DELETE FROM table1 WHERE table1_id = 2;
table1 will contain
| TABLE1_ID | COLUMN1 |
|-----------|---------|
| 1 | value11 |
table1_history will contain
| HISTORY_ID | DT | OPERATION | TABLE1_ID | COLUMN1 |
|------------|--------------------------------|-----------|-----------|---------|
| 1 | January, 04 2014 06:31:15+0000 | insert | 1 | value1 |
| 2 | January, 04 2014 06:31:15+0000 | insert | 2 | value2 |
| 3 | January, 04 2014 06:31:15+0000 | update | 1 | value11 |
| 4 | January, 04 2014 06:31:15+0000 | delete | 2 | value2 |
Here is SQLFiddle demo

Try to use Trigger
eg:
DROP TRIGGER auditlog
CREATE TRIGGER auditlog BEFORE UPDATE ON frequencies
FOR EACH ROW BEGIN
INSERT INTO frequencies_audit select * from frequencies where freqId = NEW.freqId;
END;

Related

Check if multiple records already exits and then insert new records MySql

Sorry if my question is inappropriate but I need the answer for one of my project
Actually, I want to insert multiple records from table1 to table2 of MySql. But before inserting records in table2, I need to check if any record already exists in table2, and If any single record exists then skip that record and insert the remaining ones.
For Example: I want to insert record 101 & 102 in table2 from table1 but if record 101 already exists in table2 then skip 101 and insert 102.
This is my code to insert record from table1 to table2
INSERT INTO table2 (owner_id, month,date,medium, monthly_rent, tax_deduction, final_payment)
SELECT id, 'sep2020','2020/10/05',medium, monthly_rent, tax_deduction, final_payment
FROM table1
WHERE table1.id =('100','101')
Since you have a primary key on id you could use INSERT IGNORE..https://dev.mysql.com/doc/refman/8.0/en/insert.html which will throw a warning if a duplicate key is detected and won't add a new row. for example
DROP TABLE IF EXISTS T,T1;
CREATE TABLE T (ID INT, VAL INT);
CREATE TABLE T1 (ID INT PRIMARY KEY,VAL INT);
INSERT INTO T VALUES (101,10),(102,20),(103,30);
INSERT IGNORE INTO T1
SELECT ID,VAL
FROM T;
UPDATE T SET VAL = 50 WHERE ID = 101;
INSERT IGNORE INTO T1
SELECT ID,VAL
FROM T;
mysql> SELECT * FROM T;
+------+------+
| ID | VAL |
+------+------+
| 101 | 50 |
| 102 | 20 |
| 103 | 30 |
+------+------+
3 rows in set (0.05 sec)
mysql> SELECT * FROM T1;
+-----+------+
| ID | VAL |
+-----+------+
| 101 | 10 |
| 102 | 20 |
| 103 | 30 |
+-----+------+
3 rows in set (0.00 sec)
It seems that you want to add a row to table2 every time an new row is added to table1 so it may be worth considering a trigger to do the job. https://dev.mysql.com/doc/refman/8.0/en/triggers.html

How can i add a new entry into a mysql table, BUT only for 1 column, while keeping all other column data

So i have the following table
but when i run the following command:
"INSERT INTO default_db.loader_messages (confirmation_secure_radio_button_message) VALUES ('$confirmmessagevalue1')";
it adds a new row, but empties the loader_message1 column as you can see above.
please tell me how do i keep the current data in the loader_message1 column as well as add a new row ?
If you can change from an insert..values to insert..select then you could
drop table if exists t;
create table t (id int auto_increment primary key,col1 varchar(10),col2 varchar(10));
insert into t (col1) values ('col1');
insert into t (col1,col2)
select col1,'aaa'
from t where id = (select max(id) from t)
;
insert into t (col1) values ('xxx');
insert into t (col1,col2)
select col1,'bbb'
from t where id = (select max(id) from t)
;
select * from t;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
| 1 | col1 | NULL |
| 2 | col1 | aaa |
| 3 | xxx | NULL |
| 4 | xxx | bbb |
+----+------+------+
4 rows in set (0.02 sec)
if this is not a possibility for you then consider capturing in your front end before inserting or inserting in a procedure and fill down after the insert using an update.
I mentioned that it is a poor design to replicate column value to multiple rows.
Still...you shall
select loader_message1 from dbname where yourcondition;
get the mysqli result into $row and then using
$row['loader_message1'] or $row[0]
in the insert like
insert... (fld1, fld2) values (value1, value2)

Insert statement in self-join table

What is the correct statement to make an insert in a table with a self-join?
If I try to make a classic insert I get the error:
Cannot add or update a child row: a foreign key constraint fails
This is my insert query:
insert into mTable(record_name,self_fk,val, note, ref,insert_date, end_date)
values('processo prova',0,1,'nota di prova', 'az12345', NOW(), NOW());
In your INSERT query, you are referencing to a foreign key (the id 0) that doesn't exist -> constraint fails
I saw in your edits, before you roll it back, your CREATE TABLE script.
The field containing the reference to the parent was created this way :
`id_processo_padre` int(11) NOT NULL DEFAULT '1'
I suggest you to edit this field to make it nullable :
ALTER TABLE `mTable` MODIFY `id_processo_padre` int(11) NULL;
This will allow you to INSERT the first top level parent (or any top level parent)
insert into mTable(record_name, self_fk, ...)
values('processo prova', NULL, ...);
-- ^--^----------This
Test it yourself :
Schema (MySQL v5.7)
CREATE TABLE test
(
id INT(6) NOT NULL PRIMARY KEY AUTO_INCREMENT,
parent_id INT(6) NULL,
someData VARCHAR(255),
FOREIGN KEY (parent_id) REFERENCES test(id)
);
INSERT INTO test VALUES (default, null, "parent"),
(default, 1, "child1_1"),
(default, 1, "child1_2"),
(default, 3, "child2_2");
Query #1
SELECT t1.*, t2.someData AS "My parent's name" FROM test t1
LEFT JOIN test t2
ON t2.id = t1.parent_id
ORDER BY t1.id ASC;
Output
| id | parent_id | someData | My parent's name |
| --- | --------- | -------- | ---------------- |
| 1 | null | parent | null |
| 2 | 1 | child1_1 | parent |
| 3 | 1 | child1_2 | parent |
| 4 | 3 | child2_2 | child1_2 |
View on DB Fiddle

How to make assign always the value 1 to the LAST "row_id" created

I have a mysql table and the first column names "row_id" and contains an number that shows the id of the row created into the table.
Here below a very simple an example made easier:
+--------+---------+------+---------+------+-----------+
| row_id | user_id | city | zipcode | note | imagepath |
+--------+---------+------+---------+------+-----------+
| 1 | | | | | |
| 2 | | | | | |
| 3 | | | | | |
| 4 | | | | | |
+--------+---------+------+---------+------+-----------+
I would like to know if there is a way, into the phpmyadmin console, to be able to make assign always the value 1 to the LAST "row_id" created, making become as 2 the previous "row_id" that was 1, making become as 3 the previous "row_id" that was 2, and so on.
Thank you very much.
Simply:
UPDATE my_table SET row_id = row_id + 1; INSERT INTO my_table VALUES (1, 5, 'fourth_city', 'fourth_zipcode', 'fourth_note', 'fourth_image');
UPDATE my_table SET row_id = row_id + 1; INSERT INTO my_table VALUES (1, 6, 'fifth_city', 'fifth_zipcode', 'fifth_note', 'fifth_image');
.... And so on
But if row_id is your primary key then you must drop it before:
ALTER TABLE my_table DROP PRIMARY KEY;
UPDATE my_table SET row_id = row_id + 1; INSERT INTO my_table VALUES (1, 5, 'fourth_city', 'fourth_zipcode', 'fourth_note', 'fourth_image');
ALTER TABLE my_table ADD PRIMARY KEY(row_id);
ALTER TABLE my_table DROP PRIMARY KEY;
UPDATE my_table SET row_id = row_id + 1; INSERT INTO my_table VALUES (1, 6, 'fifth_city', 'fifth_zipcode', 'fifth_note', 'fifth_image');
ALTER TABLE my_table ADD PRIMARY KEY(row_id);
.... And so on.
You can create a stored procedure or function to simplify the call. Hope help.

MySQL: Multiple Primary Keys and Auto Increment

I'm quite new to setting up tables in MySQL and there is something I'd like to do which is a bit more advance than I'm able to do.
I have two columns as part of a composite primary key, one is a Date and an ID I would like to be an auto increment integer. For each date, I would like to reset the auto integer to 0, so something like this:
|-----------------|
|Date | ID |
|-----------------|
|2012-06-18 | 1 |
|2012-06-18 | 2 |
|2012-06-18 | 3 |
|2012-06-19 | 1 |
|2012-06-19 | 2 |
|2012-06-20 | 1 |
|-----------------|
Thanks
Here this should work.
CREATE TABLE `answer`(
`dates` DATE NOT NULL,
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`dates`,`id`)
) ENGINE=MyISAM;
It is known to cause problems with innoDB. Hope this helps you.
EDIT: RESULTS
2012-06-19 1
2012-06-19 2
2012-06-19 3
2012-07-19 1
2012-07-19 2
2012-08-19 1
On php myadmin.
Well, for me mysql does what you want automatically.
mysql> CREATE TABLE TestData(Date date not null, ID int unsigned not null auto_increment, PRIMARY KEY(Date, ID));
mysql> INSERT INTO TestData SET Date = "2012-06-18";
mysql> INSERT INTO TestData SET Date = "2012-06-18";
mysql> INSERT INTO TestData SET Date = "2012-06-18";
mysql> INSERT INTO TestData SET Date = "2012-06-19";
mysql> INSERT INTO TestData SET Date = "2012-06-19";
mysql> INSERT INTO TestData SET Date = "2012-06-20";
mysql> select * from TestData;
+------------+----+
| Date | ID |
+------------+----+
| 2012-06-18 | 1 |
| 2012-06-18 | 2 |
| 2012-06-18 | 3 |
| 2012-06-19 | 1 |
| 2012-06-19 | 2 |
| 2012-06-20 | 1 |
+------------+----+
No magic involved.
You can create a before insert trigger.
DELIMITER $$
CREATE TRIGGER `composite_auto_increment` BEFORE INSERT ON `your_table`
FOR EACH ROW
BEGIN
DECLARE max_id INT(11); -- add the appropriate column length from your table definition
SELECT ID FROM `your_table` WHERE `Date` = DATE(NOW()) INTO max_id;
SET NEW.ID = IF(ISNULL(max_id), 1, max_id + 1);
END$$
This way, if and ID already existed for the day, it gets incremented. If it didn't, it gets set to 1. Note that in this scenario, ID isn't AUTO_INCREMENT in the table definition. It just gets done by the trigger.
In trigger:
SELECT ID FROM your_table WHERE Date = DATE(NOW()) INTO max_id;
must be:
SELECT max(ID) FROM your_table WHERE Date = NEW.key_field INTO max_id;
but better is lock by key.
this is better for concurrent inserts on innodb.