I'm trying to setup a mysql trigger. So lets assume the table is like this
mysql> explain users;
+------------+-------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+-------------------+-----------------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(30) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
| purge_date | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+------------+-------------+------+-----+-------------------+-----------------------------+
and
mysql> explain users_details;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(30) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
so the trigger i have setup will create a purge_date of NOW on the users table when something is removed from the users_details table. This is fine.
The issue is that sometimes the data for the users_details table comes through incorrectly and then the users update it so then i need to remove the purge_date if they re-insert the data. Now I have made this trigger
CREATE TRIGGER purge_fix AFTER INSERT ON users_details
FOR EACH ROW
BEGIN
UPDATE users
SET purge_date= '0000-00-00 00:00:00'
WHERE users.name = NEW.name;
END;
Which works fine but in some situations there will not be a link between the users_details table and the users table (it will be created at a later stage) so my question is, as the trigger will fail in some situations (which is 100% fine by me), will I be breaking something having the trigger failing?
Related
I want start_date and start_time copied into latest_time and latest_date, while adding a new entry into my logbook. But I want dependency on logbook.logbook_index_id = logbook_index.id for all entries too.
mysql> describe logbook;
+-------------------------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------------------+-----------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| logbook_index_id | int(10) unsigned | NO | | NULL | |
| start_date | date | NO | | NULL | |
| start_time | time | NO | | NULL | |
mysql> describe logbook_index;
+--------------------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+----------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| first_date | date | NO | | NULL | |
| first_time | time | NO | | NULL | |
| latest_date | date | NO | | NULL | |
| latest_time | time | NO | | NULL | |
+--------------------+----------------------+------+-----+---------+----------------+
atm I got this far ...
create trigger update_dates after insert on logbook
for each row update logbook_index
set latest_date = start_date where logbook_index.id = logbook_index_id;
I do it mostly wrong I bet. How does this work correctly and how do I get the time copied too ?
If I understood your question correctly:
For this I would suggest using a trigger
You can put an AFTER INSERT trigger on the table that you insert, inside the trigger you can put the update to the other table.
In order to access variables from the newly insert record, you need to do the following:
UPDATE logbook_index
SET latest_date = NEW.start_date
WHERE logbook_index.id = NEW.logbook_index_id;
Notice the keyword NEW that is used to access the newly insert record.
If you were using an AFTER UPDATE trigger, you could access the old values by using OLD
What you're searching for is a Trigger, a procedure that's automatically invoked in response to an event, in your case the insertion of a row in the logbook table.
Here's my table.
+-------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| Postcode | varchar(255) | YES | | NULL | |
| Town | varchar(255) | YES | | NULL | |
| Region | varchar(255) | YES | | NULL | |
| Company Name | varchar(255) | YES | | NULL | |
| Fee | double | YES | | NULL | |
| Company Benefits | varchar(255) | YES | | NULL | |
| Date Updated | date | YES | | NULL | |
| Website | mediumtext | YES | | NULL | |
| Updated By | varchar(255) | YES | | NULL | |
| Notes | varchar(255) | YES | | NULL | |
| LNG | varchar(255) | YES | | NULL | |
| LAT | varchar(255) | YES | | NULL | |
+-------------------+--------------+------+-----+---------+----------------+
You can see we have an "Updated by" column.
How can I make it so that, when a user updates the row, the "Updated By" column automatically updates (or inserts if it's a new row they're adding) with the currently logged-in users name?
Many Thanks
You will have to explicitly make sure about that and whenever an UPDATE is happening then you need to update that column as well saying below. Best way to assure it, have your application logic fill in the column whenever an UPDATE to the record is happening from current logged-in user principle or claim
update tbl1
set ...,
Updated By = <logged in user name>
where Id = <some val>
You can use USER() or CURRENT_USER() in Update or Insert statements to achieve needed effect.
From my side - the only one secure way is to create stored procedures, providing inserts or updates to desired table.
Indeed, this problem was discussed here:
mysql Set default value of a column as the current logged in user
Something like this !
CREATE TRIGGER `updater`.`tableName_BEFORE_INSERT` BEFORE INSERT ON `tableName`
FOR EACH ROW
BEGIN
Set New.Updated_By = current_user();
END
I am posting this thread in order to have some advices regarding the performance of my SQL query.
I have actually 2 tables, one which called HGVS_SNP with about 44657169 rows and another on run table which has an average of 2000 rows.
When I try to update field Comment of my run table it takes lot's of time to perform the query. I was wondering if there is any method to increase my SQL query.
Structure of HGVS_SNP Table:
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| snp_id | int(11) | YES | MUL | NULL | |
| hgvs_name | text | YES | | NULL | |
| source | varchar(8) | NO | | NULL | |
| upd_time | varchar(32) | NO | | NULL | |
+-----------+-------------+------+-----+---------+-------+
My run table has the following structure:
+----------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+--------------+------+-----+---------+-------+
| ID | varchar(7) | YES | | NULL | |
| Reference | varchar(7) | YES | MUL | NULL | |
| HGVSvar2 | varchar(120) | YES | MUL | NULL | |
| Comment | varchar(120) | YES | | NULL | |
| Compute | varchar(20) | YES | | NULL | |
+----------------------+--------------+------+-----+---------+-------+
Here's my query:
UPDATE run
INNER JOIN SNP_HGVS
ON run.HGVSvar2=SNP_HGVS.hgvs_name
SET run.Comment=concat('rs',SNP_HGVS.snp_id) WHERE run.Compute not like 'tron'
I`m guessing since you JOIN a text column with a VARCHAR(120) column that you don`t really need a text column. Make it a VARCHAR so you can index it
ALTER TABLE `HGVS_SNP` modify hgvs_name VARCHAR(120);
ALTER TABLE `HGVS_SNP` ADD KEY idx_hgvs_name (hgvs_name);
This will take a while on large tables
Now your JOIN should be much faster,also add an index on compute column
ALTER TABLE `run` ADD KEY idx_compute (compute);
And the LIKE is unnecessary,change it to
WHERE run.Compute != 'tron'
I want to create a student table with column 'student_birthday' and its format should be dd-mm-yy.
create table `student`.`studentinfo`(
`student_id` int(10) not null auto_increment,
`student_name` varchar(45) not null,
`student_surname` varchar(45) not null,
`student_birthday` date(???),
(some lines of code)
primary key(student_id));
what should be inputted in the (???) to get the right format above?
Just use "DATE" without the brackets. The brackets are only needed for certain column types where you want to specify the maximum number of bytes/characters that can be stored.
For MySQL, it's documented at https://dev.mysql.com/doc/refman/5.7/en/date-and-time-types.html
The following example will explain your problem. I am using MySQL 5.7.18.
Firstly I have described the structure of users table as I am going to create posts table with FOREIGN KEY.
Later I created posts table and it has a DATE field named created with many other columns.
Finally I inserted 1 row in the newly created table.
mysql> desc users;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| id | bigint(20) | NO | PRI | NULL | |
| fname | varchar(50) | NO | | NULL | |
| lname | varchar(50) | NO | | NULL | |
| uname | varchar(20) | NO | | NULL | |
| email | text | NO | | NULL | |
| contact | bigint(12) | NO | | NULL | |
| profile_pic | text | NO | | NULL | |
+-------------+-------------+------+-----+---------+-------+
7 rows in set (0.00 sec)
mysql> CREATE TABLE posts(id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, title text NOT NULL, description text NOT NULL, posted_by bigint, FOREIGN KEY(posted_by) REFERENCES users(id) ON DELETE CASCADE ON UPDATE RESTRICT , created DATE);
Query OK, 0 rows affected (0.01 sec)
mysql> desc posts;
+-------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| title | text | NO | | NULL | |
| description | text | NO | | NULL | |
| posted_by | bigint(20) | YES | MUL | NULL | |
| created | date | YES | | NULL | |
+-------------+------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql> INSERT INTO posts(title, description, posted_by, created) values("Getting started with MySQL", "Excellent Database system", 1, "2017-05-26");
Query OK, 1 row affected (0.00 sec)
mysql> select * from posts;
+----+----------------------------+---------------------------+-----------+------------+
| id | title | description | posted_by | created |
+----+----------------------------+---------------------------+-----------+------------+
| 1 | Getting started with MySQL | Excellent Database system | 1 | 2017-05-26 |
+----+----------------------------+---------------------------+-----------+------------+
1 row in set (0.00 sec)
mysql>
The datatype date on its own is enough to represent a date value. The format will matter when you are displaying the data, for which you can use the FORMAT function on your date column.
I should add that there is a certain amount of flexibility as to the format when inserting date time literals as documented here.
alter table if field is not already exist
ALTER TABLE `table`
ADD( `abc` text NOT NULL,
`xyz` tinyint(1) NOT NULL,
);
if abc or xyz fields are already exist the can not be alter table
if it is possible ?
You can use a SHOW COLUMNS beforehand and construct your query accordingly, adding only fields that are missing.
Example output of SHOW COLUMNS:
mysql> SHOW COLUMNS FROM City;
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| Id | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | | | |
| Country | char(3) | NO | UNI | | |
| District | char(20) | YES | MUL | | |
| Population | int(11) | NO | | 0 | |
+------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
I can't comment yet, so I post answer: try this link for detailed example. It queries information_schema.COLUMNS table for column information about database tables.