MySql constraint that two columns have different values on each row - mysql

How can I declare a constraint such that two columns may not have the same value in any row.
E.g. Given
create table `presents` (
`from` varchar(255) NOT NULL,
`to` varchar(255) NOT NULL
)
I want to make sure that nobody ever gives a present to themselves.
'alice', 'bob' # OK
'bob', 'charlie' # OK
'bob', 'alice' # OK
'bob', 'alice' # OK again
'bob', 'bob' # Fails

create table `presents` (
`from` varchar(255) NOT NULL,
`to` varchar(255) NOT NULL,
CHECK(from<>to)
)

Here's one idea:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table (id SERIAL PRIMARY KEY, `from` INT NOT NULL, `to` INT NOT NULL);
INSERT INTO my_table (`from`,`to`) SELECT 1,2 FROM (SELECT 1) x WHERE 1 <> 2;
INSERT INTO my_table (`from`,`to`) SELECT 1,1 FROM (SELECT 1) x WHERE 1 <> 1;
SELECT * FROM my_table;
+----+------+----+
| id | from | to |
+----+------+----+
| 1 | 1 | 2 |
+----+------+----+

Related

mysql constarint interval intersection

I have mysql table
CREATE TABLE `range` (
`id` int(11) NOT NULL,
`object_id` int NOT NULL,
`datetime_from` datetime NOT NULL,
`datetime_to` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Please help to provide on mysql level constraint implementation: no time interval intersection for same object_id.
A trigger is fine, but by way of demonstrating that no trigger is required, consider the following...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table (
id SERIAL,
dt_from DATE NOT NULL,
dt_to DATE NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO my_table (dt_from,dt_to)
VALUES
('2018-05-31','2018-06-03');
-- Attempt 1: conflicting dates
SET #dt_from = '2018-05-28';
SET #dt_to = '2018-06-01';
INSERT INTO my_table (dt_from,dt_to)
SELECT #dt_from
, #dt_to
FROM (SELECT 1) x
LEFT
JOIN my_table y
ON y.dt_from < #dt_to
AND y.dt_to > #dt_from
WHERE y.id IS NULL;
-- Attempt 2: Non-conflicting dates
SET #dt_from = '2018-06-04';
SET #dt_to = '2018-06-06';
INSERT INTO my_table (dt_from,dt_to)
SELECT #dt_from
, #dt_to
FROM (SELECT 1) x
LEFT
JOIN my_table y
ON y.dt_from < #dt_to
AND y.dt_to > #dt_from
WHERE y.id IS NULL;
SELECT * FROM my_table;
+----+------------+------------+
| id | dt_from | dt_to |
+----+------------+------------+
| 1 | 2018-05-31 | 2018-06-03 |
| 2 | 2018-06-04 | 2018-06-06 |
+----+------------+------------+
See. Conflicting dates are ignored.

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

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 Query - recent entries per group

I'm trying to select the most recent entries per group in a table.
Say I have a table "blog_posts" which has a column for "id" (all unique, auto incremented), "post_cat" which can be values 'category1' or 'category2' or 'category3', and a "publish_status" column which can be values 'online' or 'offline'.
How can I select the most recent entries for each category?
I have the following right now, but it almost feels like it's selecting randomly:
select * FROM `blog_posts` WHERE (publish_status = 'online') GROUP BY post_cat ORDER BY id DESC LIMIT 10
I'd keep it real simple and use a trigger to maintain a last_post_id in the category table so you can easily join back on the posts table - something like this:
Simple Query
select
pc.cat_id,
pc.name,
u.username,
bp.*
from
post_category pc
inner join blog_post bp on pc.last_post_id = bp.post_id
inner join users u on bp.user_id = u.user_id
order by
pc.cat_id;
+--------+------+----------+---------+---------+---------------------+
| cat_id | name | username | post_id | user_id | post_date |
+--------+------+----------+---------+---------+---------------------+
| 1 | cat1 | bar | 3 | 2 | 2011-02-09 12:45:33 |
| 2 | cat2 | BAR | 5 | 3 | 2011-02-09 12:45:33 |
| 3 | cat3 | f00 | 4 | 1 | 2011-02-09 12:45:33 |
+--------+------+----------+---------+---------+---------------------+
Tables
drop table if exists post_category;
create table post_category
(
cat_id smallint unsigned not null auto_increment primary key,
name varchar(255) unique not null,
last_post_id int unsigned null,
key (last_post_id)
)
engine=innodb;
drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
username varbinary(32) unique not null
)
engine=innodb;
drop table if exists blog_post;
create table blog_post
(
post_id int unsigned not null auto_increment primary key,
user_id int unsigned not null,
post_date datetime not null,
key (post_date, user_id)
)
engine=innodb;
drop table if exists blog_post_category;
create table blog_post_category
(
cat_id smallint unsigned not null,
post_id int unsigned not null,
primary key (cat_id, post_id)
)
engine=innodb;
Triggers
delimiter #
create trigger blog_post_before_ins_trig before insert on blog_post
for each row
begin
set new.post_date = now();
end#
create trigger blog_post_category_before_ins_trig before insert on blog_post_category
for each row
begin
update post_category set last_post_id = new.post_id where cat_id = new.cat_id;
end#
delimiter ;
Test Data
insert into post_category (name) values ('cat1'),('cat2'),('cat3'),('cat4');
insert into users (username) values ('f00'),('bar'),('BAR'),('alpha'),('beta');
insert into blog_post (user_id) values (1),(1),(2),(1),(3);
insert into blog_post_category (cat_id, post_id) values
(1,1),(1,3),
(2,1),(2,5),
(3,1),(3,3),(3,4);
Hope this helps :)
There's no really straightforward way to go about this...
http://www.artfulsoftware.com/infotree/queries.php#104
http://planet.mysql.com/entry/?id=26926
If you only have three categories, you can just make separate queries and take the union:
(SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category1' ORDER BY `id` DESC LIMIT 10) UNION
(SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category2' ORDER BY `id` DESC LIMIT 10) UNION
(SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category3' ORDER BY `id` DESC LIMIT 10)
You could even re-sort the whole thing at the end. It's only 30 rows!
SELECT * FROM (
(SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category1' ORDER BY `id` DESC LIMIT 10) UNION
(SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category2' ORDER BY `id` DESC LIMIT 10) UNION
(SELECT * FROM `blog_posts` WHERE `publish_status` = 'online' AND `post_cat`='category3' ORDER BY `id` DESC LIMIT 10)
) `monster` ORDER BY `id` DESC

MySQL: Insert record if not exists in table [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