Avoid inserting duplicate column values - mysql

I have a very simple table with 3 columns tag_id, label, timestamp and I need as lightweight as possible a query to insert only when there is a new value for the column label.
How would I write an sql query to do this? I can see some examples already on the site but they are all mixed up in more complex queries (some involving subqueries) that I can't understand.
There seems to be different ways of doing it and I need to find out the most lightweight one so that I can repeat it in a loop to insert multiple tags in one go without putting too much strain on the server.

You can use
ALTER TABLE `tableName` ADD UNIQUE KEY (label);
This will enforce a unique value for that column in the schema. You will get an error when you attempt to insert a duplicate value. If you want to simply ignore the error, you can use INSERT IGNORE INTO.

you can also use:
INSERT INTO table(`label`) VALUES ("new value")
ON DUPLICATE KEY UPDATE `label` = "new value";

Related

Insert statement yields different results than the select all in sql

I'm currently trying to create a table of theater locations that only has three locations. I imported denormalized data that I tried to normalize with this statement:
insert into theater(`name`, email, address, phone)
select distinct theater, theater_email, theater_address, theater_phone
from denormalized_tickets;
when I comment out the first line and run it I get the result I'm looking for.
When I write a query to see the theater table select * from theater;, it returns the theaters duplicated each 12 times.
How should I solve this? Is there anything I'm overlooking?
As discussed in the comments above, INSERT creates new rows each time you execute it. If you do that multiple times, you may add more rows every time.
Vasya recommended creating a UNIQUE index to block new rows from being created with the same values. This may or may not be appropriate for a given table. For instance, what if you want to allow multiple rows to have the same values?
Another thing you might like to read about is MySQL's REPLACE statement. The syntax is similar to INSERT, but if there's a duplicate in column(s) of a primary key or unique key, it first deletes the old row and then inserts the new row. But this won't help if you don't have the unique key defined, because how would MySQL know it's a conflict?

Correct way of inserting new row into SQL table, but only if pair does not exist

This has been discussed before, however I cannot understand the answers I have found.
Essentially I have a table with three columns memo, user and keyid (the last one is primary and AUTO_INC). I insert a pair of values (memo and user). But if I try to insert that same pair again it should not happen.
From what I found out, the methods to do this all depend on a unique key (which I've got, in keyid) but what I don't understand is that you still need to do a second query just to get the keyid of the existing couple (or get nothing, in which case you go ahead with the insertion).
Is there any way to do all of this in a single query? Or am I understanding what I've read (using REPLACE or IGNORE) wrong?
You need to set a UNIQUE KEY on user + memo,
ALTER TABLE mytable
ADD CONSTRAINT unique_user_memo UNIQUE (memo,user)
and then using INSERT IGNORE or REPLACE according to your needs when inserting. Your current unique key is the primary key, that is all well and good, but you need a 2nd one in order to not allow the insertion of duplicate data. If you do not create a new unique key on the two columns together, then you'll need to do a SELECT query before every insert to check if the pair already exists.

Proper usage of INSERT .... ON DUPLICATE KEY UPDATE

I am considering using INSERT ON DUPLICATE KEY UPDATE for my application which routinely has to submit many rows to the database in one transaction. However I am slightly confused regarding one thing. The usage examples online seem to be many in their variations for this functionality.
The behavior I am looking for is that I want to Insert the row if it does not already exist in the unique index, but if it does exist I simply want to return the ID but update nothing. Am I correct in assuming that this is the intended functionality for this statement.
Also I don't want to go creating dummy fields in my tables to utilize this functionality, as is suggested in many examples. That in my opinion is just bad practice.
Any advice is greatly appreciated. Below is an example from mysql's website that illustrates close to what I want but the c=3 part is not explained on it. I am wondering if this is required to make the last_insert_id actually work or if its just part of their example. I have read that without some dummy operation after the last_insert_id part then the last_insert_id won't work.
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
Instead you can just SELECT the unique ID to determine whether it exists. If it does, just return it. Otherwise, do the INSERT and return the new ID.
You cannot do this with a single statement in MySQL. A SELECT statement returns existing values; data modification statements (including INSERT) do not return data. (They usually return a count of some sort.) This includes the INSERT...ON DUPLICATE KEY UPDATE statement—it does not return data.
You can probably do what you want with a stored procedure, but the procedure will contain more than one statement. If that doesn't work for you, then do as #Explosion Pills suggests and use a SELECT followed, if needed, by an INSERT.

Is it possible to conditionally insert multiple values into a MySQL table in one statement?

I read this question, which highlights a solution to conditionally insert values into a table if they don't already exist. My question: is it possible to conditionally insert multiple values at once.
For instance, say I have a table that just contains user names (this is a pointless table, but let's keep it simple). The table's contents look like this:
matthew 20
mark 24
luke 25
john 56
buddy 68
A user enters jimmy 34, mark 25 and bobby 54 in a web form and submits, and I'd like to check whether those three values exist in the table already and insert the ones that don't in one statement. Yes, for this example, I'm assuming names are unique.
Here is a paraphrase of the code snippet from the question I linked to, adapted to this example:
INSERT INTO users(name)
SELECT 'jimmy'
FROM dual
WHERE NOT EXISTS (SELECT * FROM users
WHERE user = 'jimmy')
How can I adapt this for multiple values being inserted at once? It's also important that the solution work independently of the number of values entered. In my example, I give three (jimmy, mark and bobby) but there may only be one or there may be 20.
Second question: is this wise? I know that reducing the number of queries is desirable but is it worth it here? Should I just set up a for loop and loop through, alternately checking if a value exists and inserting if it doesn't?
Thanks for any help.
Sorry I don't have code that I've tried myself to show, I'm not even sure what to try here.
Update: added an extra column to the table. I wanted to keep things simple but need two columns to illustrate the fact that deleting a row and then inserting or updating are not what I want as they would favor the user's input over what is already in the table.
See INSERT IGNORE combined with a UNIQUE KEY on the field in question.
When a unique key constraint fails the whole row is silently ignored.
ALTER TABLE users ADD UNIQUE KEY `name` (`name`);
INSERT IGNORE INTO `users` (`name`, `age`)
VALUES ("jimmy", 22), ("bob", 45),
("luke", 300), ("john", 456);
Note: this will also suppress errors when datatypes mismatch and accurate conversion is impossible. (e.g. DECIMAL vs INT) MySQL will continue using the nearest result possible. (e.g. INT) You should ensure only pre-validated data is inserted with such statement.
I am not big on programming(especially on php), but can you parse the string into separate names and then do the loop?
something like (hopefuly the syntax is somewhat correct)
$names = split(" ", $user_names);
for ($i=0; $i<count($names); i++)
{
//sql query check - add new name function
function_sql_query($names[$i]);
}
In addition, you can add rules to your SQLDBMS to disallow dublicates in this attribute and add only unique records; this process will be maintained by DBMS
You can use MySQL's REPLACE
http://dev.mysql.com/doc/refman/5.0/en/replace.html
OR INSERT ... ON DUPLICATE KEY UPDATE
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c;

MySQL enum column from anothertable column

I'm sure this is either totally impossible or really easy:
If I'm creating a table and I want one of the columns to have limited options, it seems that I use either the ENUM or SET value type. But I have to define the possible values at that moment. What if I have another table which has two columns, a primary key column and a data column, and I want the ENUM for my new table to be set to the primary key of the already existing column?
I'm sure I can just write in the values long-hand, but ideally what I need is for new values to be entered into the list table and for the table with the enum column to just accept that the value choices will include anything new added to that list table.
Is this possible without needing to manipulate the structure of the new table each time something is added to the list?
i think this link help :
http://dev.mysql.com/doc/refman/5.0/en/enum.html
have a discussion of it
in the user comments
start :
"In MySQL 5.0, you can convert an enum's values into a dynamically-defined table of values, which then provides effectively a language-neutral method to handle this kind of conversion (rather than relying on PHP, Tcl, C, C++, Java, etc. specific code).
"
he do it with stored PROCEDURE
The easiest way is to use a regular column without contraints. If you're interested in all the current values, use DISTINCT to query them:
select distinct YourColumn from YourTable
That way, you don't have any maintenance and can store whatever you like in the table.
The foreign key table you mention is also a good option. The foreign key will limit the original column. Before you do the actual insert, you run a query to expand the "enum" table:
insert into EnumTable (name)
select 'NewEnumValue'
where not exists (select * from EnumTable where name = 'NewEnumValue')
Not sure what exactly you're trying to achieve btw; limit the column, but automatically expand the choices when someone breaks the limit?