How to implement this mysql query? - mysql

Insert Into table if a duplicate exits select that row primary key else insert into that table and return last insert id ?
SELECT IF (EXISTS(SELECT * FROM users WHERE userName='adminchat')) THEN
BEGIN
SELECT userId FROM users WHERE userName='adminchat';
end;
ELSE
BEGIN
INSERT INTO `users`( `userRole`, `userName`, `createdOn`, `emailId`, `is_active`, `password`) VALUES (1,'user1_chat',NOW(),'sdmd1#sdmd1.com',1,'123456')
select LAST_INSERT_ID();
END;

If a table contains an AUTO_INCREMENT column and INSERT ... UPDATE inserts a row, the LAST_INSERT_ID() function returns the AUTO_INCREMENT value. If the statement updates a row instead, LAST_INSERT_ID() is not meaningful. However, you can work around this by using LAST_INSERT_ID(expr). Suppose that id is the AUTO_INCREMENT column. To make LAST_INSERT_ID() meaningful for updates, insert rows as follows:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
A way to make things work is to use a dummy column,
so if you have a table with auto_increment column ID and unique key a,b and a smallint dummy column for instance, the query might look like this:
INSERT INTO test (a,b) VALUES ('1','2') ON DUPLICATE KEY UPDATE ID=LAST_INSERT_ID(ID),Dummy = NOT dummy;
Now, SELECT LAST_INSERT_ID(); will return the correct ID.

Related

I got error code 1442 for creating TRIGGER in MySQL and another syntax error for my other trigger? How can I fix it?

I'm trying to create TRIGGERS in MySQL but I got a syntax error message. Here's my code for creating the tables and inserting the values:
The first table:
CREATE TABLE widgetSale (
id INTEGER auto_increment,
item_id INT,
customer_id INT,
quan INT,
price INT,
reconciled INT,
primary key (id));
INSERT INTO widgetSale (item_id, customer_id, quan, price, reconciled) VALUES (1, 3, 5, 1995, 0);
INSERT INTO widgetSale (item_id, customer_id, quan, price, reconciled) VALUES (2, 2, 3, 1495, 1);
INSERT INTO widgetSale (item_id, customer_id, quan, price, reconciled) VALUES (3, 1, 1, 2995, 0);
SELECT * FROM widgetSale;
My first trigger for the first table:
delimiter //
CREATE TRIGGER updateWidgetSale BEFORE UPDATE ON widgetSale for each row
BEGIN
IF NEW.reconciled = 1 THEN
SIGNAL SQLSTATE VALUE '45000'
SET MESSAGE_TEXT = 'cannot update table "widgetSale" after it has been reconciled';
END IF;
END
//
And here are my tables to create trigger for timestamps:
DROP TABLE IF EXISTS widgetSale;
CREATE TABLE widgetCustomer(
id integer auto_increment,
name TEXT,
last_order_id INT,
stamp TEXT,
primary key(id) );
CREATE TABLE widgetSale (
id integer auto_increment,
item_id INT,
customer_id INTEGER,
quan INT,
price INT,
stamp TEXT,
primary key(id) );
CREATE TABLE widgetLog (
id integer auto_increment,
stamp TEXT,
event TEXT,
username TEXT,
tablename TEXT,
table_id INT,
primary key(id));
INSERT INTO widgetCustomer (name) VALUES ('Bob');
INSERT INTO widgetCustomer (name) VALUES ('Sally');
INSERT INTO widgetCustomer (name) VALUES ('Fred');
SELECT * FROM widgetCustomer;
delimiter //
CREATE TRIGGER stampSale before insert on widgetSale for each row
BEGIN
SET NEW.stamp = CURDATE();
update widgetCustomer set last_order_id = new.item_id where widgetCustomer.id = new.customer_id;
update widgetCustomer set stamp = new.stamp;
INSERT INTO widgetLog (stamp, event, username, tablename, table_id) VALUES (NEW.stamp, 'INSERT ', 'TRIGGER', 'widgetSale', NEW.customer_id);
END
//
INSERT INTO widgetSale (item_id, customer_id, quan, price) VALUES (1, 3, 5, 1995);
INSERT INTO widgetSale (item_id, customer_id, quan, price) VALUES (2, 2, 3, 1495);
INSERT INTO widgetSale (item_id, customer_id, quan, price) VALUES (3, 1, 1, 2995);
SELECT * FROM widgetSale;
SELECT * FROM widgetCustomer;
SELECT * FROM widgetLog;
So my problem is:
I could not create the first trigger because it seems the raise function does not exist in MySQL. I was advised to use Signal statement but I don't know what syntax should I put?
I was able to create the trigger for timestamps but I got error code 1442. I don't know what went wrong with my syntax?
*Updated: I was able to solve my problems now, for the second trigger, turns out I need to CREATE TRIGGER BEFORE INSERT, not AFTER INSERT (because otherwise I cannot update the table), and wrote two UPDATE statements to update the widgetCustomer table in which I want to update the id and the stamp column, and I have to do that by writing two separate UPDATE statements.
Summary of errors from above comment thread:
You need to use DELIMITER when defining stored routines in the MySQL client. See https://dev.mysql.com/doc/refman/8.0/en/stored-programs-defining.html
Use the SIGNAL statement to raise errors in a MySQL stored routine. See https://dev.mysql.com/doc/refman/8.0/en/signal.html
Your condition appears to be reconciled = 1, and you reference that column in the row that spawned the trigger as NEW.reconciled. You don't need to SELECT from the table to get that column.
delimiter //
CREATE TRIGGER updateWidgetSale BEFORE UPDATE ON widgetSale
BEGIN
IF NEW.reconciled = 1 THEN
SIGNAL SQLSTATE VALUE '45000'
SET MESSAGE_TEXT = 'cannot update table "widgetSale" after it has been reconciled';
END IF;
END
//
User blabla_bingo noticed you had mistakenly referenced reconciled in some INSERT statements where it didn't belong. I guess it was the result of copy & paste of some lines of code.
Re error 1442: MySQL does not allow you to INSERT/UPDATE/DELETE the same table for which the trigger was spawned. In other words, if the trigger is for an operation ON widgetSale, then you can't UPDATE widgetSale in that trigger.
But you don't need to UPDATE the table to change one column in current row for which the trigger spawned. You simply reference the columns of current row with NEW.columnName like the following to set one column to a scalar value:
SET NEW.stamp = CURDATE();
CURDATE() is an equivalent way of writing DATE(NOW()).

SQL - Insert into table if doesn't have data

I'm using MYSQL script and I want to insert some values in a table.
INSERT INTO `testType` (`name`) VALUES ('URL');
INSERT INTO `testType` (`name`) VALUES ('xD');
INSERT INTO `testType` (`name`) VALUES ('LOL');
But I only want to insert if the table is empty in the first place.
I'm not a SQL guy but basically
if(testType.length() == 0 {
INSERT INTO `testType` (`name`) VALUES ('URL');
INSERT INTO `testType` (`name`) VALUES ('xD');
INSERT INTO `testType` (`name`) VALUES ('LOL');
}
How can I do this the simplest and smallest way possible? Thank you.
EDIT: my question is different. I want to insert ALL THE DATA if the table is empty. not only one insert at the time
First, I would suggest doing this in one step:
INSERT INTO testType(name)
VALUES ('URL'), ('xD'), ('LOL');
Then, you can express this without IF:
INSERT INTO testType(name)
SELECT t.name
FROM (SELECT 'URL' as name UNION ALL
SELECT 'xD' as name UNION ALL
SELECT 'LOL' as name
) t
WHERE NOT EXISTS (SELECT 1 FROM testType);
Finally, if you want to insert these values if each doesn't exist, then you can let the database do the work. First, define a unique constraint/index on the name (if name is not already the primary key), and then use ON DUPLICATE KEY UPDATE:
CREATE UNIQUE INDEX unq_testtable_name ON testtable(name);
INSERT INTO testType(name)
VALUES ('URL'), ('xD'), ('LOL')
ON DUPLICATE KEY UPDATE name = VALUES(name);
You can use stored procedure
DELIMITER //
CREATE PROCEDURE `proc1` ()
BEGIN
SELECT COUNT(*) INTO variable1 FROM testType;
IF variable1 = 0 THEN
INSERT INTO `testType` (`name`) VALUES ('URL');
INSERT INTO `testType` (`name`) VALUES ('xD');
INSERT INTO `testType` (`name`) VALUES ('LOL');
END WHILE;
END //
Try this:
DECLARE #ExistCount INT;
SET #ExistCount = (SELECT COUNT(1) FROM `testType`);
IF #ExistCount<1
THEN
INSERT INTO `testType` (`name`) VALUES ('URL'),('xD'),('LOL');
END IF;

MySQL database trigger does not work properly

I have two tables, table1 and table2. The SQL is like:
create table table1(
name varchar(100) PRIMARY key not null
);
create table table2(
id bigint PRIMARY key AUTO_INCREMENT,
username varchar(100) not null );
create trigger trigger_test
after insert
on table1
for each ROW
insert into table2 (username)
select new.name from table1;
Every time a row is inserted into table1, this row should also be inserted into table2 by the trigger I created. But after I insert string 'a' into table1, it seems right.
After I insert a second string 'b' into table1, the result appears wrong.
.
For the second time, the same row in table2. Then, I keep inserting rows into table1, the third time is like this:
I am stuck here because I cannot find a solution. Hope to get your help. Thanks in advance.
Your trigger should be either
create trigger trigger_test
after insert
on table1
for each ROW
insert into table2 (username)
values (new.name);
Or
create trigger trigger_test
after insert
on table1
for each ROW
insert into table2 (username)
select new.name from table1 where name = new.name;
Second option is not recomended. But added just to show you where the problem was

Insert Increasing Auto Increment Value

I'm having a problem with the auto increment id increasing when I don't want to it. I'm aware that the auto increment id increases when using INSERT IGNORE so I'm working around that, but still getting a behavior I can't figure out.
I'm building a normalized table of transactions, and in this table there is a column for first name which will have a reference table of transaction_first_names. My workflow is that I load data into a non normalized staging table, compare the values in the staging table with the values in the reference tables and if they do not exist into the reference table, then move the data from the staging table to the normalized table.
The issue I'm having is that when I try to insert any "new" values from the staging table into the reference tables, it seem to increment the autoincrement id's in the reference table in a way I can't explain. I wouldn't normally be ocd or stingy with id's, but as a continuing process I don't want the id's to continually be chewed through.
Here is my setup, link & code. As you can see in the second result the last inserted value was given the id of 16, whereas the goal is that id should be 9:
Runnable Example - http://rextester.com/KVMO89341
CREATE TABLE IF NOT EXISTS `transaction_first_names` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`first_name` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `u_first_name` (`first_name`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `transaction_stage` (
`transaction_id` BIGINT(20) UNSIGNED NOT NULL,
`first_name` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`transaction_id`),
INDEX `first_name` (`first_name`(191))
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB;
TRUNCATE transaction_stage;
TRUNCATE transaction_first_names;
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3658822144, 'Michael');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3658825319, 'Pete');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3658828867, 'Robert');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3658865656, 'Martin');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3659080925, 'Charlews');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3659943769, 'Christopher');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3660191699, 'Robert');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3660192662, 'Errol');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3660194469, 'Frank');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3660200483, 'Frank');
-- first select
SELECT DISTINCT st.first_name
FROM transaction_stage st
LEFT JOIN transaction_first_names f ON st.first_name <=> f.first_name
WHERE f.id IS NULL
AND st.first_name IS NOT NULL;
-- first insert
INSERT INTO transaction_first_names (`first_name`)
SELECT DISTINCT st.first_name
FROM transaction_stage st
LEFT JOIN transaction_first_names f ON st.first_name <=> f.first_name
WHERE f.id IS NULL
AND st.first_name IS NOT NULL;
-- second insert
INSERT INTO transaction_first_names (`first_name`)
VALUES ('Another name');
-- check autoincrement
SELECT * FROM transaction_first_names order by id asc;
DROP TABLE IF EXISTS transaction_first_names;
DROP TABLE IF EXISTS transaction_stage;
I've tried wrapping the select distinct in the first insert statement, but no luck.
Ah, InnoDB handles things a bit differently depending on how the system variable innodb_autoinc_lock_mode is set.
For lock modes 1 or 2, gaps may occur between successive statements
because for bulk inserts the exact number of auto-increment values
required by each statement may not be known and overestimation is
possible.
https://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html

MySQL insert unique record by index of columns

I have a table:
table user(
id_user,
userName,
email,
primary key(id_user)
);
I added unique index on it:
alter table user add unique index(userName, email);
Now I have two indexs on the table:
Index:
Keyname Unique Field
PRIMARY Yes id_user
userName Yes userName, email
The task is to find the MySQL statement for fastest way to insert new unique record.
Statement should return Id_user of the new or existent record.
I'm considering these 2 options, and don't know which is better or is there some third better way to do this?:
1.
INSERT INTO `user` (`userName`, `email`)
VALUES (u1,'u1#email.me' )
ON DUPLICATE KEY Ignore
Q: Where in this statement should be specified that the required KEY for unique inserts is Keyname = uesrName?
2.
IF EXISTS(SELECT `userName`, `email` FROM user WHERE `userName` = u1 AND `email` = u1#email.me)
BEGIN
END
ELSE
BEGIN
INSERT INTO user(`userName`, `email`)
VALUES (u1, u1#email.me);
END IF;
Q: In this statement - how the index with Keyname = userName should be taken in consideration?
Thanks!
The only way to get data out of a table in MySQL is to select.
DELIMITER $$
CREATE FUNCTION ForceUser(pUsername varchar(255), pEmail varchar(255))
RETURNS integer
BEGIN
DECLARE MyId INTEGER;
/*First do a select to see if record exists:*/
/*because (username,email) is a unique key this will return null or a unique id.*/
SELECT id INTO MyId FROM user
WHERE username = pUsername
AND email = pEmail;
IF MyId IS NULL THEN
/*If not then insert the record*/
INSERT INTO user (username, email) VALUES (pUserName,pEmail);
SELECT LAST_INSERT_ID() INTO MyId;
END IF;
RETURN MyID;
END $$
DELIMITER ;
Q: Where in this statement should be specified that the required KEY for unique inserts is Keyname = uesrName?
A: MySQL already knows this, because that information is part of the table definition.
See: http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html