MySQL: Insert record if not exists in table [duplicate] - mysql

This question already has answers here:
How can I do 'insert if not exists' in MySQL?
(11 answers)
Closed 2 years ago.
I am trying to execute the following query:
INSERT INTO table_listnames (name, address, tele)
VALUES ('Rupert', 'Somewhere', '022')
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name='value'
);
But this returns an error. Basically I don't want to insert a record if the 'name' field of the record already exists in another record - how to check if the new name is unique?

I'm not actually suggesting that you do this, as the UNIQUE index as suggested by Piskvor and others is a far better way to do it, but you can actually do what you were attempting:
CREATE TABLE `table_listnames` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`address` varchar(255) NOT NULL,
`tele` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
Insert a record:
INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Rupert', 'Somewhere', '022') AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `table_listnames`;
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
+----+--------+-----------+------+
Try to insert the same record again:
INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Rupert', 'Somewhere', '022') AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
+----+--------+-----------+------+
Insert a different record:
INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'John', 'Doe', '022') AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name = 'John'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `table_listnames`;
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
| 2 | John | Doe | 022 |
+----+--------+-----------+------+
And so on...
Update:
To prevent #1060 - Duplicate column name error in case two values may equal, you must name the columns of the inner SELECT:
INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Unknown' AS name, 'Unknown' AS address, '022' AS tele) AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `table_listnames`;
+----+---------+-----------+------+
| id | name | address | tele |
+----+---------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
| 2 | John | Doe | 022 |
| 3 | Unknown | Unknown | 022 |
+----+---------+-----------+------+

INSERT doesn't allow WHERE in the syntax.
What you can do: create a UNIQUE INDEX on the field which should be unique (name), then use either:
normal INSERT (and handle the error if the name already exists)
INSERT IGNORE (which will fail silently cause a warning (instead of error) if name already exists)
INSERT ... ON DUPLICATE KEY UPDATE (which will execute the UPDATE at the end if name already exists, see documentation)

Worked :
INSERT INTO users (full_name, login, password)
SELECT 'Mahbub Tito','tito',SHA1('12345') FROM DUAL
WHERE NOT EXISTS
(SELECT login FROM users WHERE login='tito');

MySQL provides a very cute solution :
REPLACE INTO `table` VALUES (5, 'John', 'Doe', SHA1('password'));
Very easy to use since you have declared a unique primary key (here with value 5).

INSERT IGNORE INTO `mytable`
SET `field0` = '2',
`field1` = 12345,
`field2` = 12678;
Here the mysql query, that insert records if not exist and will ignore existing similar records.
----Untested----

You can easily use the following way :
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
In this way, you can insert any new raw and if you have duplicate data, replace a specific column ( The best columns are timestamps ).
For example :
CREATE TABLE IF NOT EXISTS Devices (
id INT(6) NOT NULL AUTO_INCREMENT,
unique_id VARCHAR(100) NOT NULL PRIMARY KEY,
created_at VARCHAR(100) NOT NULL,
UNIQUE KEY unique_id (unique_id),
UNIQUE KEY id (id)
)
CHARACTER SET utf8
COLLATE utf8_unicode_ci;
INSERT INTO Devices(unique_id, time)
VALUES('$device_id', '$current_time')
ON DUPLICATE KEY UPDATE time = '$current_time';

To overcome a similar problem, I have modified the table to have a unique column. Using your example, on creation I would have something like:
name VARCHAR(20),
UNIQUE (name)
and then use the following query when inserting into it:
INSERT IGNORE INTO train
set table_listnames='Rupert'

If you really can't get a unique index on the table, you could try...
INSERT INTO table_listnames (name, address, tele)
SELECT 'Rupert', 'Somewhere', '022'
FROM some_other_table
WHERE NOT EXISTS (SELECT name
FROM table_listnames
WHERE name='Rupert')
LIMIT 1;

This query works well:
INSERT INTO `user` ( `username` , `password` )
SELECT * FROM (SELECT 'ersks', md5( 'Nepal' )) AS tmp
WHERE NOT EXISTS (SELECT `username` FROM `user` WHERE `username` = 'ersks'
AND `password` = md5( 'Nepal' )) LIMIT 1
And you can create the table using following query:
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) NOT NULL,
`password` varchar(32) NOT NULL,
`status` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Note: Create table using second query before trying to use first query.

Brian Hooper :
You almost hit the point but you have an error in your synatx. Your insert will never work. I tested on my database and here is the right answer:
INSERT INTO podatki (datum,ura,meritev1,meritev1_sunki,impulzi1,meritev2,meritev2_sunki,impulzi2)
SELECT '$datum', '$ura', '$meritve1','$sunki1','$impulzi1','$meritve2','$sunki2','$impulzi2'
FROM dual
WHERE NOT EXISTS (SELECT datum,ura
FROM podatki
WHERE datum='$datum' and ura='$ura'
I'm giving you my example of y table. Insert is almost the same like Bian Hooper wrote, except that I put the select FROM DUAL ont from other table.
Cind regards, Ivan

This is not an answer, it's just a note. The query like the one in the accepted answer does not work if the inserted values are duplicates, like here:
INSERT INTO `addr` (`email`, `name`)
SELECT * FROM (SELECT 'user#domain.tld', 'user#domain.tld') AS tmp
WHERE NOT EXISTS (
SELECT `email` FROM `addr` WHERE `email` LIKE 'user#domain.tld'
);
Error
SQL query: Copy Documentation
MySQL said: Documentation
#1060 - Duplicate column name 'user#domain.tld'
In the contrary, the query like the one from Mahbub Tito's answer works fine:
INSERT INTO `addr` (`email`, `name`)
SELECT 'user#domain.tld', 'user#domain.tld'
WHERE NOT EXISTS (
SELECT `email` FROM `addr` WHERE `email` LIKE 'user#domain.tld'
);
1 row inserted.
Tested in MariaDB

insert into customer_keyskill(customerID, keySkillID)
select 2,1 from dual
where not exists (
select customerID from customer_keyskill
where customerID = 2
and keySkillID = 1 )

You are inserting not Updating the result.
You can define the name column in primary column or set it is unique.

I had a problem, and the method Mike advised worked partly, I had an error Dublicate Column name = '0', and changed the syntax of your query as this`
$tQ = "INSERT INTO names (name_id, surname_id, sum, sum2, sum3,sum4,sum5)
SELECT '$name', '$surname', '$sum', '$sum2', '$sum3','$sum4','$sum5'
FROM DUAL
WHERE NOT EXISTS (
SELECT sum FROM names WHERE name_id = '$name'
AND surname_id = '$surname') LIMIT 1;";
The problem was with column names. sum3 was equal to sum4 and mysql throwed dublicate column names, and I wrote the code in this syntax and it worked perfectly,

I had a similar problem and I needed to insert multiple if not existing. So from the examples above I came to this combination... it's here just in case somebody would need it.
Notice:
I had to define name everywhere as MSSQL required it... MySQL works with * too.
INSERT INTO names (name)
SELECT name
FROM
(
SELECT name
FROM
(
SELECT 'Test 4' as name
) AS tmp_single
WHERE NOT EXISTS
(
SELECT name FROM names WHERE name = 'Test 4'
)
UNION ALL
SELECT name
FROM
(
SELECT 'Test 5' as name
) AS tmp_single
WHERE NOT EXISTS
(
SELECT name FROM names WHERE name = 'Test 5'
)
) tmp_all;
MySQL:
CREATE TABLE names (
OID int(11) NOT NULL AUTO_INCREMENT,
name varchar(32) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (OID),
UNIQUE KEY name_UNIQUE (name)
) ENGINE=InnoDB AUTO_INCREMENT=1;
or
MSSQL:
CREATE TABLE [names] (
[OID] INT IDENTITY (1, 1) NOT NULL,
[name] NVARCHAR (32) NOT NULL,
PRIMARY KEY CLUSTERED ([OID] ASC)
);
CREATE UNIQUE NONCLUSTERED INDEX [Index_Names_Name] ON [names]([name] ASC);

This query can be used in PHP code.
I have an ID column in this table, so I need check for duplication for all columns except this ID column:
#need to change values
SET #goodsType = 1, #sybType=5, #deviceId = asdf12345SDFasdf2345;
INSERT INTO `devices` (`goodsTypeId`, `goodsId`, `deviceId`) #need to change tablename and columnsnames
SELECT * FROM (SELECT #goodsType, #sybType, #deviceId) AS tmp
WHERE NOT EXISTS (
SELECT 'goodsTypeId' FROM `devices` #need to change tablename and columns names
WHERE `goodsTypeId` = #goodsType
AND `goodsId` = #sybType
AND `deviceId` = #deviceId
) LIMIT 1;
and now new item will be added only in case of there is not exist row with values configured in SET string

Related

How to Add Auto Incremental ID Column to Table with data

How to Add Auto Incremental ID Column to Table with data. ie. New column will fill with ids in old data
Old user table with data
Name, email,
abc, abc#gmail.com
abcd, abcd#gmial.com
EXPECTED OUTPUT
id, Name, email,
1, abc, abc#gmail.com
2, abcd, abcd#gmial.com
You can write:
ALTER TABLE MY_TABLE ADD id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
Alter table does no allow you to order the new field so perhaps you need to do it in 2 stages. For example
DROP TABLE IF EXISTS T;
CREATE TABLE T (NAME VARCHAR(10),EMAIL VARCHAR(20));
INSERT INTO T VALUES('ABC','abc#gmail.com'),('ABCD','abcd#gmial.com');
ALTER TABLE T
ADD COLUMN ID INT FIRST;
UPDATE T JOIN(
SELECT NAME, ROW_NUMBER() OVER (ORDER BY NAME DESC) RN FROM T) s
ON S.NAME = T.NAME
SET T.ID = S.RN
;
ALTER TABLE T
MODIFY COLUMN ID INT AUTO_INCREMENT PRIMARY KEY;
SELECT * FROM T;
Where id is added and then updated for existing records using row_number with order by
With this result
+----+------+----------------+
| ID | NAME | EMAIL |
+----+------+----------------+
| 1 | ABCD | abcd#gmial.com |
| 2 | ABC | abc#gmail.com |
+----+------+----------------+
2 rows in set (0.00 sec)
The second Alter statement then modifys id.
show create table t;
CREATE TABLE `t` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`NAME` varchar(10) DEFAULT NULL,
`EMAIL` varchar(20) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
If you are not on mysql version 8 or above you will need to replace the row_number bit with row number simulation using variables.
Not that it makes any difference anyway since any query would still need to include an order by to get the outcome you want.

If mail message doesn't exist, add to mysql database [duplicate]

This question already has answers here:
How can I do 'insert if not exists' in MySQL?
(11 answers)
Closed 2 years ago.
I am trying to execute the following query:
INSERT INTO table_listnames (name, address, tele)
VALUES ('Rupert', 'Somewhere', '022')
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name='value'
);
But this returns an error. Basically I don't want to insert a record if the 'name' field of the record already exists in another record - how to check if the new name is unique?
I'm not actually suggesting that you do this, as the UNIQUE index as suggested by Piskvor and others is a far better way to do it, but you can actually do what you were attempting:
CREATE TABLE `table_listnames` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`address` varchar(255) NOT NULL,
`tele` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
Insert a record:
INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Rupert', 'Somewhere', '022') AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `table_listnames`;
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
+----+--------+-----------+------+
Try to insert the same record again:
INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Rupert', 'Somewhere', '022') AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
+----+--------+-----------+------+
Insert a different record:
INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'John', 'Doe', '022') AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name = 'John'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `table_listnames`;
+----+--------+-----------+------+
| id | name | address | tele |
+----+--------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
| 2 | John | Doe | 022 |
+----+--------+-----------+------+
And so on...
Update:
To prevent #1060 - Duplicate column name error in case two values may equal, you must name the columns of the inner SELECT:
INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Unknown' AS name, 'Unknown' AS address, '022' AS tele) AS tmp
WHERE NOT EXISTS (
SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `table_listnames`;
+----+---------+-----------+------+
| id | name | address | tele |
+----+---------+-----------+------+
| 1 | Rupert | Somewhere | 022 |
| 2 | John | Doe | 022 |
| 3 | Unknown | Unknown | 022 |
+----+---------+-----------+------+
INSERT doesn't allow WHERE in the syntax.
What you can do: create a UNIQUE INDEX on the field which should be unique (name), then use either:
normal INSERT (and handle the error if the name already exists)
INSERT IGNORE (which will fail silently cause a warning (instead of error) if name already exists)
INSERT ... ON DUPLICATE KEY UPDATE (which will execute the UPDATE at the end if name already exists, see documentation)
Worked :
INSERT INTO users (full_name, login, password)
SELECT 'Mahbub Tito','tito',SHA1('12345') FROM DUAL
WHERE NOT EXISTS
(SELECT login FROM users WHERE login='tito');
MySQL provides a very cute solution :
REPLACE INTO `table` VALUES (5, 'John', 'Doe', SHA1('password'));
Very easy to use since you have declared a unique primary key (here with value 5).
INSERT IGNORE INTO `mytable`
SET `field0` = '2',
`field1` = 12345,
`field2` = 12678;
Here the mysql query, that insert records if not exist and will ignore existing similar records.
----Untested----
You can easily use the following way :
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
In this way, you can insert any new raw and if you have duplicate data, replace a specific column ( The best columns are timestamps ).
For example :
CREATE TABLE IF NOT EXISTS Devices (
id INT(6) NOT NULL AUTO_INCREMENT,
unique_id VARCHAR(100) NOT NULL PRIMARY KEY,
created_at VARCHAR(100) NOT NULL,
UNIQUE KEY unique_id (unique_id),
UNIQUE KEY id (id)
)
CHARACTER SET utf8
COLLATE utf8_unicode_ci;
INSERT INTO Devices(unique_id, time)
VALUES('$device_id', '$current_time')
ON DUPLICATE KEY UPDATE time = '$current_time';
To overcome a similar problem, I have modified the table to have a unique column. Using your example, on creation I would have something like:
name VARCHAR(20),
UNIQUE (name)
and then use the following query when inserting into it:
INSERT IGNORE INTO train
set table_listnames='Rupert'
If you really can't get a unique index on the table, you could try...
INSERT INTO table_listnames (name, address, tele)
SELECT 'Rupert', 'Somewhere', '022'
FROM some_other_table
WHERE NOT EXISTS (SELECT name
FROM table_listnames
WHERE name='Rupert')
LIMIT 1;
This query works well:
INSERT INTO `user` ( `username` , `password` )
SELECT * FROM (SELECT 'ersks', md5( 'Nepal' )) AS tmp
WHERE NOT EXISTS (SELECT `username` FROM `user` WHERE `username` = 'ersks'
AND `password` = md5( 'Nepal' )) LIMIT 1
And you can create the table using following query:
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) NOT NULL,
`password` varchar(32) NOT NULL,
`status` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Note: Create table using second query before trying to use first query.
Brian Hooper :
You almost hit the point but you have an error in your synatx. Your insert will never work. I tested on my database and here is the right answer:
INSERT INTO podatki (datum,ura,meritev1,meritev1_sunki,impulzi1,meritev2,meritev2_sunki,impulzi2)
SELECT '$datum', '$ura', '$meritve1','$sunki1','$impulzi1','$meritve2','$sunki2','$impulzi2'
FROM dual
WHERE NOT EXISTS (SELECT datum,ura
FROM podatki
WHERE datum='$datum' and ura='$ura'
I'm giving you my example of y table. Insert is almost the same like Bian Hooper wrote, except that I put the select FROM DUAL ont from other table.
Cind regards, Ivan
This is not an answer, it's just a note. The query like the one in the accepted answer does not work if the inserted values are duplicates, like here:
INSERT INTO `addr` (`email`, `name`)
SELECT * FROM (SELECT 'user#domain.tld', 'user#domain.tld') AS tmp
WHERE NOT EXISTS (
SELECT `email` FROM `addr` WHERE `email` LIKE 'user#domain.tld'
);
Error
SQL query: Copy Documentation
MySQL said: Documentation
#1060 - Duplicate column name 'user#domain.tld'
In the contrary, the query like the one from Mahbub Tito's answer works fine:
INSERT INTO `addr` (`email`, `name`)
SELECT 'user#domain.tld', 'user#domain.tld'
WHERE NOT EXISTS (
SELECT `email` FROM `addr` WHERE `email` LIKE 'user#domain.tld'
);
1 row inserted.
Tested in MariaDB
insert into customer_keyskill(customerID, keySkillID)
select 2,1 from dual
where not exists (
select customerID from customer_keyskill
where customerID = 2
and keySkillID = 1 )
You are inserting not Updating the result.
You can define the name column in primary column or set it is unique.
I had a problem, and the method Mike advised worked partly, I had an error Dublicate Column name = '0', and changed the syntax of your query as this`
$tQ = "INSERT INTO names (name_id, surname_id, sum, sum2, sum3,sum4,sum5)
SELECT '$name', '$surname', '$sum', '$sum2', '$sum3','$sum4','$sum5'
FROM DUAL
WHERE NOT EXISTS (
SELECT sum FROM names WHERE name_id = '$name'
AND surname_id = '$surname') LIMIT 1;";
The problem was with column names. sum3 was equal to sum4 and mysql throwed dublicate column names, and I wrote the code in this syntax and it worked perfectly,
I had a similar problem and I needed to insert multiple if not existing. So from the examples above I came to this combination... it's here just in case somebody would need it.
Notice:
I had to define name everywhere as MSSQL required it... MySQL works with * too.
INSERT INTO names (name)
SELECT name
FROM
(
SELECT name
FROM
(
SELECT 'Test 4' as name
) AS tmp_single
WHERE NOT EXISTS
(
SELECT name FROM names WHERE name = 'Test 4'
)
UNION ALL
SELECT name
FROM
(
SELECT 'Test 5' as name
) AS tmp_single
WHERE NOT EXISTS
(
SELECT name FROM names WHERE name = 'Test 5'
)
) tmp_all;
MySQL:
CREATE TABLE names (
OID int(11) NOT NULL AUTO_INCREMENT,
name varchar(32) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (OID),
UNIQUE KEY name_UNIQUE (name)
) ENGINE=InnoDB AUTO_INCREMENT=1;
or
MSSQL:
CREATE TABLE [names] (
[OID] INT IDENTITY (1, 1) NOT NULL,
[name] NVARCHAR (32) NOT NULL,
PRIMARY KEY CLUSTERED ([OID] ASC)
);
CREATE UNIQUE NONCLUSTERED INDEX [Index_Names_Name] ON [names]([name] ASC);
This query can be used in PHP code.
I have an ID column in this table, so I need check for duplication for all columns except this ID column:
#need to change values
SET #goodsType = 1, #sybType=5, #deviceId = asdf12345SDFasdf2345;
INSERT INTO `devices` (`goodsTypeId`, `goodsId`, `deviceId`) #need to change tablename and columnsnames
SELECT * FROM (SELECT #goodsType, #sybType, #deviceId) AS tmp
WHERE NOT EXISTS (
SELECT 'goodsTypeId' FROM `devices` #need to change tablename and columns names
WHERE `goodsTypeId` = #goodsType
AND `goodsId` = #sybType
AND `deviceId` = #deviceId
) LIMIT 1;
and now new item will be added only in case of there is not exist row with values configured in SET string

How to use INSERT... ON DUPLICATE?

Structure table:
CREATE TABLE IF NOT EXISTS `table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rows_id` int(11) NOT NULL,
`url_id` int(11) NOT NULL,
`keyword_id` int(11) NOT NULL,
`date` datetime NOT NULL,
`seet` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;
STRUCTURE TABLE WITH TEST ROWS ON SQLFIDDLE
query insert:
INSERT INTO `table` (`id`, `rows_id`, `url_id`, `keyword_id`, `date`, `seet`)
VALUES
(1, 1, 2, 1, '2014-05-01 00:00:00', 1);
I would like insert this row or update row if table already have row with date = '2014-05-01 00:00:00' and rows_id = '1' and keyword_id = '1'.
In dev.mysql.com i see query INSERT ... ON DUPLICATE KEY UPDATE but how make insert or update in my case ?
INSERT...ON DUPLICATE KEY UPDATE (IODKU) does an update only if the values you insert conflict with an existing row based on a PRIMARY KEY or UNIQUE KEY.
So you need to define a UNIQUE KEY over the three columns or else IODKU can't tell if the row conflicts with an existing one.
ALTER TABLE `table` ADD UNIQUE KEY (date, rows_id, keyword_id);
You said in a comment above that you can have more than one row with the same rows_id. That's fine -- the unique constraint says that you can't have two rows that duplicate the same combination of three values in date, rows_id, and keyword_id. But you can have multiple rows that have the same value in any one of those columns, as long as the combination of the three is unique.
Here's a quick demo:
mysql> create table t (
id int auto_increment primary key,
d int,
r int,
k int,
unique key(d,r,k)
);
mysql> insert into t values (1,1,1,1);
Query OK, 1 row affected (0.01 sec)
mysql> insert into t values (1,1,1,1) on duplicate key update d = values(d)+1;
Query OK, 2 rows affected (0.00 sec)
mysql> select * from t;
+----+------+------+------+
| id | d | r | k |
+----+------+------+------+
| 1 | 2 | 1 | 1 |
+----+------+------+------+
From what I'm understanding from your question, this might help. This SQL Query will test if a row exists and update the row or create a new one based on whether or not that row already exists.
IF EXISTS (SELECT * FROM table WHERE date = 2014-05-01 00:00:00 AND rows_id = 1 AND keyword_id = 1)
BEGIN
UPDATE table SET Params=values
END
ELSE
BEGIN
INSERT INTO `table` (`id`, `rows_id`, `url_id`, `keyword_id`, `date`, `seet`) VALUES (1, 1, 2, 1, '2014-05-01 00:00:00', 1)
END
If the row exists (if the SELECT statement returns data) the UPDATE query will run. If the row does not exist (SELECT statement returns no data) then the INSERT INTO statement will run.

Select and insert into a table in mysql

Mysql table
create table table1(
id int(3) zerofill auto_increment primary key,
username varchar(10)
)
engine=innodb;
Mysql insert query
insert into table1 (username)
select id from (select id from table1) as a where
a.id=last_insert_id();
I am trying to insert into a table by selecting the last id from the same table and the same row,the above queries give the explanation of what i want to do.The insert query gives null value in both the id and username.
The expected results is below.
id username
001 001
002 002
003 003
A possible approach
INSERT INTO table1 (username)
SELECT LPAD(COALESCE(MAX(id), 0) + 1, 3, '0')
FROM table1
Here is SQLFiddle demo
A drawback of this approach is that under heavy load different concurrent users may get the same MAX(id) and you'll end up with rows that have different ids but the same username.
Now, the more precise way to do it involves a separate sequencing table and a BEFORE INSERT triger
Proposed changed table schema
CREATE TABLE table1_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE table1
(
id INT(3) ZEROFILL PRIMARY KEY DEFAULT 0,
username VARCHAR(10)
);
The trigger
DELIMITER $$
CREATE TRIGGER tg_table1_before_insert
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO table1_seq VALUES(NULL);
SET NEW.id = LAST_INSERT_ID(), NEW.username = LPAD(NEW.id, 3, '0');
END$$
DELIMITER ;
Now you just insert new rows into table1 like this
INSERT INTO table1 (username)
VALUES (NULL), (NULL)
Outcome:
| ID | USERNAME |
-----------------
| 1 | 001 |
| 2 | 002 |
Here is SQLFiddle demo
Why store the value at all?
CREATE TABLE table1 (
id int(3) zerofill auto_increment PRIMARY KEY
);
CREATE VIEW oh_look_username
AS
SELECT id
, LPad(Cast(id As varchar(10)), 3, '0') As username
FROM table1

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