koron / nvgd

Filterable (grep, head and tail) HTTP file server

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

make excel upload transactional

koron opened this issue · comments

Error 1062: Duplicate entry '200' for key 'PRIMARY'

for MySQL

verified:

https://dev.mysql.com/doc/index-other.html の world database 内の countrylanguage で確認。
2行目のcountrycode(3の制限あり)を長さを4に書き換えて、1行目のpercentageを5.3から50.3に書き換えた。
この状態でrestoreしたら1行目だけが反映された。

restoreでは弾けるが、updateではスルーして入ってしまう。

updateはupsertとして作ったので、duplicate keyがあっても入ってしまうのは、想定される動作。

よって同じデータをrestoreを使ってアップロードすると

failed to open db-restore://mysql/countrylanguage; Error 1062: Duplicate entry 'ABW-Spanish' for key 'PRIMARY'

こんな感じのエラーになる。

一方でMySQLはconstraintの扱いがガバガバらしく
CountryCode | char(3) のところに 4文字の文字列を insert しても3文字に切り詰めて入れている。
そのほか enum('T', 'F') のところに別の文字列を入れることもできてしまった。

mysql> desc countrylanguage;
+-------------+---------------+------+-----+---------+-------+
| Field       | Type          | Null | Key | Default | Extra |
+-------------+---------------+------+-----+---------+-------+
| CountryCode | char(3)       | NO   | PRI |         |       |
| Language    | char(30)      | NO   | PRI |         |       |
| IsOfficial  | enum('T','F') | NO   |     | F       |       |
| Percentage  | decimal(4,1)  | NO   |     | 0.0     |       |
+-------------+---------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

mysql> insert into countrylanguage values('ABWZ', 'Japanese', 'F', 0.1);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select * from countrylanguage where countrycode = 'ABW';
+-------------+------------+------------+------------+
| CountryCode | Language   | IsOfficial | Percentage |
+-------------+------------+------------+------------+
| ABW         | Dutch      | T          |        5.3 |
| ABW         | English    | F          |        9.5 |
| ABW         | Japanese   | F          |        0.1 |
| ABW         | Papiamento | F          |       76.7 |
| ABW         | Spanish    | F          |        7.4 |
+-------------+------------+------------+------------+
5 rows in set (0.00 sec)

Char(3)に ABWZ の4文字を入れたら、エラーにならず3文字に切り詰められて入る例

decimal(4, 1) にも文字列が入ってしまう。

mysql> insert into countrylanguage values('ABWZ', 'Japanese', 'F', 'foobar');
Query OK, 1 row affected, 2 warnings (0.00 sec)

mysql> select * from countrylanguage where countrycode = 'ABW';
+-------------+------------+------------+------------+
| CountryCode | Language   | IsOfficial | Percentage |
+-------------+------------+------------+------------+
| ABW         | Dutch      | T          |        5.3 |
| ABW         | English    | F          |        9.5 |
| ABW         | Japanese   | F          |        0.0 |
| ABW         | Papiamento | F          |       76.7 |
| ABW         | Spanish    | F          |        7.4 |
+-------------+------------+------------+------------+
5 rows in set (0.01 sec)

まとめ:

  • 操作タイプごとのはなし
    • update: upsert相当なのでduplicateがあっても入って行くのは当然、仕様通り
    • restore: duplicateがあればそこでエラーになって反映されない
  • 型や制約関連
    • 長さ制限や自動型変換など: mysqlが勝手にやって入れてしまう。nvgdではどうにもならない/何か追加で努力が要る
    • 外部キーによる制約などは普通にかかっている

works for me