To preface, I'm not very experienced with database design. I have a table of hashes and ids. When a group of new hashes are added, each row in the group gets the same id. If any hash within the new group already exists in the database, all hashes in the new group and existing group(s) get a new, shared id (effectively merging ids when hashes are repeated):
INSERT INTO hashes
(id, hash)
VALUES
($new_id, ...), ($new_id, ...)
ON DUPLICATE KEY UPDATE
repeat_count = repeat_count + 1;
INSERT INTO hashes_lookup SELECT DISTINCT id FROM hashes WHERE hash IN (...);
UPDATE hashes JOIN hashes_lookup USING (id) SET id = '$new_id';
TRUNCATE TABLE hashes_lookup;
Other tables reference these ids, so that if an id changes, foreign key constraints take care of updating the ids across tables. The issue here, however, is that I can't enforce uniqueness across any of the child tables. If I do, my queries fail with:
Foreign key constraint for table '...', record '...' would lead to a duplicate entry in table '...'
This error makes sense, given the following test case where id and value are a composite unique key:
id | value
---+-------
a | 1
b | 2
c | 1
Then a gets changed to c:
id | value
---+-------
c | 1
b | 2
c | 1
But c,1 already exists.
It would be ideal if there was an ON UPDATE IGNORE CASCADE option, so that if a duplicate row exists, any duplicating inserts are ignored. However, I'm pretty sure the real issue here is my database design, so I am open to any and all suggestions. My current solution is to not enforce uniqueness across child tables, which leads to a lot of redundant rows.
Edit:
CREATE TABLE `hashes` (
`hash` char(64) NOT NULL,
`id` varchar(128) NOT NULL,
`repeat_count` int(11) NOT NULL DEFAULT '0',
`insert_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY `hash` (`hash`) USING BTREE,
KEY `id` (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `emails` (
`id` varchar(128) NOT NULL,
`group_id` char(5) NOT NULL,
`email` varchar(500) NOT NULL,
KEY `index` (`id`) USING BTREE,
UNIQUE KEY `id` (`id`,`group_id`,`email`(255)) USING BTREE,
CONSTRAINT `emails_ibfk_1` FOREIGN KEY (`id`) REFERENCES `hashes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
I think will be good to create table hash_group to store id of hash group:
CREATE TABLE `hash_group` (
`id` BIGINT AUTO_INCREMENT NOT NULL,
`group_name` varchar(128) NOT NULL,
`insert_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY `group_name` (`group_name`) USING BTREE,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
And change structure of existing tables:
CREATE TABLE `hashes` (
`hash` char(64) NOT NULL,
`hash_group_id` BIGINT NOT NULL,
`repeat_count` int(11) NOT NULL DEFAULT '0',
`insert_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY `hash` (`hash`) USING BTREE,
KEY `hashes_hash_group_id_index` (`hash_group_id`) USING BTREE,
CONSTRAINT `hashes_hash_group_id_fk` FOREIGN KEY (`hash_group_id`) REFERENCES `hash_group` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `emails` (
`hash_group_id` BIGINT NOT NULL,
`group_id` char(5) NOT NULL,
`email` varchar(500) NOT NULL,
KEY `emails_hash_group_id_index` (`hash_group_id`) USING BTREE,
UNIQUE KEY `emails_unique` (`hash_group_id`,`group_id`,`email`(255)) USING BTREE,
CONSTRAINT `emails_ibfk_1` FOREIGN KEY (`hash_group_id`) REFERENCES `hash_group` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Also create trigger to update hash group if you need to do it:
DELIMITER $$
CREATE TRIGGER `update_hash_group_name` AFTER UPDATE ON `hashes`
FOR EACH ROW
BEGIN
UPDATE `hash_group`
SET `group_name` = md5(now()) -- replace to you hash formula
WHERE id = NEW.hash_group_id;
END;$$
DELIMITER ;
And create function for getting actual group id:
DROP FUNCTION IF EXISTS get_hash_group;
DELIMITER $$
CREATE FUNCTION get_hash_group(id INT) RETURNS INT
BEGIN
IF (id IS NULL) THEN
INSERT INTO `hash_group` (`group_name`)
VALUES (md5(now())); -- replace to you hash
RETURN LAST_INSERT_ID();
END IF;
RETURN id;
END;$$
DELIMITER ;
Scenario:
Initial fill:
INSERT INTO `hash_group` (id, group_name) VALUES
(1, 'test1'),
(2, 'test2'),
(3, 'test3');
INSERT INTO `hashes` (hash, hash_group_id) VALUES
('hash11', 1),
('hash12', 1),
('hash13', 1),
('hash2', 2),
('hash3', 3);
INSERT INTO `emails` (hash_group_id, group_id, email)
VALUES
(1, 'g1', 'example1#'),
(2, 'g1', 'example2#'),
(3, 'g1', 'example2#');
Updating of hash_group scenario:
START TRANSACTION;
-- Get #min_group_id - minimum group id (we will leave this id and delete other)
SELECT MIN(hash_group_id) INTO #min_group_id
FROM hashes
WHERE hash IN ('hash11', 'hash12', 'hash2', 'hash15');
-- Replace other group ids in email table to #min_group_id
UPDATE `emails`
SET `hash_group_id` = #min_group_id
WHERE `hash_group_id` IN (
SELECT hash_group_id
FROM hashes
WHERE #min_group_id IS NOT NULL
AND hash IN ('hash11', 'hash12', 'hash2', 'hash15')
-- Update only if we are gluy several hash_groups
AND `hash_group_id` > #min_group_id
);
-- Delete other hash_groups and leave only group with #min_group_id
DELETE FROM `hash_group` WHERE `id` IN (
SELECT hash_group_id
FROM hashes
WHERE #min_group_id IS NOT NULL
AND hash IN ('hash11', 'hash12', 'hash2', 'hash15')
-- Delete only if we are gluy several hash_groups
AND `hash_group_id` > #min_group_id
);
-- #group_id = existing hash_group.id or create new if #min_group_id is null (all inserted hashes are new)
SELECT get_hash_group(#min_group_id) INTO #group_id;
-- Now we can insert new hashes.
INSERT INTO `hashes` (hash, hash_group_id) VALUES
('hash11', #group_id),
('hash12', #group_id),
('hash2', #group_id),
('hash15', #group_id)
ON DUPLICATE KEY
UPDATE repeat_count = repeat_count + 1;
COMMIT;
I maybe wrong but I think you mis-named the id field in hashes.
I think you should rename the id field in hashes to something like group_id, then have a AUTO_INCREMENT field called id that should also be PRIMARY in hashes that the id in emails refers to this field instead. When you want to update and relate all the hashes together, you update the group_id field instead of id, and id remains unique across the table.
This way you can avoid the cascade problem, also you will always know the original hash that the email was referring to.
Sure, if you want to fetch all the hashes related to an email (old and the new) you must exectue and extra query, but I think it solves all your problems.
Edit:
you can use a trigger to do this
The trigger goes like this
DELIMITER $$
CREATE TRIGGER `update_hash_id` AFTER UPDATE ON `hashes`
FOR EACH ROW
BEGIN
UPDATE `emails` SET `id` = NEW.id WHERE `id` = OLD.id;
END;$$
DELIMITER ;
and you must remove the foreign key relation too.
The solution, which we have arrived in chat chat:
/* Tables */
CREATE TABLE `emails` (
`group_id` bigint(20) NOT NULL,
`email` varchar(500) NOT NULL,
UNIQUE KEY `group_id` (`group_id`,`email`) USING BTREE,
CONSTRAINT `emails_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `entities` (`group_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `hashes` (
`group_id` bigint(20) NOT NULL,
`hash` varchar(128) NOT NULL,
`repeat_count` int(11) NOT NULL DEFAULT '0',
UNIQUE KEY `hash` (`hash`),
KEY `group_id` (`group_id`),
CONSTRAINT `hashes_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `entities` (`group_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `entities` (
`group_id` bigint(20) NOT NULL,
`entity_id` bigint(20) NOT NULL,
PRIMARY KEY (`group_id`),
KEY `entity_id` (`entity_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `entity_lookup` (
`entity_id` bigint(20) NOT NULL,
PRIMARY KEY (`entity_id`) USING HASH
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/* Inserting */
START TRANSACTION;
/* Determine next group ID */
SET #next_group_id = (SELECT MAX(group_id) + 1 FROM entities);
/* Determine next entity ID */
SET #next_entity_id = (SELECT MAX(entity_id) + 1 FROM entities);
/* Merge any entity ids */
INSERT IGNORE INTO entity_lookup SELECT entity_id FROM entities JOIN hashes USING(group_id) WHERE HASH IN(...);
UPDATE entities JOIN entity_lookup USING(entity_id) SET entity_id = #next_entity_id;
TRUNCATE TABLE entity_lookup;
/* Add the new group ID to entity_id */
INSERT INTO entities(group_id, entity_id) VALUES(#next_group_id, #next_entity_id);
/* Add new values into hashes */
INSERT INTO hashes (group_id, HASH) VALUES
(#next_group_id, ...)
ON DUPLICATE KEY UPDATE
repeat_count = repeat_count + 1;
/* Add other new values */
INSERT IGNORE INTO emails (group_id, email) VALUES
(#next_group_id, "email1");
COMMIT;
Adding an extra integer column to each of the child tables would avoid this problem altogether by using it as a primary key. The key never changes because it isn't a reference to anything else.
Using composite keys as primary keys is generally something that you want to avoid. And considering that this key combination is not always unique, I would definitely say you need a dedicated primary key in all of your child tables with this problem.
You can even auto increment it so you aren't manually assigning it every time. For example..
Create Table exampleTable
(
trueID int NOT NULL AUTO_INCREMENT,
col1 int NOT NULL,
col2 varChar(50)
PRIMARY KEY(trueID)
)
Then, when two of the rows in a child table are set with identical values (for whatever reason), the primary key stays unique, preventing any conflicts in the Database that could arise.
Related
I am creating an inventory management app in node.js that uses MySQL as a database. I have a weak entity “rental_item” that holds the items in a particualr rental. The issue is that the rental may not come back all at once so I need a way of marking the “rental_returned” boolean in the rental table true only when all of the “item_returned” entires are true.
Here is my table structure:
CREATE TABLE `rental` (
`rental_id` int NOT NULL AUTO_INCREMENT,
`renter_id` int NOT NULL,
`date_in` date NOT NULL,
`date_out` date NOT NULL,
`sig_path` varchar(50) NOT NULL,
`doc_path` varchar(50) NOT NULL,
`col_name` varchar(50) NOT NULL,
`col_path` varchar(50) NOT NULL,
`cost` decimal(15,2) NOT NULL,
`rental_returned` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`rental_id`),
UNIQUE KEY `doc_path` (`doc_path`),
UNIQUE KEY `col_path` (`col_path`),
UNIQUE KEY `sig_path` (`sig_path`),
KEY `renter_key` (`renter_id`),
CONSTRAINT `renter_key` FOREIGN KEY (`renter_id`) REFERENCES `renter` (`renter_id`)
)
CREATE TABLE `rental_item` (
`rental_id` int NOT NULL,
`i_ID` varchar(20) NOT NULL,
`item_returned` tinyint(1) NOT NULL DEFAULT '0',
KEY `rental_key` (`rental_id`),
KEY `rental_item_key` (`i_ID`),
CONSTRAINT `rental_item_key` FOREIGN KEY (`i_ID`) REFERENCES `item` (`i_ID`),
CONSTRAINT `rental_key` FOREIGN KEY (`rental_id`) REFERENCES `rental` (`rental_id`) ON DELETE CASCADE
)
I am currently doing this through the mysql2 node.js module and just checking for all the values of a given rental_id. I then found out about triggers and thought this way could be better. I fiddled round with things like this Trigger with table join, but couldn’t wrap my head around how to get the rental_id of the entry that was updated from rental_item, then check that all entires in rental_item with that id have item_returned = 1, and finally update the rental table to show that all the items/the complete rental has been returned.
I understand that this sould be an update after trigger on rental_item but dont know how to handle the conditionals or loops needed.
Use NEW.rental_id to get the ID of the row that was updated.
CREATE TRIGGER rental_returned AFTER UPDATE ON rental_item
FOR EACH ROW
UPDATE rental
SET rental_returned = (
NOT EXISTS (
SELECT *
FROM rental_item
WHERE rental_id = NEW.rental_id
AND item_returned = 0))
WHERE rental_id = NEW.rental_id
Help me please!
I am having this error.
Error: Cannot add or update a child row: a foreign key constraint fails (world.alarmes, CONSTRAINT fk_alarmes_registos1 FOREIGN KEY (idRegisto) REFERENCES registos (idRegisto) ON DELETE NO ACTION ON UPDATE NO ACTION)
I have these tables.
CREATE TABLE `registos` (
`data_registo` char(10) NOT NULL,
`hora_registo` time NOT NULL,
`idSensor` varchar(8) NOT NULL,
`Temperatura` char(6) DEFAULT NULL,
`Humidade` char(6) DEFAULT NULL,
`pt_orvalho` char(6) DEFAULT NULL,
`idRegisto` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`idRegisto`,`idSensor`,`data_registo`,`hora_registo`),
KEY `fk_registos_sensores1_idx` (`idSensor`),
CONSTRAINT `fk_registos_sensores1` FOREIGN KEY (`idSensor`) REFERENCES `sensores` (`idSensor`) ON DELETE NO ACTION ON UPDATE NO ACTION
)
CREATE TABLE `alarmes` (
`idAlarme` int(11) NOT NULL AUTO_INCREMENT,
`descricao_alarme` varchar(45) DEFAULT NULL,
`data_criacao` datetime DEFAULT CURRENT_TIMESTAMP,
`idRegisto` int(11) NOT NULL DEFAULT ''0'',
PRIMARY KEY (`idAlarme`,`idRegisto`),
KEY `fk_alarmes_registos1_idx` (`idRegisto`),
CONSTRAINT `fk_alarmes_registos1` FOREIGN KEY (`idRegisto`) REFERENCES `registos` (`idRegisto`) ON DELETE NO ACTION ON UPDATE NO ACTION
)
When I do an insert into the table records the error pops up.
insert into registos values ('2014-03-31', '14:03:32', 'BrgTH032', '22.3', '45.3', '9.9', '32');
If I do this:
SET FOREIGN_KEY_CHECKS=0
the next insertion already accepted, but when I try again. back to give the same error.
I've been researching and fails because the registos table references a foreign key from the sensores table. You can't directly insert into a relational table without there being a corresponding entry in the table that is being referenced.
But I don't know how to resolve this.
Help me please.
-------EDIT( I used a trigger to populate the table Alarmes)------------------------
DELIMITER $$
create TRIGGER alerta
BEFORE INSERT ON registos
FOR EACH ROW
begin
Set #tempmax=0;
Set #tempmin=0;
select lim_inf_temp, lim_sup_temp into #tempmin, #tempmax from sensores where idSensor=NEW.idSensor;
Set #maxidAlarme=0;
if (CAST(NEW.Temperatura AS UNSIGNED)<#tempmin) then
SELECT MAX(idAlarme) into #maxidAlarme FROM alarmes;
SET #maxidAlarme=#maxidAlarme+1;
INSERT INTO alarmes(idAlarme,descricao_alarme, idRegisto) VALUES (#maxidAlarme,"temperatura inserida inferior ao normal",New.idRegisto);
end if;
if (CAST(NEW.Temperatura AS UNSIGNED)>#tempmax) then
SELECT MAX(idAlarme) into #maxidAlarme FROM alarmes;
SET #maxidAlarme=#maxidAlarme+1;
INSERT INTO alarmes(idAlarme,descricao_alarme, idRegisto) VALUES (#maxidAlarme,"temperatura inserida superior ao normal",New.idRegisto);
end if;
end $$;
DELIMITER ;
You are trying to insert more values into the table than allowed 7 (seven) but 6 (six) expected.
Please, always include the columns that you are inserting to in an 'insert' query.
There are seven columns in this table but one is an 'auto increment' column so there should be 6 (six) values in the insert query.
CREATE TABLE `registos` (
`data_registo` char(10) NOT NULL,
`hora_registo` time NOT NULL,
`idSensor` varchar(8) NOT NULL,
`Temperatura` char(6) DEFAULT NULL,
`Humidade` char(6) DEFAULT NULL,
`pt_orvalho` char(6) DEFAULT NULL,
`idRegisto` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`idRegisto`,`idSensor`,`data_registo`,`hora_registo`),
KEY `fk_registos_sensores1_idx` (`idSensor`),
CONSTRAINT `fk_registos_sensores1
Here is the 'insert' query:
insert into registos values ('2014-03-31', '14:03:32', 'BrgTH032', '22.3', '45.3', '9.9', '32');
There are seven values but you would expect the query to look like (columns added):
insert into registos (data_registo, hora_registo, idSensor, Temperatura, Humidade, pt_orvalho)
values ('2014-03-31', '14:03:32', 'BrgTH032', '22.3', '45.3', '9.9', '32');
I suggest that the query should be:
insert into registos (data_registo, hora_registo, idSensor, Temperatura, Humidade, pt_orvalho)
values ('2014-03-31', '14:03:32', 'BrgTH032', '22.3', '45.3', '9.9');
The trigger on 'registos' must be an after insert trigger to pick up the NEW 'idRegisto' value.
create TRIGGER alerta
AFTER INSERT ON registos
FOR EACH ROW
begin
I Want to add an Integer Column to a String that's because i need to generate a varchar variable with a numeric part that automatically increments. For example, P000001,P000002...
In order to do that what i am doing while creation of table i have taken an int field ID which auto_increments and i am Concatenating P with 00000 and the ID value
The Table i have created is :
CREATE TABLE tblAcceptTest(
ID int AUTO_INCREMENT NOT NULL primary key,
PatientID as CONCAT('P' , CONCAT('000000',CAST(ID as char)))
);
It Shows me the error from as keyword.
Please help
MySQL's documentation (http://dev.mysql.com/doc/refman/5.1/en/create-table.html) says, "the default value must be a constant; it cannot be a function or an expression." Why don't you just get the PatientID value afterward as part of the SELECT:
SELECT CONCAT('P', LPAD(ID, 6, 0)) AS PatientID FROM tblAcceptTest;
It looks like you want six digits after the "P", so try this for your expression:
CONCAT('P', LPAD(ID, 6, '0'))
Mysql has little support for computed columns.
Patient ID from your specification could be a char(7)
CREATE TABLE tblAcceptTest(
ID int AUTO_INCREMENT NOT NULL primary key,
PatientID char(7)
);
Then create some triggers. Note that the following insert trigger will cause issues with high concurrency servers.
DELIMITER |
CREATE TRIGGER tblAcceptTest_insert BEFORE INSERT ON tblAcceptTest
FOR EACH ROW BEGIN
DECLARE next_id INT;
SET next_id = (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='tblAcceptTest');
SET NEW.PatientID = CONCAT('P' , RIGHT(CONCAT('000000',next_id),6)) ;
END;
|
CREATE TRIGGER tblAcceptTest_update BEFORE UPDATE ON tblAcceptTest
FOR EACH ROW BEGIN
SET NEW.PatientID = CONCAT('P' , RIGHT(CONCAT('000000',NEW.ID),6)) ;
END;
|
DELIMITER ;
You use relationships and views to achieve the same result.
CREATE TABLE `patient` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`patient` varchar(60) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `accepted_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`patient_id` int(11) NOT NULL,
`accepted` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `patient_id` (`patient_id`),
CONSTRAINT `accepted_test_ibfk_1` FOREIGN KEY (`patient_id`) REFERENCES `patient` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
create or replace view accepted_test_veiw as
select CONCAT('P' , RIGHT(CONCAT('000000',patient_id),6)) patient_key
, accepted
, id accepted_test_id
, patient_id
from accepted_test ;
select * from `accepted_test_veiw`
There is a table:
CREATE TABLE `mytable` (
`user_id` INT(10) UNSIGNED NOT NULL,
`thing_id` VARCHAR(100) NOT NULL DEFAULT '',
`lock_date` DATETIME NOT NULL,
`lock_id` VARCHAR(36) NOT NULL,
PRIMARY KEY (`user_id`,`thing_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
and some values there:
INSERT INTO mytable(user_id,thing_id,lock_date,lock_id)
VALUES
(51082,'299ac9ff-2b2b-102d-8ff6-f64c971398c3','2012-03-16 00:39:12','ec7b2008-6ede-11e1-aac2-5924aae99221'),
(108325,'299ac9ff-2b2b-102d-8ff6-f64c971398c3','2013-02-05 19:30:03','7c6de986-6edd-11e1-aac2-5924aae99221'),
(108325,'d90b354d-4b5f-11e0-9959-47117d41cf4b','2012-03-16 00:47:41','1c243032-6ee0-11e1-aac2-5924aae99221');
I want to delegate all records of user_id = 108325 to user_id = 51082, and if both users have an equal thing_id field, leave the newer one only (lock_date1 > lock_date2), so that I have following result:
51082,'299ac9ff-2b2b-102d-8ff6-f64c971398c3','2013-02-05 19:30:03','7c6de986-6edd-11e1-aac2-5924aae99221'
108325,'d90b354d-4b5f-11e0-9959-47117d41cf4b','2012-03-16 00:47:41','1c243032-6ee0-11e1-aac2-5924aae99221'
Note that 51082 now has a newer record: lock_date = '2013-02-05 19:30:03' instead of '2012-03-16 00:39:12'.
So, how can I update a row, and on duplicate key leave the newer one (by some particular field)?
Thanks!
INSERT INTO
mytable(user_id,thing_id,lock_date,lock_id)
VALUES
(51082,'299ac9ff-2b2b-102d-8ff6-f64c971398c3','2012-03-16 00:39:12','ec7b2008-6ede-11e1-aac2-5924aae99221'),
(108325,'299ac9ff-2b2b-102d-8ff6-f64c971398c3','2013-02-05 19:30:03','7c6de986-6edd-11e1-aac2-5924aae99221'),
(108325,'d90b354d-4b5f-11e0-9959-47117d41cf4b','2012-03-16 00:47:41','1c243032-6ee0-11e1-aac2-5924aae99221')
ON DUPLICATE KEY UPDATE SET
user_id = VALUES(user_id),
lock_date = VALUES(lock_date),
lock_id = VALUES(lock_id)
Having some troubles with ON DUPLICATE KEY UPDATE in MySQL. Below is the query im trying to run.
INSERT INTO `Overall` ( `rsn` , `starting_xp` , `starting_lvl` ) VALUES ( 'iWader' , '195843626' , '2281' ) ON DUPLICATE KEY UPDATE `current_xp` = '195843626' AND `current_lvl` = '2281'
It inserts fine, but when there is a duplicate it doesnt update, and doesnt throw any errors.
Running the query through PMA returns no error and doesnt update
Removing the ON DUPLICATE KEY UPDATE section returns a duplicate key error
This is the structure of my table
CREATE TABLE IF NOT EXISTS `overall` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rsn` varchar(12) NOT NULL,
`starting_xp` int(10) unsigned NOT NULL,
`starting_lvl` int(10) unsigned NOT NULL,
`current_xp` int(10) unsigned NOT NULL,
`current_lvl` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `rsn` (`rsn`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
After ON DUPLICATE KEY UPDATE you should not need to use and with the fields, use , instead.
ON DUPLICATE KEY UPDATE `current_xp` = '195843626', `current_lvl` = '2281'
Try this:
INSERT INTO `Overall` ( `rsn` , `starting_xp` , `starting_lvl` ) VALUES ( 'iWader' , '195843626' , '2281' ) ON DUPLICATE KEY UPDATE `current_xp` = '195843626', `current_lvl` = '2281';
The AND in your UPDATE clause is wrong. The AND is used in boolean expressions like "is foo true AND bar true?"
Here you want to update column current_xp, current_lvl.