ON DUPLICATE KEY UPDATE won't work - mysql

I'm trying like hours to make a simple MySQL command and it won't work.
I have a database where package IDs for Apps are stored, like 'com.android.package'.
They are stored like so:
| ID | PackageID | PackageDesc |
| 1 | com.android.package | This is a package |
| 2 | com.android.test2pa | This is package 2 |
And so on...
Now I want to insert a new entry, if 'com.android.package' don't exist and if it exists, I want to do nothing...
I've tried following:
INSERT INTO Packages (PackageID) VALUES ('com.android.package') ON DUPLICATE KEY UPDATE PackageID=VALUES(PackageID)
But it still creates new entries, like that:
| ID | PackageID | PackageDesc |
| 3 | com.android.package | |
| 4 | com.android.package | |
| 5 | com.android.package | |
I don't know where's my error.

A proposed Packages table schema for ON DUPLICATE KEY UPDATE to work as expected is the following:
CREATE TABLE Packages (
`ID` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`PackageID` VARCHAR(30) NOT NULL,
`PackageDesc` VARCHAR (100),
UNIQUE(`PackageID`)
);
After this statement is executed:
INSERT INTO Packages (PackageID, PackageDesc) VALUES
('com.android.package', 'This is a package')
ON DUPLICATE KEY UPDATE PackageID=VALUES(PackageID);
Packages contains the following row:
# ID, PackageID, PackageDesc
'1', 'com.android.package', 'This is a package'
If you now execute the following statement:
INSERT INTO Packages (PackageID, PackageDesc) VALUES
('com.android.package', 'This is a package2')
ON DUPLICATE KEY UPDATE PackageID=VALUES(PackageID), PackageDesc=VALUES(PackageDesc);
Packages contains:
# ID, PackageID, PackageDesc
'1', 'com.android.package', 'This is a package2'
This means an UPDATE was performed by the latter INSERT INTO.
Demo here

Related

How do I use INSERT ... ON DUPLICATE KEY UPDATE?

State Problem
Apart from 1st col in MySQL server which is PK and auto_increment, col "C" is STRING/VARCHAR. How do I use INSERT ... ON DUPLICATE KEY UPDATE on col "C".
Should I also set col "C" as UNIQUE as well?
Example
Assume that my table in MySQL server looks similar to this...
---------------------------
|ID(PK)| A | B | C | D | E |
+------+---+---+---+---+---+
| 1 | | | | | |
| 2 | | | | | |
| 3 | | | | | |
---------------------------
What I expect
The duplicate input must be ignored from the MySQL server.
Can I also send alert pop-up/session pop-up, if the duplicate has been inserted into MySQL server as "This query has already existed."?
Column C must be set to NOT NULL, UNIQUE then SQL will return error against attempt of duplicate value insert. You may handle that error in your backend code. Or you can handle and alter the duplicate value with 'ON DUPLICATE KEY UPDATE' clause:
INSERT INTO t1 (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;

Insert statement in self-join table

What is the correct statement to make an insert in a table with a self-join?
If I try to make a classic insert I get the error:
Cannot add or update a child row: a foreign key constraint fails
This is my insert query:
insert into mTable(record_name,self_fk,val, note, ref,insert_date, end_date)
values('processo prova',0,1,'nota di prova', 'az12345', NOW(), NOW());
In your INSERT query, you are referencing to a foreign key (the id 0) that doesn't exist -> constraint fails
I saw in your edits, before you roll it back, your CREATE TABLE script.
The field containing the reference to the parent was created this way :
`id_processo_padre` int(11) NOT NULL DEFAULT '1'
I suggest you to edit this field to make it nullable :
ALTER TABLE `mTable` MODIFY `id_processo_padre` int(11) NULL;
This will allow you to INSERT the first top level parent (or any top level parent)
insert into mTable(record_name, self_fk, ...)
values('processo prova', NULL, ...);
-- ^--^----------This
Test it yourself :
Schema (MySQL v5.7)
CREATE TABLE test
(
id INT(6) NOT NULL PRIMARY KEY AUTO_INCREMENT,
parent_id INT(6) NULL,
someData VARCHAR(255),
FOREIGN KEY (parent_id) REFERENCES test(id)
);
INSERT INTO test VALUES (default, null, "parent"),
(default, 1, "child1_1"),
(default, 1, "child1_2"),
(default, 3, "child2_2");
Query #1
SELECT t1.*, t2.someData AS "My parent's name" FROM test t1
LEFT JOIN test t2
ON t2.id = t1.parent_id
ORDER BY t1.id ASC;
Output
| id | parent_id | someData | My parent's name |
| --- | --------- | -------- | ---------------- |
| 1 | null | parent | null |
| 2 | 1 | child1_1 | parent |
| 3 | 1 | child1_2 | parent |
| 4 | 3 | child2_2 | child1_2 |
View on DB Fiddle

Insert Into.. Select.. On Duplicate Key Update

I'm trying to test how the insert into duplicate key works. And currently this is what I did:
INSERT INTO
user_test (userName, first, last)
SELECT
u.userName, u.first, u.last
FROM otherdatabase.user as u
ORDER BY u.userName ASC
ON DUPLICATE KEY UPDATE
userName = u.userName
I executed this query and it worked and inserted rows. Then what I did was I modified one row from the user table and then tried to run this query again, but instead of just updating that one row it inserted all the rows again.
From what I understand shouldn't it just update that one row I modified from the user table?
What I'm trying to do is do a "Insert if it doesn't exist and update if it exist" query and found that using insert into .. on duplicate key can do that but I'm obviously doing it wrong...
CREATE TABLE user_test (
id bigint(20) NOT NULL AUTO_INCREMENT,
userName varchar(20) DEFAULT NULL,
first varchar(20) DEFAULT NULL,
last varchar(20) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=64 DEFAULT CHARSET=latin1
Per Barranka's suggestion I added a unique index to the user_name column
Alter table user_test add unique index idx_userName(userName)
Then I ran the query again and it didn't add any more rows since its already existing..
This is an example of what the user_table looks like now, its now the same on the users table.
user_table:
userName | first | last |
ckeith | Carl | Keith |
mmonroe | Mickey | Monroe |
Then what I did to test it again is from the user table I modified one of the rows
user:
userName | first | last |
ckeithh | Carl | Keith |
mmonroe | Mickey | Monroe |
and executed the query again, this is now what the users_table looks like:
user_table:
userName | first | last |
ckeith | Carl | Keith |
mmonroe | Mickey | Monroe |
ckeithh | Carl | Keith |
I thought it would just update the first row to ckeithh but it just inserted one row?
My expected output was:
user_table:
userName | first | last |
ckeithh | Carl | Keith |
mmonroe | Mickey | Monroe |
Update:
I added a unique index and made sure that it is unique. The inserting works but now the update is not working. Anything else i should try?
Still not able to get this to work, I have confirmed that the column i'm using is unique and that my version of mysql is v5 (i saw on one of the forums that for this to work mysql should be v5, not sure if thats real or not, but still i checked and im using v5.5.37)

InnoDB hierarchical data: recursively delete fragment of a tree

This is my table:
CREATE TABLE `pages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent` int(11) DEFAULT NULL,
`label` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
where id is a unique id (autoincrement) and parent is also an id from the same table. If parent is NULL, the page hasn't got parent.
What I want? If I delete one parent, it should auto delete all his childs in the same table. I believe that this can be done using on DELETE CASCADE, and this is the way that I want to do it :). But I've tried many configurations of code, and none of them work. Either table cannot be created, or insert query is not working, because of an error that looks similar to "key not exist".
What I found?
How to recursively delete items from table? - answer is great, but with none of code. This answer to the same question:
https://stackoverflow.com/a/9260373/1125465 doesn't work for me. There are some problems with table creation. I think this answer was made in a hurry, and there is some key word missing?
Recursive MySQL Query with relational innoDB this one is simmilar, but not the same case, there are few tables.
Sql server - recursive delete - Come on, there must be a simpliest answer...
Technical info:
mysql Ver 14.14 Distrib 5.1.70, for pc-linux-gnu (x86_64) using
readline 5.1
Table engine: InnoDB
This works for me (and here's a fiddle http://sqlfiddle.com/#!8/d15b4/1):
CREATE TABLE
test
(
id INT NOT NULL PRIMARY KEY,
parent INT,
CONSTRAINT
fk_test_test
FOREIGN KEY
(parent)
REFERENCES
test (id)
ON DELETE CASCADE
);
INSERT
INTO test
VALUES (1, NULL),
(2, 1),
(3, 2),
(4, 3),
(5, NULL),
(6, 5);
SELECT *
FROM test;
+----+--------+
| id | parent |
+----+--------+
| 1 | NULL |
| 5 | NULL |
| 2 | 1 |
| 3 | 2 |
| 4 | 3 |
| 6 | 5 |
+----+--------+
DELETE
FROM test
WHERE id = 1;
SELECT *
FROM test;
+----+--------+
| id | parent |
+----+--------+
| 5 | NULL |
| 6 | 5 |
+----+--------+

MySQL update to other tables

I want to be able to insert data into t1 and have data get populated in table t2 with the primary key as a foreign key in t2.
Basically, how come in my current setup when I INSERT INTO t1 (first_name, last_name) values ( "blah", "blah"); and then do SELECT * FROM t2; t2 it says Empty Set (0.00 sec) for t2? Shouldn't it at least show the default id of 1?
t1:
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| first_name | varchar(20) | NO | | NULL | |
| last_name | varchar(20) | NO | | NULL | |
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
+------------+------------------+------+-----+---------+----------------+
t2:
+-----------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+-------+
| address | varchar(50) | NO | | NULL | |
| id | int(10) unsigned | NO | MUL | NULL | |
| last_name | varchar(20) | YES | | NULL | |
+-----------+------------------+------+-----+---------+-------+
In a relational database, a FOREIGN KEY is a declaration that you intend to insert values into T2 that must match an already existing value in T1, and that you want the database to refuse to perform any action that would break this relationship.
It does not mean that the database will create records on its own in order to satisfy a relationship. If you try to insert a value into T2 that does not exist in T1, the command will fail; it will not add the required record to T1.
That is the opposite of what you're suggesting, however, in which you want the foreign key values to get automatically generated. However, there's no requirement that a primary key value actually have references and, furthermore, no limit on the number of times that primary key value can be referenced — so how would the database guess what should be created in T2?
That said, if you want some of your own code to execute automatically when data is added to T1, code which can do whatever you want, you can create a trigger on T1.
No, tables won't propagate automatically. (You can however do it with triggers) You will have to insert into t2.
You can create a trigger on table t1 so that it inserts a row into t2 with the correct id and the other fields NULL
Foreign keys will not insert records for you.
DELIMITER ;;
CREATE TRIGGER insert_addr_rec BEFORE INSERT ON t1
FOR EACH ROW BEGIN
INSERT INTO t2 SET id=NEW.id, last_name=NEW.last_name
END ;;
DELIMITER ;
NB untested code