47098


mysqlでレコードを挿入する際に、挿入したいデータが既にレコードがある場合は挿入せず、ない場合にのみ挿入したいです。  
下記のsqlをコマンドラインから実行しました。

[code]

    insert into fileinfo (filename, url) values ("a", "aa") where not exists (select * from fileinfo where filename = "a");
    
[/code]

下記のエラーがでました。

[code]

    You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'where not exists (select * from fileinfo where filename = "a")' at line 1
    
[/code]

どこが間違っているのかわかりません

CentOS7  
mysql --version  
mysql Ver 15.1 Distrib 10.1.34-MariaDB, for Linux (x86_64) using readline 5.1  
です。

DB構造は下記の通りです。

[code]

    +----------+--------------+------+-----+---------+----------------+
    | Field    | Type         | Null | Key | Default | Extra          |
    +----------+--------------+------+-----+---------+----------------+
    | id       | int(11)      | NO   | PRI | NULL    | auto_increment |
    | filename | varchar(255) | YES  |     | NULL    |                |
    | url      | varchar(255) | YES  |     | NULL    |                |
    +----------+--------------+------+-----+---------+----------------+
    
[/code]

よろしくお願いいたします。


CC BY-SA 4.0
2018-07-30T06:07:25.187
47097
2018-08-06T01:09:57.900
2018-08-06T01:09:57.900
24823
28019
question
mysql mariadb
mysqlでレコードがない場合のみ挿入したい


以下のリファレンスよりmariadbでは`insert into values`に直接`where`句は記述できません。  
[INSERT - MariaDB Knowledge Base](https://mariadb.com/kb/en/library/insert/)

次の参考URLより  
[mysqlでデータが存在するときinsertしないDML -
まがりの日記](http://oomatomo.hatenablog.com/entry/33737434)

[code]

    insert into fileinfo (filename, url) 
    select * from (select'a', 'aa') as tmp
    where not exists  (select * from fileinfo where filename = 'a') limit 1
    
[/code]

とすれば目的の通り、動作するようです。

`ignore`を使った方法も参考URLに記述されていますが、こちらはDBが出力する重複エラーを無視するという方法なので、あまりいい方法ではありません。

書いているうちにコメントで回答がありますね。  
せっかく書いたので投稿しておきます。


CC BY-SA 4.0
2018-07-30T07:19:00.600
47098
2018-07-30T08:14:27.900
2018-07-30T08:14:27.900
3060
17014
47097
answer


> mysqlでレコードを挿入する際に、挿入したいデータが既にレコードがある場合は挿入せず、ない場合にのみ挿入したいです。

もし、filenameを NOT NULLにできる場合、UNIQUE制約を検討したほうが良いと思います。

[code]

    mysql> CREATE TABLE fileinfo (
        ->   id int(20) NOT NULL AUTO_INCREMENT,
        ->   filename varchar(255) NOT NULL,
        ->   url varchar(255) DEFAULT NULL,
        ->   PRIMARY KEY (id),
        ->   UNIQUE (filename)
        -> );
    Query OK, 0 rows affected (0.07 sec)
    
    mysql> insert into fileinfo (filename, url) values ("a", "aa");
    Query OK, 1 row affected (0.01 sec)
    
    mysql> insert into fileinfo (filename, url) values ("a", "aa");
    ERROR 1062 (23000): Duplicate entry 'a' for key 'filename'
    
[/code]

他の解答でもあるように、IGNOREもできますし、ON DUPLICATE KEY UPDATEというオプションも使えるようになります。

[code]

    mysql> select * from fileinfo;
    +----+----------+------+
    | id | filename | url  |
    +----+----------+------+
    |  1 | a        | a    |
    +----+----------+------+
    1 row in set (0.00 sec)
    
    mysql> insert into fileinfo (filename, url) values ("a", "url") ON DUPLICATE KEY UPDATE url = "new url";
    Query OK, 2 rows affected (0.01 sec)
    
    mysql> select * from fileinfo;
    +----+----------+---------+
    | id | filename | url     |
    +----+----------+---------+
    |  1 | a        | new url |
    +----+----------+---------+
    1 row in set (0.00 sec)
    
[/code]

INDEXもつくため、索引のスピードも早くなります。

[この解答](https://stackoverflow.com/a/3164595/8299670)を参考にしました。  
MySQLの[insert-on-
duplicateのドキュメント](https://dev.mysql.com/doc/refman/8.0/en/insert-on-
duplicate.html)


CC BY-SA 4.0
2018-07-31T04:53:09.847
47118
2018-08-01T03:33:22.613
2018-08-01T03:33:22.613
24823
24823
47097
answer