下記のようなテキストを保存するためのテーブルがあった時
MySQL
1CREATE TABLE text ( 2 text_id SERIAL PRIMARY KEY COMMENT 'テキストID', 3 text VARCHAR(65535) NOT NULL COMMENT 'テキスト' 4) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='テキストデータテーブル';
下記のようにすることで
同じテキストが存在すればinsertしないが
まだ保存されていないテキストの場合はinsertすることができました。
MySQL
1 INSERT into text (text) 2 SELECT 'ここに挿入したいテキスト' 3 WHERE ( 4 SELECT COUNT(text) = 0 5 FROM text 6 WHERE text = 'ここに挿入したいテキスト' 7 )
しかしこれだとSQL文に同じテキストを貼り付けることになってしまうので、少し気持ち悪いなあと思っています。
ユーザ定義変数を利用せずに
重複している'ここに挿入したいテキスト'
を1つだけにしてなんとか同じようにするにはどうすれば良いですか?
よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答4件
0
ベストアンサー
MySQL独自構文ですが、INSERT IGNOREで重複を除外する事が出来ます。下記の場合、既にtextに'a'があるとINSERTされないです。
(例)
INSERT IGNORE INTO text(text_id ,text) VALUES(1,'a');
但し、上記で言うと、textカラムにUNIQUEキー制約が必要ですね。
投稿2016/12/28 00:14
総合スコア3027
0
※これは回答ではありません。
すでに解決済みではありますが、いくつか注意点がありますので、以下に記載させていただきます。
'text'カラムのサイズによっては、INSERT IGNORE による方法では実現できません。
なぜなら、MySQL には作成できるインデックスの長さに制限があるからです。
https://dev.mysql.com/doc/refman/5.6/ja/innodb-restrictions.html
InnoDB の内部的な最大キー長は 3500 バイトですが、MySQL 自体では 3072 バイトに制限されています。
UTF-8 の場合、1文字のサイズは2〜3バイト(だったと思います)なので、text
カラムに格納したい文字数が約1000文字を超える場合、
カラム値全体をカバーするインデックスが作成できないことになります。
sql
1mysql> CREATE TABLE test (text VARCHAR(2048), UNIQUE INDEX (text)); 2ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
また、MySQLの文字列比較には
- デフォルトの照合順序では、大文字/小文字を区別しない
- 末尾の空白を無視する
という制約があります。
sql
1mysql> SHOW COLLATION WHERE `Charset` = 'utf8'; 2+--------------------------+---------+-----+---------+----------+---------+ 3| Collation | Charset | Id | Default | Compiled | Sortlen | 4+--------------------------+---------+-----+---------+----------+---------+ 5| utf8_general_ci | utf8 | 33 | Yes | Yes | 1 | 6| utf8_bin | utf8 | 83 | | Yes | 1 | 7| utf8_unicode_ci | utf8 | 192 | | Yes | 8 | 8(以下略)
※ '_ci'は Case Insensitive の略
https://dev.mysql.com/doc/refman/5.6/ja/char.html
MySQL のすべての照合順序は、PADSPACE 型のものです。これは、MySQL 内のすべての CHAR、VARCHAR、および TEXT 値が、末尾のスペースに関係なく比較されることを意味します。
そのため、
- 大文字/小文字を区別したい場合、
text
カラムの照合順序を utf8_bin に - 末尾の空白も無視させたくない場合、照合順序を binary に
変更する必要があります。
(もっとも、照合順序を変更すると、他の部分に影響が出るかもしれませんが、、)
デフォルトの比較順序 (utf8_general_ci) の場合
sql
1mysql> CREATE TABLE test (text VARCHAR(1024), UNIQUE INDEX (text)); 2Query OK, 0 rows affected (0.04 sec) 3 4mysql> INSERT IGNORE INTO test VALUES ('hoge'), ('HOGE'), ('hoge '); 5Query OK, 1 row affected, 2 warnings (0.01 sec) 6Records: 3 Duplicates: 2 Warnings: 2 7 8mysql> SELECT * FROM test; 9+------+ 10| text | 11+------+ 12| hoge | 13+------+ 141 row in set (0.00 sec)
utf8_bin の場合
sql
1mysql> CREATE TABLE test (text VARCHAR(1024) COLLATE 'utf8_bin', UNIQUE INDEX (text)); 2Query OK, 0 rows affected (0.04 sec) 3 4mysql> INSERT IGNORE INTO test VALUES ('hoge'), ('HOGE'), ('hoge '); 5Query OK, 2 rows affected, 1 warning (0.00 sec) 6Records: 3 Duplicates: 1 Warnings: 1 7 8mysql> SELECT * FROM test; 9+------+ 10| text | 11+------+ 12| HOGE | 13| hoge | 14+------+ 152 rows in set (0.00 sec)
binary の場合
sql
1mysql> CREATE TABLE test (text VARCHAR(1024) COLLATE 'binary', UNIQUE INDEX (text)); 2Query OK, 0 rows affected (0.04 sec) 3 4mysql> INSERT IGNORE INTO test VALUES ('hoge'), ('HOGE'), ('hoge '); 5Query OK, 3 rows affected (0.00 sec) 6Records: 3 Duplicates: 0 Warnings: 0 7 8mysql> SELECT * FROM test; 9+-----------+ 10| text | 11+-----------+ 12| HOGE | 13| hoge | 14| hoge | 15+-----------+ 163 rows in set (0.00 sec)
※ SQL の実行結果は、全て MySQL5.7 によるもの
投稿2016/12/28 06:25
総合スコア4791
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
SQLServerならMERGE構文という、同じ内容レコードがあればUPDATE(アップデートしなくてもいい)、無ければINSERTを行える構文があります。
MySQLでもINSERT … ON DUPLICATE KEY UPDATEがそれに該当するようです。
投稿2016/12/28 00:09
総合スコア486
0
変数を使ってよろしければ
sql
1 2 SET @foo:="ここに挿入したいテキスト"; 3 4 INSERT into text (text) 5 SELECT @foo 6 WHERE ( 7 SELECT COUNT(text) = 0 8 FROM text 9 WHERE text = @foo 10 )
当環境では上記のSQLがうまく動かないので????
INSERT into text (text)
SELECT * FROM (SELECT @foo) X
WHERE (
SELECT COUNT(text) = 0
FROM text
WHERE text = @foo
)
余計な事ですが、text VARCHAR(65535)が大きいのでmd5を設けて条件文にも使われた方が、今後大量になる場合に良いと考えます。
投稿2016/12/27 23:07
編集2016/12/27 23:47総合スコア4070
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/12/28 02:10