MySql complains about 'Duplicate entry' though unique data is being entered - mysql

I have this table in a mysql database:
mysql> show columns from wifi_network_config_auth_algorithm;
+------------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+-------------+------+-----+---------+-------+
| wifi_network_config_id | int(11) | NO | PRI | NULL | |
| auth_algorithm | varchar(50) | NO | PRI | NULL | |
+------------------------+-------------+------+-----+---------+-------+
The table was created using liquibase. Table creation itself does not define primary keys. Following table creation, the following liquibase command is used to set the combination of 2 columns as the primary key:
<addPrimaryKey tableName="wifi_network_config_auth_algorithm"
columnNames="wifi_network_config_id,auth_algorithm"
constraintName="pk_wifi_network_config_auth_algorithm"/>
Now, when you execute this to load data into this table:
LOCK TABLES `wifi_network_config_auth_algorithm` WRITE;
INSERT INTO `wifi_network_config_auth_algorithm` VALUES
(1, 'OPEN'),
(1, 'SHARED'),
(2, 'SHARED'),
(2, 'LEAP');
UNLOCK TABLES;
You get:
ERROR 1062 (23000): Duplicate entry '1' for key 2
Since the combination of both columns is the primary key, so the combination of the data in the two columns should be unique - which is true for the data shown above. Why is mysql complaining?
Also, it's complaining that the value '1' is being assigned to key 2, which does not make sense. I changed the INSERT to:
INSERT INTO `wifi_network_config_auth_algorithm` (`wifi_network_config_id`, `auth_algorithm`)
but it did not make any difference - same complaint from mysql.
Thanks,
Hari

This works for me. Is the table empty or missing these values before you execute the insert statement?
If I run this example twice I get an error message:
Duplicate entry '1-OPEN' for key 'PRIMARY'
Calling DELETE FROM wifi_network_config_auth_algorithm first avoids that.
Otherwise there must be something wrong with the way the primary key was created, since your error message differs.
I created a test table using the following:
CREATE TABLE `test` (
`wifi` int(11) NOT NULL,
`auth` varchar(50) NOT NULL,
PRIMARY KEY (`wifi`,`auth`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Figured out the issue with #kbenson's help. The answer is in the comments for the original question.

Related

How to insert a field that contains a modified value of a row

I have this table:
CREATE TABLE `new_random` (
`i_domain` varchar(500) DEFAULT NULL,
`i_domain_no_http` varchar(500) DEFAULT NULL,
UNIQUE KEY `i_domain_UNIQUE` (`i_domain`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
I have created the field i_domain_no_http using alter table. It is a new column (no value there it is initial set to NULL) where I want to insert the exact values of i_domain but after modifying them and removing a prefix http://./
I made the query:
insert into `myscheme`.`new_random` (`new_random`.`i_domain_no_http`)
select substring_index(`new_random`.`i_domain`,'http://',-1)
from `myscheme`.`new_random`;
Example, the table should look like:
i_domain | i_domain_no_http
------------------------------------
http://11.com | 11.com
https://22.com | 22.com
But I am getting this error:
i_domain | i_domain_no_http
------------------------------------
http://11.com |
https://22.com |
NULL | 11.com
NULL | 22.com
The 'i_domain' should be a primary key and not NULL but I had to remove the NN and PK to avoid the error:
Error Code: 1364. Field 'i_domain' doesn't have a default value
What is the problem? How to solve it?
What you want is an UPDATE query:
UPDATE myscheme.new_random
SET i_domain_no_http = SUBSTRING_INDEX(new_random.i_domain,'://',-1)
Output:
i_domain i_domain_no_http
http://11.com 11.com
https://22.com 22.com
Demo on dbfiddle

Query fails to load data in the way I expect, overwrites existing data

I have the following query:
INSERT INTO `user_pen_names` (`uid`,`pnid`,`my_name`) VALUES ('7','200','stink') ON DUPLICATE KEY UPDATE `my_name`=values(`my_name`)
My table has the following columns defined:
id INT primary, auto-increment
uid INT unsigned, unique
pnid INT unsigned, unique
my_name VARCHAR(24)
I have one table entry already:
id(0), uid(7), pnid(100), my_name(test)
When I execute the above query, what I expected to see was two rows:
id(0), uid(7), pnid(100), my_name(test)
id(1), uid(7), pnid(200), my_name(stink)
What's happening, and I am one confused puppy because of it, is that the existing row is being modified...
id(0), uid(7), pnid(100), my_name(stink)
The same thing happens if I modify uid and pnid so they are no longer unique. Can anyone explain to me why this is happening?
EDIT I made the two columns combinationally unique using the following command:
ALTER TABLE `user_pen_names` ADD UNIQUE KEY `upn_unique_id` (`uid`, `pnid`)
I've not done this before, but theoretically, the INSERT command should only shift to its UPDATE sub-command when uid AND pnid match a row already in the table. Nevertheless, this also didn't work.
It works fine for me. I suspect you didn't run the test you thought you were running.
I tested on a Macbook with MySQL 8.0.1:
mysql> CREATE TABLE `user_pen_names` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(10) unsigned DEFAULT NULL,
`pnid` int(10) unsigned DEFAULT NULL,
`my_name` varchar(24) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uid` (`uid`,`pnid`)
);
mysql> INSERT INTO `user_pen_names` (id, `uid`,`pnid`,`my_name`) VALUES (0, '7','100','test');
mysql> INSERT INTO `user_pen_names` (`uid`,`pnid`,`my_name`) VALUES ('7','200','stink')
ON DUPLICATE KEY UPDATE `my_name`=values(`my_name`);
mysql> SELECT * FROM user_pen_names;
+----+------+------+---------+
| id | uid | pnid | my_name |
+----+------+------+---------+
| 1 | 7 | 100 | test |
| 2 | 7 | 200 | stink |
+----+------+------+---------+
Note that when you insert a 0 into an auto-increment column, it generates a new id, starting at 1.
You have uid & pnid set as unique. So because you can't insert another uid=7, it's modifying the 7 row that has uid of 7 already.

MySQL update query not using indexed columns

I tried the following SQL query to update the table INDEXED_MERCHANT where I have 10000 records in the table. I indexed both "Name" and "A" as Indexed keys to improve the update query performance. By executing the command SHOW CREATE TABLE INDEXED_MERCHANT; I'll get an output result as follows:
INDEXED_MERCHANT | CREATE TABLE `INDEXED_MERCHANT` (
`ID` varchar(50) NOT NULL,
`NAME` varchar(200) DEFAULT NULL,
`ONLINE_STATUS` varchar(10) NOT NULL,
`A` varchar(100) DEFAULT NULL,
`B` varchar(200) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `NAME` (`NAME`,`A`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
Here this means both my keys are recognized as indexed keys. When I execute the following command, the "Extra" column result says the query doesn't using the index keys. How should I achieve my goal ?
Executed query : EXPLAIN EXTENDED UPDATE INDEXED_MERCHANT SET ONLINE_STATUS = '0' WHERE NAME = 'A 205' AND A = 'P 205';
Result:
+----+-------------+------------------+-------+---------------+------+---------+-------------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | **Extra** |
+----+-------------+------------------+-------+---------------+------+---------+-------------+------+----------+-------------+
| 1 | SIMPLE | INDEXED_MERCHANT | range | NAME | NAME | 906 | const,const | 1 | 100.00 | **Using where** |
+----+-------------+------------------+-------+---------------+------+---------+-------------+------+----------+-------------+
Your query is hitting "NAME" index as evident in explain output column "key".
Here is the explanation of key and extra columns from mysql documentation
key
The key column indicates the key (index) that MySQL actually decided to use. If MySQL decides to use one of the possible_keys indexes to look up rows, that index is listed as the key value.
Using where
A WHERE clause is used to restrict which rows to match against the next table or send to the client. Unless you specifically intend to fetch or examine all rows from the table, you may have something wrong in your query if the Extra value is not Using where and the table join type is ALL or index. Even if you are using an index for all parts of a WHERE clause, you may see Using where if the column can be NULL.

Inserting New Items Into an Already Populated Table

I have a table with various fields including a primary key, id, which is auto-incrementing:
+-------------------------------+------------------+------+-----+---------+
| Field | Type | Null | Key | Default | Extra
+-------------------------------+------------------+------+-----+---------+
| id | tinyint(11) | NO | PRI | NULL | auto_increment
The table is already populated with 114 items:
mysql> select count(*) as cnt from beer;
+-----+
| cnt |
+-----+
| 114 |
+-----+
And I am trying to insert a group of new items into the table. I am not explicitly inserting an id key. Here's a sample query:
mysql> INSERT INTO beer (name, type, alcohol_by_volume, description, image_url)
VALUES('Test Ale', 1, '4.6', '', 'https://untappd.s3.amazonaws.com/site/assets/images/temp/badge-beer-default.png');
I get the following error when attempting to manually insert that query (the insertion is actually done with a PHP script to the same results):
ERROR 1062 (23000): Duplicate entry '127' for key 1
What's going on? I thought the id would automatically increment upon insertion. I should note that the first 13 entries are blank/null for some reason, and the last key is currently 127. (it's not my table -- I'm just writing the script).
Tiny int is not the good choice for auto_increment primary key... Range is just (-128...127). Normally it's used as a flag; you need to use unsigned int
Try resetting the auto increment of primary key manually using this:
ALTER TABLE `beer` AUTO_INCREMENT = 128;

How do I prevent MySQL from auto-incrementing the Primary Key while using ON DUPLICATE KEY UPDATE when the duplicate is a different unique column?

Consider the following table:
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| vendor_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| vendor_name | varchar(100) | NO | UNI | NULL | |
| count | int(10) unsigned | NO | | 1 | |
+-------------+------------------+------+-----+---------+----------------+
I have the following MySQL query:
INSERT INTO `table`
(`vendor_name`)
VALUES
('foobar') ON DUPLICATE KEY UPDATE `count` = `count` + 1
The intent of this query is to insert a new vendor name to the table and in case the vendor name already exists, the column count should be incremented by 1. This works however the primary key of the current column will also be auto-incremented. How can I prevent MySQL from auto-incrementing the primary key in these cases? Is there a way to do this with one query?
Thank you.
This works however the primary key of the current column will also be auto-incremented. How can I prevent MySQL from auto-incrementing the primary key in these cases?
By using an UPDATE statement when the value already exists:
IF EXISTS(SELECT NULL
FROM TABLE
WHERE vendor_name = $vendor_name) THEN
UPDATE TABLE
SET count = count + 1
WHERE vendor_name = $vendor_name
ELSE
INSERT INTO TABLE
(vendor_name)
VALUES
($vendor_name
END IF
I tried the alternative to ON DUPLICATE KEY UPDATE, REPLACE INTO:
REPLACE INTO vendors SET vendor_name = 'foobar', COUNT = COUNT + 1
It updates the count, and the vendor_id so it's worse...
The database & data doesn't care if the numbers aren't sequential, only that the values are unique. If you can live with that, I'd use the ON DUPLICATE UPDATE syntax though I admit the behaviour is weird (understandable considering using an INSERT statement).
I think this might do it. But it's very much against the principles of Daoism - you're really going against the grain.
There is probably a better solution.
INSERT INTO `table`
(`vendor_name`)
VALUES
('foobar') ON DUPLICATE KEY UPDATE `count` = `count` + 1, `vendor_id`=`vendor_id`-1