Single query for "INSERT INTO table if column value not found" - mysql

How can I use a single query for inserting table when a column value is not found.
eg/ i want to insert new user only when this username not found
what i doing now is issue 1 query to check for existing,
then another query if no existing found. total 2 query
INSERT INTO friends (memberID) SELECT 1 WHERE NOT EXISTS (SELECT memberID FROM friends WHERE memberID = 1)

You just need to add FROM DUAL
INSERT INTO friends
(memberid)
SELECT 1
FROM dual
WHERE NOT EXISTS (SELECT memberid
FROM friends
WHERE memberid = 1)
sql fiddle

How about this:
INSERT INTO YourTable (UserName)
SELECT x
FROM (SELECT 'New User Name' AS x) a
WHERE x NOT IN(SELECT UserName
FROM YourTable)

Since you only want one row with a given value you should enforce that with a UNIQUE constraint on the table, for example:
ALTER TABLE friends ADD UNIQUE (memberID);
After you do that, you can simply add the IGNORE keyword to your insert statements and it won't report an error and it won't insert a duplicate row if it already exists.
INSERT IGNORE INTO friends(memberID) VALUES(1);

Related

How do I combine multiple conditions (exists and not exists) checks before inserting a new record in mysql?

I would like to build a query to insert a new record, after checking with an EXISTS and a NOT EXISTS condition in two different tables.
IF NOT EXISTS (SELECT 1 FROM `categories` WHERE categories.term_id = 123)
AND EXISTS (SELECT 1 FROM `terms` WHERE terms.id = 123)
THEN INSERT INTO `categories`(id, term_id, term_type_id)
VALUES ('', '123', '4')
Thanks in advance.
You an use indices to enforce this behavior.
EXISTS (SELECT 1 FROMtermsWHERE terms.id = 123)
To enforce this, define categories.term_id as a foreign key to terms.id.
That way you can not insert a term_id into the categories table if that is non existent in the terms table.
IF NOT EXISTS (SELECT 1 FROMcategoriesWHERE categories.term_id = 123)
To enforce this, you need to put a UNIQUE index on the categories.term_id column. This will block duplicate entries.
You can first check the desired record from the table with a select query. If the query returns the 0 rows then execute the insert statement otherwise no need to insert.

MySQL WHERE NOT EXISTS error

Let's say I have two columns member_id, email in one table users. I'm trying to add a new row if no similar data is found with below statement:
INSERT INTO users(member_id, email)
VALUES (1,'k#live.com')
WHERE NOT EXISTS (SELECT * FROM users WHERE member_id=1 AND email='k#live.com');
However, it's not working. #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE EXISTS
Please shed some light. Thanks.
Assuming you have a unique constraint on member_id, email or a combination of both, I believe you will be better served with an INSERT IGNORE, if the record doesn't exist, it will be inserted.
INSERT IGNORE INTO users(member_id, email)
values (1, 'k#live.com');
If there is no unique constraint, use this technique here
INSERT INTO users(member_id, email)
SELECT 1,'k#live.com'
FROM dual
WHERE NOT EXISTS
(SELECT * FROM users WHERE member_id=1 AND email='k#live.com');
Dual is used in the dummy select rather than users in order to limit the rows inserted to 1.
There cannot be a WHERE clause in an INSERT ... VALUES ... statement.
The normal pattern for avoiding duplicates is to add UNIQUE constraint(s).
If you want to avoid adding any duplicate "member_id" values, and you also want to avoid adding any duplicate "email" values, then
CREATE UNIQUE INDEX mytab_UX1 ON mytab (member_id);
CREATE UNIQUE INDEX mytab_UX2 ON mytab (email);
Whenever an INSERT or UPDATE attempts to create a duplicate value, a duplicate key exception (error) will be thrown. MySQL provides the IGNORE keyword which will suppress the error, and allow the statement to complete successfully, but without introducing any duplicates.
Given an empty table, the first statement would insert a row, the second and third statements would not.
INSERT IGNORE INTO mytab (member_id, email) VALUES (1,'k#live.com');
INSERT IGNORE INTO mytab (member_id, email) VALUES (2,'k#live.com');
INSERT IGNORE INTO mytab (member_id, email) VALUES (1,'aaa#bbb.com');
If you want to restrict just the combination of the two columns to being unique, that is you would allow the 2nd and 3rd statements to insert a row, then you'd add a UNIQUE constraint on the combination of the two columns, rather than two separate unique indexes as above.
CREATE UNIQUE INDEX mytab_UX1 on mytab (member_id, email);
Aside from that convention, say you don't have a unique constraint, but you only want to modify the behavior of the single insert statement, then you can use a SELECT statement to return the values you want to insert, and then you can add a WHERE clause to the SELECT.
To avoid adding any duplicate member_id or duplicate email, then something like this would accomplish that:
INSERT INTO mytab (member_id, email)
SELECT s.member_id, s.email
FROM (SELECT 1 AS member_id, 'k#live.com' AS email) s
WHERE NOT EXISTS (SELECT 1 FROM mytab d WHERE d.member_id = s.member_id)
AND NOT EXISTS (SELECT 1 FROM mytab e WHERE e.email = s.email)
For best performance with a large table, you're going to want at least two indexes, one with a leading column of member_id, and one with a leading column of email. The NOT EXISTS subqueries can make use of an index to quickly locate a "matching" row, rather than scanning every row in the table.)
Again, if it's just the combination of the two columns you want to be unique, you'd use a single NOT EXISTS subquery, as in your original query.
Alternatively, you could use an anti-join pattern as an equivalent to the NOT EXISTS subquery.
INSERT INTO mytab (member_id, email)
SELECT s.member_id, s.email
FROM (SELECT 2 AS member_id, 'k#live.com' AS email) s
LEFT
JOIN mytab d
ON d.member_id = s.member_id
LEFT
JOIN mytab e
ON e.email = s.email
WHERE d.member_id IS NULL
AND e.email IS NULL

Combine two queries to check for duplicates in MySQL?

I have a table that looks like this:
Number | Name
--------+--------
123 | Robert
This is what I want to do:
If the Number is already in the database, don't insert a new record.
If the Number is not in the databse, but the name is, create a new name and insert it. So for example, if I have a record that contains 123 for Number and Bob for Name, I don't want to insert it, but if I get a record that contains 456 for Number and Robert for name, I would insert 456 and Robert1. I was going to check for duplicates individually like:
SELECT * FROM Person where Number = 123;
//If number is not found
SELECT * FROM Person where Name = 'Robert';
//If name is found, add a number to it.
Is there a way I can combine the two statements?
There are actually two problems in your question. The first problem is to make Number column unique and the second one is to increment the column Name by appending a number if it already exists.
FIRST PART
Since the number is UNIQUE, enforce a UNIQUE constraint on the column. It could be a PRIMARY KEY or a UNIQUE KEY.
If the column has no KEY and you want to make it PRIMARY, here is the ALTER statement:
ALTER TABLE TableName ADD CONSTRAINT tb_pk PRIMARY KEY (Number)
SQLFiddle Demo
but if you only want it to be UNIQUE and not a primary key,
ALTER TABLE TableName ADD CONSTRAINT tb_uq UNIQUE (Number)
SQLFiddle Demo
SECOND PART
You can actually do it without using join.
INSERT INTO TableName(Number, Name)
SELECT 124 AS Number,
CONCAT('Robert', COALESCE(MAX(CAST(REPLACE(Name, 'Robert', '0') AS UNSIGNED)) + 1,'')) AS Name
FROM TableName
WHERE Name LIKE 'Robert%'
SQLFiddle Demo
SQLFiddle Demo (added more example)
SQLFiddle Demo (throws exception due to uniqueness)
Some details:
when the value supplied on column Number already exists, it will throw an error since the column is unique. I have read a comment from a deleted posts saying: "..Number is not unique, but if it does exist, I don't want to enter a record." -- it does not make any sense if you don't want to add uniqueness on the column. How will you know if the number already exists or not? Doing a little check for the existence of Number feels like a little overhead for me. So my best recommendation is to enforce uniqueness.
SELECT * FROM Person WHERE Number = 123 OR Name = 'Robert'
I haven't worked with SQL for some time, so this may be wrong ;)
Edit:
$number = 123;
$name = 'Robert';
$query = mysql_query("SELECT * FROM Person WHERE Number = $number OR Name = '$name' ");
if (mysql_num_rows($query) == 0 ) {
//-> Add your record, it's unused
} else if (mysql_result($query, 0, 'number') == $number && mysql_result($query, 0, 'name' == $name)) {
//combination of number and name already exists -> modify name and add record
} else {
echo "Number is used by another name";
}
Use this query, for insert the row [123, 'Robert']. if you want insert other values, change 123 & Robert values in below query:
insert into Person (Number,Name)
select 123, IF(mn.MaxNumber is NULL,'Robert',concat('Robert',mn.MaxNumber+1))
from (SELECT 'foo') foo
left JOIN (select max(CONVERT(SUBSTR(Name,LENGTH('Robert')+1),UNSIGNED)) `MaxNumber`
from person where name rlike '^Robert[0-9]*$') mn on 1=1
where Not Exists (select * from Person where Number=123)
NOTE: if Robert exists in the table, above query inserts Robert1. if Robert1 exists, it inserts Robert2, and so on .
make both number and name unique.
ALTER TABLE `person` ADD UNIQUE (`number` ,`name`);
You can now do a insert with ON DUPLICATE
INSERT INTO `person` (`number`, `name`, `id`) VALUES ('322', 'robert', 'NULL') ON DUPLICATE KEY UPDATE `id`='NULL';
For appending a number after name i would suggest using autoincrement column instead.
insert into Person (Number,Name)
select 123, IF(mn.MaxNumber is NULL,'Robert',concat('Robert',mn.MaxNumber+1))
from (SELECT 'foo') foo
left JOIN (select max(CONVERT(SUBSTR(Name,LENGTH('Robert')+1),UNSIGNED)) `MaxNumber`
from person where name rlike '^Robert[0-9]*$') mn on true
where Not Exists (select * from Person where Number=123)

insert into table only if not exist on other table

I'm trying to do the following thing:
I have two tables: ReportImage (imageId, reportId, counter)
and userReportedImages (imageId, userId)
I want that every user will be able to report an image only once - this means that first I want to check if there is a row in 'userReportedImages' with the values (imageId, userId) if so do nothing, else create a row in 'ReportImage' with the values (imageId, reportId, counter), if such row already exist (other user reported that image) then I want to raise the counter.
so far before checking for same user report I had the following statement:
INSERT INTO ReportImage VALUES (imageId,reportId,1) ON DUPLICATE KEY UPDATE counter = counter+1
this statement is working fine.
I tried to change this statement to first check if the row exist on the other table, but I didn't manage to do it, can you help me?
First, you need to define a UNIQUE constraint or a compund column primary key on table ReportImage,
ALTER TABLE ReportImage ADD CONTRAINT tb_uq UNIQUE(ImageID, ReportID)
Give this a try,
INSERT INTO ReportImage(ImageID, ReportID, Counter)
SELECT 'imageID HERE' AS ImageID,
'userID HERE' AS ReportID,
1 AS Counter
FROM userReportedImages a
LEFT JOIN ReportImage b
ON a.imageId = b.imageId AND
a.userId = b.ReportID AND
a.imageID = 'imageID HERE' AND
a.userID = 'userID HERE'
WHERE b.imageId IS NULL OR
b.ReportID IS NULL
ON DUPLICATE KEY UPDATE counter = VALUES(counter) + 1
you could try using NOT EXISTS
insert into table2(`name`)
select * from (select 'name1' as name) tmp
where not exists(
select ('x') from table1 where name = 'test1'
);
SQL Fiddle
An insert trigger should be a solution for you: link

mysql insert value if it doesn't exist

I'm trying to insert an ingredient to an ingredients table if it doesn't exist.
I'm using the following syntax:
INSERT INTO ingredient(Name)
(
SELECT 'ingName' FROM dummytable WHERE
(SELECT count(*) FROM ingredient WHERE Name = 'ingName')=0)
This does not seem to work (0 rows affected), even though the SELECT query seem to return the desired result (an entry which contains "ingName").
The "ingredient" table has 2 columns: Name, id (id is auto incremented)
Thanks,
Li
Its better to add unique index on the name column:
ALTER TABLE `ingredient` ADD UNIQUE(`Name`)
After doing that you can use INSERT IGNORE:
INSERT IGNORE INTO `ingredient` ... /* anything */
That's because your inner query SELECT count(*) FROM ingredient WHERE Name = 'ingName' is returning a value > 0 and hence the upper query SELECT 'ingName' FROM dummytable WHERE is not selecting any rows and so no insert is happening.
I tried the same with a test table having 2 column name|value and it did worked fine
INSERT INTO test1(name) (
SELECT 'name' FROM test2 WHERE
(
SELECT count(*) FROM test2 WHERE name = 'bilboa'
)
=0
)
Inserted 2 rows with value name cause that's what I am selecting in select query and my test table 2 rows.