Trigger value, call for table column and concenate with text - mysql

I am not able to solve that [CREATE TRIGGER VALUE] needs to call for table content and concatenate with text. For details of expected result, see below result area.
Currently the code can be run In one execution, creating 2 lines in account_log as expected.
I have marked the line that I suspect needs to be update with [<-- Needs update?].
CREATE DATABASE IF NOT EXISTS test6;
USE test6;
DROP TABLE IF EXISTS account;
CREATE TABLE account
(
`id` CHAR(4) PRIMARY KEY,
`name` VARCHAR(25),
`price` DECIMAL(4, 2)
);
DROP TABLE IF EXISTS account_log;
CREATE TABLE account_log
(
`log_id` INTEGER PRIMARY KEY AUTO_INCREMENT,
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`description` VARCHAR(60)
);
DELETE FROM account;
INSERT INTO account
VALUES
('1', 'Adam', 10),
('2', 'Eva', 7)
;
DROP PROCEDURE IF EXISTS product_update;
DELIMITER ;;
CREATE PROCEDURE product_update()
BEGIN
UPDATE account
SET
name = "Ad"
WHERE
id = "1";
END
;;
DELIMITER ;
DROP TRIGGER IF EXISTS after_account_update;
CREATE TRIGGER after_account_update
AFTER UPDATE
ON account
FOR EACH ROW
INSERT INTO
account_log (`description`)
VALUES
('Update detected: Productid: [product-1]') -- <-- Needs update?
;
-- ----------------------------
-- Provoke triggers to execute.
-- ----------------------------
CALL product_update();
CALL product_update();
SELECT * FROM account_log;
Results:
The result looks currently like this:
(the content of description is plain text).
+--------+---------------------+-----------------------------------------+
| log_id | timestamp | description |
+--------+---------------------+-----------------------------------------+
| 1 | 2019-03-28 18:14:58 | Update detected: Productid: [product-1] |
| 2 | 2019-03-28 18:14:58 | Update detected: Productid: [product-1] |
+--------+---------------------+-----------------------------------------+
I need the result to look like this
(where the values 1 and 2 in table description, comes from table account, column [id]):
+--------+---------------------+-----------------------------------------+
| log_id | timestamp | description |
+--------+---------------------+-----------------------------------------+
| 1 | 2019-03-28 18:14:58 | Update detected: Productid: 1 |
| 2 | 2019-03-28 18:14:58 | Update detected: Productid: 2 |
+--------+---------------------+-----------------------------------------+

It works by using below TRIGGER VALUES CONCAT:
CREATE TRIGGER after_account_insert
AFTER INSERT
ON account
FOR EACH ROW
INSERT INTO
account_log (`description`)
VALUES
(
CONCAT("Update detected: Productid: ", "[", NEW.id, "]", ".")
)
;

Related

What is the best way to generate primary key automatically?

I want to generate my primary key automatically in MySQL data table. But I want it to be a character string though in sequence.
Example:
user_id (Primary Key)
USER000001
USER000002
USER000003
USER000004 ....and so on..
By separate table for sequencing and a trigger, you can generate PK automatically with your format.
Tables
CREATE TABLE tableName_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE tableName
(
id VARCHAR(10) NOT NULL PRIMARY KEY DEFAULT '0', name VARCHAR(30)
);
Now the trigger
DELIMITER $$
CREATE TRIGGER tg_table_insert
BEFORE INSERT ON tableName
FOR EACH ROW
BEGIN
INSERT INTO tableName_seq VALUES (NULL);
SET NEW.id = CONCAT('USER', LPAD(LAST_INSERT_ID(), 6, '0'));
END$$
DELIMITER ;
Then you just insert rows to table
INSERT INTO tableName (name)
VALUES ('Jhon'), ('Mark');
And you'll have
| ID | NAME |
------------------
| USER000001 | Jhon |
| USER000002 | Mark |

How to make MySQL table primary key auto increment with some prefix

I have table like this
table
id Varchar(45) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name CHAR(30) NOT NULL,
I want to increment my id field like 'LHPL001','LHPL002','LHPL003'... etc.
What should I have to do for that? Please let me know any possible way.
If you really need this you can achieve your goal with help of separate table for sequencing (if you don't mind) and a trigger.
Tables
CREATE TABLE table1_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE table1
(
id VARCHAR(7) NOT NULL PRIMARY KEY DEFAULT '0', name VARCHAR(30)
);
Now the trigger
DELIMITER $$
CREATE TRIGGER tg_table1_insert
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO table1_seq VALUES (NULL);
SET NEW.id = CONCAT('LHPL', LPAD(LAST_INSERT_ID(), 3, '0'));
END$$
DELIMITER ;
Then you just insert rows to table1
INSERT INTO Table1 (name)
VALUES ('Jhon'), ('Mark');
And you'll have
| ID | NAME |
------------------
| LHPL001 | Jhon |
| LHPL002 | Mark |
Here is SQLFiddle demo
Create a table with a normal numeric auto_increment ID, but either define it with ZEROFILL, or use LPAD to add zeroes when selecting. Then CONCAT the values to get your intended behavior. Example #1:
create table so (
id int(3) unsigned zerofill not null auto_increment primary key,
name varchar(30) not null
);
insert into so set name = 'John';
insert into so set name = 'Mark';
select concat('LHPL', id) as id, name from so;
+---------+------+
| id | name |
+---------+------+
| LHPL001 | John |
| LHPL002 | Mark |
+---------+------+
Example #2:
create table so (
id int unsigned not null auto_increment primary key,
name varchar(30) not null
);
insert into so set name = 'John';
insert into so set name = 'Mark';
select concat('LHPL', LPAD(id, 3, 0)) as id, name from so;
+---------+------+
| id | name |
+---------+------+
| LHPL001 | John |
| LHPL002 | Mark |
+---------+------+
I know it is late but I just want to share on what I have done for this. I'm not allowed to add another table or trigger so I need to generate it in a single query upon insert. For your case, can you try this query.
CREATE TABLE YOURTABLE(
IDNUMBER VARCHAR(7) NOT NULL PRIMARY KEY,
ENAME VARCHAR(30) not null
);
Perform a select and use this select query and save to the parameter #IDNUMBER
(SELECT IFNULL
(CONCAT('LHPL',LPAD(
(SUBSTRING_INDEX
(MAX(`IDNUMBER`), 'LHPL',-1) + 1), 5, '0')), 'LHPL001')
AS 'IDNUMBER' FROM YOURTABLE ORDER BY `IDNUMBER` ASC)
And then Insert query will be :
INSERT INTO YOURTABLE(IDNUMBER, ENAME) VALUES
(#IDNUMBER, 'EMPLOYEE NAME');
The result will be the same as the other answer but the difference is, you will not need to create another table or trigger. I hope that I can help someone that have a same case as mine.
Here is PostgreSQL example without trigger if someone need it on PostgreSQL:
CREATE SEQUENCE messages_seq;
CREATE TABLE IF NOT EXISTS messages (
id CHAR(20) NOT NULL DEFAULT ('message_' || nextval('messages_seq')),
name CHAR(30) NOT NULL,
);
ALTER SEQUENCE messages_seq OWNED BY messages.id;

Two primary keys & auto increment

I have a MySQL table with two fields as primary key (ID & Account), ID has AUTO_INCREMENT.
This results in the following MySQL table:
ID | Account
------------------
1 | 1
2 | 1
3 | 2
4 | 3
However, I expected the following result (restart AUTO_INCREMENT for each Account):
ID | Account
------------------
1 | 1
2 | 1
1 | 2
1 | 3
What is wrong in my configuration? How can I fix this?
Thanks!
Functionality you're describing is possible only with MyISAM engine. You need to specify the CREATE TABLE statement like this:
CREATE TABLE your_table (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
account_id INT UNSIGNED NOT NULL,
PRIMARY KEY(account_id, id)
) ENGINE = MyISAM;
If you use an innoDB engine, you can use a trigger like this:
CREATE TRIGGER `your_table_before_ins_trig` BEFORE INSERT ON `your_table`
FOR EACH ROW
begin
declare next_id int unsigned default 1;
-- get the next ID for your Account Number
select max(ID) + 1 into next_id from your_table where Account = new.Account;
-- if there is no Account number yet, set the ID to 1 by default
IF next_id IS NULL THEN SET next_id = 1; END IF;
set new.ID= next_id;
end#
Note ! your delimiter column is # in the sql statement above !
This solution works for a table like yours if you create it without any auto_increment functionality like this:
CREATE TABLE IF NOT EXISTS `your_table` (
`ID` int(11) NOT NULL,
`Account` int(11) NOT NULL,
PRIMARY KEY (`ID`,`Account`)
);
Now you can insert your values like this:
INSERT INTO your_table (`Account`) VALUES (1);
INSERT INTO your_table (`Account`, `ID`) VALUES (1, 5);
INSERT INTO your_table (`Account`) VALUES (2);
INSERT INTO your_table (`Account`, `ID`) VALUES (3, 10205);
It will result in this:
ID | Account
------------------
1 | 1
2 | 1
1 | 2
1 | 3

MySQL - autoincrement to guid

I have a table with an auto-increment ID field as shown below.
+------------+-------------------------------------+
| company_id | name |
+------------+-------------------------------------+
| 1 | International Client |
| 2 | Oracle |
| 3 | test |
| 4 | testabc |
| 5 | testdef |
| 6 | abcd |
+------------+-------------------------------------+
I want to update the ID column to be a GUID using the uuid() function.
Additionally, how do I update the foreign key references to the correct GUID?
Use triggers.
CREATE TABLE `tbl_test` (
`GUID` char(40) NOT NULL,
`Name` varchar(50) NOT NULL,
PRIMARY KEY (`GUID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
table and pk, now trigger..
DELIMITER //
CREATE TRIGGER `t_GUID` BEFORE INSERT ON `tbl_test`
FOR EACH ROW begin
SET new.GUID = uuid();
end//
DELIMITER ;
Now try,
insert into tbl_test(Name) value('trigger happy...');
regards,
/t
you can't use it with autoincrement
guid is char not intger
you need to insert it your self
also you will need to change the id to char(40)
insert into table_name (id,name) values (uuid(),'jon');
In mysql 8.0 you can use something like below:
For UUID without dashes:
create table temp (`company_id` VARCHAR(64) NOT NULL DEFAULT (REPLACE(UUID(),'-','')), 'name' varchar(100) NOT NULL);
For UUID with dashes:
create table temp (`company_id` VARCHAR(64) NOT NULL DEFAULT (UUID()), 'name' varchar(100) NOT NULL);
I hope this answers your question, Let me know if it is not or you need more.

MSSQL Try Catch and Set Identity Insert in MySQL?

Do you know how to rewrite these this query in MySQL ?
I can't find Identity insert, I can't find any try catch,
I don't understand it.
CREATE TRIGGER T1 ON DB1.dbo.A
AFTER INSERT AS
BEGIN TRY
SET IDENTITY_INSERT DB2.dbo.B ON
INSERT INTO dbo.B(id, text) SELECT A.id,A.text FROM dbo.A INNER JOIN inserted I ON I.id = A.id
SET IDENTITY_INSERT DB2.dbo.B OFF
SET IDENTITY_INSERT DB2.dbo.D ON
INSERT INTO dbo.D(id, text) SELECT A.id,A.text FROM dbo.A INNER JOIN inserted I ON I.id = A.id
SET IDENTITY_INSERT DB2.dbo.D OFF
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SET IDENTITY_INSERT DB2.dbo.B OFF
SET IDENTITY_INSERT DB2.dbo.D OFF
END CATCH
GO
MySQL triggers have implicit transaction support, so the trigger cannot use statements that explicitly or implicitly begin or end a transaction such as START TRANSACTION, COMMIT, or ROLLBACK.
It is not necessary in MySQL to enable the insertion of values into primary key columns - this is already allowed. You can, however, toggle foreign key constraint checking and unique index checking:
http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_unique_checks
A common way to do this is to store the existing values in user variables, change the settings, then restore the settings after your script is complete:
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
-- Your SQL statements here.
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
I'm not sure why you would need to do that in your trigger, so your MySQL trigger would look something like this:
DELIMITER |
CREATE TRIGGER T1 AFTER INSERT ON A FOR EACH ROW
BEGIN
INSERT INTO B (id, text) VALUES (NEW.id, NEW.text);
INSERT INTO C (id, text) VALUES (NEW.id, NEW.text);
END;|
DELIMITER ;
Here's the results of a quick test:
CREATE TABLE `A` (
`id` int(11) NOT NULL auto_increment,
`text` varchar(255) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `B` (
`id` int(11) NOT NULL auto_increment,
`text` varchar(255) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `C` (
`id` int(11) NOT NULL auto_increment,
`text` varchar(255) default NULL,
PRIMARY KEY (`id`)
);
DELIMITER |
CREATE TRIGGER T1 AFTER INSERT ON A FOR EACH ROW
BEGIN
INSERT INTO B (id, text) VALUES (NEW.id, NEW.text);
INSERT INTO C (id, text) VALUES (NEW.id, NEW.text);
END;|
DELIMITER ;
INSERT INTO `A` (id, text) VALUES (1, 'Line 1');
INSERT INTO `A` (id, text) VALUES (2, 'Line 3');
INSERT INTO `A` (id, text) VALUES (3, 'Line 3');
SELECT * FROM `A`;
+----+--------+
| id | text |
+----+--------+
| 1 | Line 1 |
| 2 | Line 3 |
| 3 | Line 3 |
+----+--------+
SELECT * FROM `B`;
+----+--------+
| id | text |
+----+--------+
| 1 | Line 1 |
| 2 | Line 3 |
| 3 | Line 3 |
+----+--------+
SELECT * FROM `C`;
+----+--------+
| id | text |
+----+--------+
| 1 | Line 1 |
| 2 | Line 3 |
| 3 | Line 3 |
+----+--------+
If you want something similar to TRY ... CATCH, you'll need to use handlers instead:
http://dev.mysql.com/doc/refman/5.1/en/declare-handler.html
Here's the documentation on MySQL triggers:
http://dev.mysql.com/doc/refman/5.1/en/commit.html
Just set id column to AUTO_INCREMENT. You don't need to toggle something on and off.
Read more in documentation