strange "Duplicate entry" error of mysql - mysql

This might be an unicode related problem.
I have a mysql source file:
set names utf8;
STATUS;
drop table tianya;
create table tianya ( name char(50) not null primary key, passwd char (50) not null, email char(50));
insert into tianya values ("■■■■■■■■","68221",""),("12345678","098",""),("〡〢〣〤〥〦〧〨","1","");
And when I run this sql file, mysql reports:
ERROR 1062 (23000) at line 5: Duplicate entry '〡〢〣〤〥〦〧〨' for key 'PRIMARY'
as this image:
However, as we can see, the table is whole new, and the 3 primary keys are different from each other.
So, what causes this error?
=======add some extra info on 2015-Aug-28
mysql> create table tianya ( name char(50) not null primary key, passwd char (50) not null, email char(50));
Query OK, 0 rows affected (0.16 sec)
mysql>
mysql>
mysql> insert into tianya values ("■■■■■■■■","68221",""),("12345678","098","");
Query OK, 2 rows affected (0.19 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select name,hex(name) from tianya;
+--------------------------+--------------------------------------------------+
| name | hex(name) |
+--------------------------+--------------------------------------------------+
| ■■■■■■■■ | E296A0E296A0E296A0E296A0E296A0E296A0E296A0E296A0 |
| 12345678 | 3132333435363738 |
+--------------------------+--------------------------------------------------+
2 rows in set (0.03 sec)
mysql> insert into tianya values ("1234567","098",""),("〡〢〣〤〥〦〧〨","1","");
ERROR 1062 (23000): Duplicate entry '〡〢〣〤〥〦〧〨' for key 'PRIMARY'
mysql> delete from tianya;
Query OK, 2 rows affected (0.02 sec)
mysql> insert into tianya values ("1234567","098",""),("〡〢〣〤〥〦〧〨","1","");
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select name,hex(name) from tianya;
+--------------------------+--------------------------------------------------+
| name | hex(name) |
+--------------------------+--------------------------------------------------+
| 1234567 | 31323334353637 |
| 〡〢〣〤〥〦〧〨 | E380A1E380A2E380A3E380A4E380A5E380A6E380A7E380A8 |
+--------------------------+--------------------------------------------------+
2 rows in set (0.00 sec)
mysql> describe tianya;
+--------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| name | char(50) | NO | PRI | NULL | |
| passwd | char(50) | NO | | NULL | |
| email | char(50) | YES | | NULL | |
+--------+----------+------+-----+---------+-------+
3 rows in set (0.05 sec)
mysql> show create table tianya ( name char(50) not null primary key, passwd char (50) not null, email char(50));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '( name char(50) not null primary key, passwd char (50) not null, email char(50))' at line 1
mysql> show create table tianya;
+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tianya | CREATE TABLE `tianya` (
`name` char(50) COLLATE utf8_unicode_ci NOT NULL,
`passwd` char(50) COLLATE utf8_unicode_ci NOT NULL,
`email` char(50) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
====and another test:
xungeng#fl-ubuntu:~/tmp/a$ mysql -u root test < a.sql
Table Create Table
t2 CREATE TABLE `t2` (\n `name` varchar(10) COLLATE utf8_unicode_ci NOT NULL,\n UNIQUE KEY `name` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
ERROR 1062 (23000) at line 5: Duplicate entry 'hì' for key 'name'
xungeng#fl-ubuntu:~/tmp/a$ cat a.sql
set names utf8;
drop table if exists t2;
create table t2 (name varchar(10) not null unique key);
show create table t2;
insert into t2 values ("hí"),("hì");

Finally I know what had happened.
The collate utf_unicode_ci is case insensitive. This makes an insert of primary or unique key of 'TEST' failed if there is a key 'test' or 'Test'. I thought the collision is caused by '■■■■■■■■' and '〡〢〣〤〥〦〧〨', this misled you and also me. In fact the collision is caused by '12345678' and '〡〢〣〤〥〦〧〨'.
The symbols '〡〢〣〤〥〦〧〨' look so curious. They are ancient chinese symbols for number 12345678, respectively. [refer: https://zh.wikipedia.org/wiki/%E7%AD%B9%E7%AE%97 (chinese edition only)]
To resolve this problem, I changed utf8_unicode_ci to utf8_bin.

You can add to the charset of the table in the create statement. Append 'Set charset=utf8'. Maybe that helps. See http://dev.mysql.com/doc/refman/5.1/en/create-table.html
Section table-options

Related

MySQL/MariaDB unable to handle unique keys with when using utf8mb4

We have MySQL table with utf8mb4 strings:
CREATE TABLE `test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`code` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `test_code_unique` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
When inserting special characters there appears to be wrong conversion:
mysql> insert into `test` (`code`, `name`) values ('munster', 'Munster');
mysql> insert into `test` (`code`, `name`) values ('münster', 'Münster');
ERROR 1062 (23000): Duplicate entry 'münster' for key 'test_code_unique'
mysql> SELECT * FROM test WHERE code='münster';
+----+---------+---------+
| id | name | code |
+----+---------+---------+
| 1 | Munster | munster |
+----+---------+---------+
1 row in set (0.00 sec)
mysql> SELECT * FROM test WHERE code='munster';
+----+---------+---------+
| id | name | code |
+----+---------+---------+
| 1 | Munster | munster |
+----+---------+---------+
1 row in set (0.00 sec)
If unique key is removed second insert works but a search returns 2 rows even if query is different:
mysql> drop table test;
CREATE TABLE `test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`code` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
mysql> insert into `test` (`code`, `name`) values ('munster', 'Munster');
mysql> insert into `test` (`code`, `name`) values ('münster', 'Münster');
mysql> SELECT * FROM test WHERE code='münster';
+----+----------+----------+
| id | name | code |
+----+----------+----------+
| 1 | Munster | munster |
| 2 | Münster | münster |
+----+----------+----------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM test WHERE code='munster';
+----+----------+----------+
| id | name | code |
+----+----------+----------+
| 1 | Munster | munster |
| 2 | Münster | münster |
+----+----------+----------+
2 rows in set (0.00 sec)
This has been tested on both MySQL 5.7 and MariaDB 10.2 and they both give same results.
What could be going wrong?
The reason for this seemingly mysterious problem is that you're using utf8mb4_unicode_ci collation, and that collation intentionally ignores differences in accented characters vs non-accented characters. See: https://dev.mysql.com/doc/refman/5.7/en/charset-general.html
To resolve this, change collation on code column to utf8mb4_bin, which will distinguish between accented characters and non-accented characters, and also between caSe.

MYSQL have set a column to not null but still it's accepting null value [duplicate]

This question already has answers here:
A constraint to prevent the insert of an empty string in MySQL
(2 answers)
Closed 8 years ago.
Structure for a table in mysql5.5
tablename:
id:
name:
detail:
here even altering the table:
ALTER TABLE tablename MODIFY name VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL;
OR
ALTER TABLE `tablename` CHANGE `name` `name` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL DEFAULT NOT NULL;
after inserting value:
INSERT INTO `databasename`.`tablename` (`id`, `name`, `detail`) VALUES (NULL, '', 'asdfasfdadsfadsfafd');
query has run successfully no error row has been added to table,
how can i prevent such empty or null.
regards
Try this:
ALTER TABLE tablename
MODIFY COLUMN name VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL CHECK (name <> '');
DEMO:
mysql> create table tablename(id int(2) not null, something varchar(25) null, primary key(id));
Query OK, 0 rows affected (0.15 sec)
mysql> insert into tablename values(0,'hello');
Query OK, 1 row affected (0.38 sec)
mysql> insert into tablename values(1,'salut');
Query OK, 1 row affected (0.31 sec)
mysql> select * from tablename;
+----+-----------+
| id | something |
+----+-----------+
| 0 | hello |
| 1 | salut |
+----+-----------+
2 rows in set (0.00 sec)
Now, I run the UPDATE command:
mysql> ALTER TABLE tablename MODIFY COLUMN something VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL;
Query OK, 2 rows affected (0.70 sec)
Records: 2 Duplicates: 0 Warnings: 0
I insert a normal row:
mysql> insert into tablename values(2,'france');
Query OK, 1 row affected (0.29 sec)
But it does not allow me to insert a NULL value:
mysql> insert into tablename values(3,NULL);
ERROR 1048 (23000): Column 'something' cannot be null
I check to be sure:
mysql> select * from tablename;
+----+-----------+
| id | something |
+----+-----------+
| 0 | hello |
| 1 | salut |
| 2 | france |
+----+-----------+
3 rows in set (0.00 sec)

MySQL INSERT ... ON DUPLICATE KEY not updating table with no errors or warnings

So I have the following table:
mysql> show create table user_api_skills \G
*************************** 1. row ***************************
Table: user_api_skills
Create Table: CREATE TABLE `user_api_skills` (
`characterID` int(11) NOT NULL,
`typeID` int(11) NOT NULL,
`level` enum('0','1','2','3','4','5') NOT NULL DEFAULT '0',
`skillpoints` int(11) NOT NULL,
`currentTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`characterID`,`typeID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql>
And in that table a row which I am trying to insert/update:
mysql> SELECT * FROM `user_api_skills` WHERE `characterID` =93192782 AND `typeID` =3359;
+-------------+--------+-------+-------------+---------------------+
| characterID | typeID | level | skillpoints | currentTime |
+-------------+--------+-------+-------------+---------------------+
| 93192782 | 3359 | 3 | 135765 | 2013-09-30 16:58:35 |
+-------------+--------+-------+-------------+---------------------+
1 row in set (0.00 sec)
I believe my query is correctly formed and when executed it doesn't throw any errors or warnings:
mysql> INSERT INTO user_api_skills (characterID,typeID,level,skillpoints)
VALUES (93192782,3359,4,135765) ON DUPLICATE KEY UPDATE level=4,
skillpoints=135765,currentTime=NOW();
Query OK, 2 rows affected (0.22 sec)
I get 2 rows updated (as I would expect from an insert on dup update)
mysql> SELECT * FROM `user_api_skills` WHERE `characterID` =93192782 AND `typeID` =3359;
+-------------+--------+-------+-------------+---------------------+
| characterID | typeID | level | skillpoints | currentTime |
+-------------+--------+-------+-------------+---------------------+
| 93192782 | 3359 | 3 | 135765 | 2013-09-30 16:59:13 |
+-------------+--------+-------+-------------+---------------------+
1 row in set (0.00 sec)
mysql>
but the row itself only changes a single value (the currentTime). Can anybody explain why the other two fields are not updating?
Sorry, I have solved this myself. The level field is an ENUM and the query specified the new value as a number. Updating the query to the following resulted in the expected results.
mysql> INSERT INTO user_api_skills (characterID,typeID,level,skillpoints) VALUES
(93192782,3359,4,135765) ON DUPLICATE KEY UPDATE level='4', skillpoints=135765,
currentTime=NOW();
By providing a int to the update it updated to the one based number choice of the enum, so in this instance, the 4th choice is '3'.

Can't DROP "MUL" key/index in MySQL - column listed in SHOW

I'm using mysql-server-5.0.45-7.el5 on CentOs 5.
In my database, there is a table which, I don't know when, a MUL key was created (the database is shared, under control of a group), and now when I try to insert some values I get an error like shown above:
Duplicate entry '2-1-2004-09-11 13:13:41.526' for key 2:INSERT INTO ephemeris SET
EPH_TYPE_ID = 1, FILENAME = 'CBERS_2_CCD1_DRD_2004_09_11.13_13_23', ID = 0,
IS_NEW = 1, SATELLITE_ID = 2, TIME = '2004-09-11 13:13:41.526'
I got this error once, and I tried ALTER TABLE ephemeris DROP INDEX SATELLITE_ID;
It worked at first time, but now the same constraint appeared and it didn't worked at all.
The structure of table (resumed):
mysql> show columns from ephemeris;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| SATELLITE_ID | int(11) | NO | MUL | 0 | |
| EPH_TYPE_ID | int(11) | NO | | 0 | |
When I type the ALTER TABLE command, mysql returns as:
mysql> ALTER TABLE ephemeris DROP INDEX ephemeris.SATELLITE_ID ;
ERROR 1091 (42000): Can't DROP 'SATELLITE_ID'; check that column/key exists
Anybody have already gotten this error? Any help?
Rgds.
You need to first drop the foreign key constraint, then drop the index.
mysql> show create table a;
| CREATE TABLE `a` (
`id` varchar(20) DEFAULT NULL,
`sal` int(20) DEFAULT NULL,
`b_id` varchar(20) DEFAULT NULL,
KEY `b_id` (`b_id`),
CONSTRAINT `a_ibfk_1` FOREIGN KEY (`b_id`) REFERENCES `b` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
mysql> alter table a drop foreign key `a_ibfk_1`;
Query OK, 0 rows affected (0.10 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> alter table a drop index `b_id`;
Query OK, 0 rows affected (0.23 sec)
Records: 0 Duplicates: 0 Warnings: 0

Is it possible to disable automatic empty value insertion for fields without default value in MySQL?

Is there any configuration setting to stop MySQL from inserting an empty value for fields which don't have a default value and weren't specified in the insert statement? I'd much prefer it rejected an invalid insert statement.
Example - I have the following table in MySQL:
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`val1` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`val2` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
If you run this insert statement:
INSERT INTO test (val2) VALUES('a');
You get this response:
Query OK, 1 row affected, 1 warning (0.00 sec)
Response from show warnings:
+---------+------+-------------------------------------------+
| Level | Code | Message |
+---------+------+-------------------------------------------+
| Warning | 1364 | Field 'val1' doesn't have a default value |
+---------+------+-------------------------------------------+
1 row in set (0.00 sec)
Response from SELECT * FROM test:
+----+------+------+
| id | val1 | val2 |
+----+------+------+
| 1 | | asdf |
+----+------+------+
1 row in set (0.00 sec)
You can enable 'strict' mode, which'd cause MySQL to fail any inserts that don't provide values for default-less fields.