MySQL: issue setting unique restraint on combination of rows - mysql

I'm trying to set a unique restraint on a combination of columns rather than on a single column. I have a table, "tags":
id (int, PK, AI, unsigned)
tag (varchar 25)
user_id (int, unsigned)
Following the answer to this question, I tried to set the combo restraint via:
ALTER TABLE `tags` ADD UNIQUE `unique_tag_user_combo` (`tag`, `user_id`);
So far, so good. But when I come to test it, by seeing if it will let me insert the same tag twice but with different user IDs (it should), it errors:
INSERT INTO `tags` VALUES (NULL, 'foo', '1'), (NULL, 'foo', '2')
...throws...
Duplicate entry 'foo' for key 'name_2'
Remember the unique restraint is on the combo of tag + user_id, so this query, to my mind, should run fine. I could understand this error if I'd tried to insert foo/1 twice, but not foo/1 and foo/2. What am I missing?
(EDIT - also, what's that 'name_2' reference in the error message all about? I don't have a column with that name...)

You might also have an unique index on tag column.Use
SHOW CREATE TABLE yourtb

Related

MySQL check 2 values already exists before insert

My columns are like this. column "a" is primary and auto incremantal.
a | b | x | y
When inserting new data, i need to check x and y columns shouldn't be exist together.
To clarify, imagine this row is at database with these values
(2, "example.com" , "admin", "123456")
I should able to insert both of these columns
(3, "example.com" , "user", "123456")
(4, "example2.com" , "admin", "123456")
But i shouldn't able to insert this column
(5, "example.com" , "admin", "5555555")
Because "example.com" and "admin" values already in database on a row. It doesn't matter column "y" is same or not.
How can i do this?
Create a composite unique index. This will allow any number of duplicates in the individual fields, but the combination needs to be unique.
CREATE UNIQUE INDEX ix_uq ON tablename (b, x);
...and use INSERT IGNORE to insert if the unique index is not violated. If it is, just ignore the insert.
INSERT IGNORE INTO test (a,b,x,y) VALUES (5, "example.com" , "admin", "5555555");
If you want to insert unless there's a duplicate, and update if there is, you can also use INSERT INTO ... ON DUPLICATE KEY UPDATE;
Ref: MySQL only insert new row if combination of columns (which allow duplicates) is unique
You want to let the database do the work. Although you can set up a condition within a query, that condition may not be universally true or someone might use another query.
The database can check this with a unique constraint or index. Actually, the unique constraint is implementing using a unique index:
create unique index unq_t_b_x on t(b, x);
(The columns can be in either order.)
The insert would then look like:
insert into t(b, x, y)
values ('example.com', 'admin', '5555555')
on duplicate key update b = values(b);
Note that the auto-incremented value is not included in the update.
The on duplicate key update just prevents the insert from generating an error. It is better than insert ignore because the latter will ignore all errors, and you just want to ignore the one caused by the duplicate key.

MySQL on duplicate key... get existing ID?

I'm using ON DUPLICATE KEY UPDATE to handle duplicate inserts on a table, in order that they are discarded.
In my case it's a simple table storing tags:
id (int, PK, AI, unsigned, not null)
tag (varchar 25, not null, unique)
This is working fine, but I need to retrieve the ID - either the insert ID, on successful insert, or the existing ID, if it's a duplicate.
I'm getting insert ID = 0 where ON DUPLICATE KEY UPDATE fires, which I guess is expected behaviour since no insert took place.
Is there anyway I can get the existing ID, or am I headed to a separate read query?
You could add a third column ModifiedDate and use that:
insert into t(id, tag)
select id, tag
on duplicate key update ModifiedDate = now();
This will ensure that an update really occurs, and in turn, that LAST_INSERT_ID() returns a value.

INSERT INTO...SELECT - Primary key conflict - error #1062

I have a database: groupofficecom has two tables:
cal_events: id(Primary key), name, start_time, description,....
cf_cal_events: model_id (Primary key), col_1, col_2, col_3,....
I'm trying to execute the following code:
INSERT INTO groupofficecom.cf_cal_events (model_id,col_1,col_2,....)
SELECT groupofficecom.cal_events.ID, '0' AS col_1, '' AS col_2,....
FROM groupofficecom.cal_events
But it keeps giving me error #1062 - Duplicate entry '155' ('155' is the 'id' from cal_events) for key 'PRIMARY'
I want the primary key model_id to be the same value as id in cal_events because the table cf_cal_events is just complementary fields for cal_events (this is a program, so I can't change its database, it'll be gone on the first update)
Thank you guys!
This means there already is an entry with that id in the target table.
First, check how this can be.
Then, use one of the solutions described here as is appropriate:
"INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE"
i.e. UPDATE or IGNORE.
You should use an ORDER BY with the select you have and the solution above to choose which entries get ignored (all but the first entry with IGNORE).
It is also possible that you want something different entirely, i.e. to use an UPDATE statement instead of an INSERT statement.
In fact I found a very good function, it's very similar to the INSERT but smarter:
REPLACE INTO database (column_1, column_2)
SELECT source_column1, 'value' AS column2
FROM table;
Or:
REPLACE INTO database (column_1, column_2)
VALUES ('value1', 'value2')
FROM table;
Works like magic!
It inserts new items to the destination table, and if it finds a row with the same primary key value, it erases it and re-inserts the new value (it works great for updating a table from another one)
I hope this solves your problem like it solved mine ;)

MySQL - insert into statement requires me to enter primary key

I'm pretty much a complete newbie to SQL, I'm using MySQL with SQLyog. I have five fields, StudentForename, StudentSurname, StudentAge, StudentHouse and StudentID for the Primary Key. The StudentID field is set as a Primary Key and Not Null and AutoIncrement. I'm trying to use an INSERT INTO statement without having to entering the primary key - apparently I shouldn't need to, it should update itself. But it's not working, it's returning the error "Column count doesn't match value count at row 1". Here's the code I'm using. I've already set up the table, so I haven't got the code for the query that
INSERT INTO students VALUES('Harry', 'Potter', 'Slytherin', 30)
You will need to explicitly state which columns you will provide values for, otherwise it is assumed you will provide values for all columns. E.g.
INSERT INTO students (`first_name`, `last_name`, `house`, `age`) VALUES('Harry', 'Potter', 'Slytherin', 30)
(I made up column names, swap these with your columns)

MySQL: Advanced insert if not exists

I have a table with with essentially three columns: user_id, setting, and value. I'm trying to use the following code:
INSERT INTO 'user_settings'(user_id, setting, value)
VALUES (1234, setting_1, 500)
ON DUPLICATE KEY UPDATE user_id = 1234, setting = setting_1'
This works great when creating a new setting, and it doen't generate duplicate records. The problem comes when I want to change the value- this won't work after the previous query has run:
INSERT INTO 'user_settings'(user_id, setting, value)
VALUES (1234, setting_1, 999)
ON DUPLICATE KEY UPDATE user_id = 1234, setting = setting_1'
No rows are affected. Clearly I'm missing something...
IMPORTANT: I am not able to alter the database (new primary keys or something).
UPDATE: It seems my understanding of ON DUPLICATE KEY is wrong. But the question remains- what is the most efficient way way to accomplish this?
Answered in a comment below: "If the Primary (or Unique) key is (user_id, setting), then use: ... ON DUPLICATE KEY UPDATE value=999".
Assuming you actually have a unique key on user_id, you are getting "no rows affected" because you aren't changing anything in the second query. I think what you want to do is update the value field as well:
INSERT INTO 'user_settings'(user_id, setting, value)
VALUES (1234, setting_1, 999)
ON DUPLICATE KEY UPDATE setting = setting_1,value=999
Without value in there, you're just setting the user_id and the setting field to the same values they were before, and MySQL doesn't need to update the record.
If you don't have a unique key on user_id, you'll have to find a different approach, as the ON DUPLICATE KEY UPDATE won't trigger.