MySQL で SET 型の UPDATE
以下のようなテーブルのとき
CREATE TABLE foo
(
aset set('aaa', 'bbb', 'ccc')
); - 空文字列を SET のメンバーとして許していない
- null 可
値を追加する
UPDATE foo SET `aset` = CONCAT_WS(',', NULLIF(aset, ''), #{member}); aset が空文字列(emptyset)のとき、これをそのままカンマで CONCAT_WS すると、",ccc" とかになり、空文字列のメンバーは許容していないため data truncated でエラーになってしまう。
CONCAT_WS は引数が null のときはそれを飛ばして連結するので、それを利用する。
ref. https://stackoverflow.com/questions/14642658/the-best-way-to-remove-value-from-set-field
値を削除する
UPDATE foo SET `aset` = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', aset, ','), CONCAT(',', #{member}, ','), ',')) もっとややこしい。というのも ",aaa" も "aaa,,ccc" も "aaa," も不正なので、こういう値にならないようにしないといけない。
備考
SET は実際は 64bit の数値なので、SET のメンバー名(文字列)を2の乗数の数値に変換する方法があれば、単にビット演算ですむ。けど、MySQL 上にはこの方法 (メンバー名を SET の数値に直接変換する) がない(と思う)。アプリケーション側で数値と文字列のマッピングを持てば SQL は簡単になるが DDL と常に整合性をとる必要があってややこしく、それなら SET じゃなく BIGINT UNSIGNED で持てばいいことになる。
なんかいい方法あったら教えてください (SET 使うな以外で)
関連エントリー
- SQLite で LOG や SQRT を使うには SQLite にはかなり基本的な算術演算関数しかない。追加で何かしらやるためには拡張 (Run-Time Loadable Extensio...
- Ruby Sequel で生 SQL をメインに使う Sequel はドキュメント見ると SQL そのまま書くやりかたもとクエリビルダを介すやりかたも許されていると感じるので (別に他のライブラ...
- TF-IDFとコサイン類似度による類似エントリー機能の実装 TF-IDFによる類似エントリー機能の実装をしてみました。ほぼSQLiteですませるような構成です。 やっていることの概要 エントリーのHT...
- Ubuntu 16.4 LTS クリーンインストールして引越 カスタムOSインストールガイド - Ubuntu 16.04 – さくらのサポート情報 を見ながらインストールまでやる。 旧サーバと同じホス...
- Lightroom のカタログを SQLite で読んで統計を出したりする .lrcat っていったい何なのか カタログファイルの実体である lrcat は SQLite の DB ファイルそのもの。sqlite3 ...