Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 26.8Mb
PDF (A4) - 26.9Mb
HTML Download (TGZ) - 7.1Mb
HTML Download (Zip) - 7.2Mb


11.4.5 SET 型

SET は、ゼロ以上の値を取ることができる文字列オブジェクトであり、それぞれの値は、テーブルの作成時に指定された許可される値のリストから選択する必要があります。SET カラム値が複数のセットメンバーで構成される場合は、各メンバーはカンマ (,) で区切って指定されます。このため、SET メンバーの値自体にはカンマを含めないでください。

たとえば、SET('one', 'two') NOT NULL として指定したカラムは、次に示す値のいずれかを取ります。

''
'one'
'two'
'one,two'

SET カラムには最大 64 個の個別のメンバーを含めることができます。テーブルには、グループと見なされる ENUM および SET カラムの中の一意の要素リスト定義を、255 個以下を含めることができます。この制限の詳細は、セクションD.10.5「.frm ファイル構造により課せられる制限」を参照してください。

定義の中に重複した値が含まれていると、警告 (厳密な SQL モードが有効になっている場合はエラー) が発生します。

テーブルが作成されるときに、テーブル定義内の SET メンバー値から末尾のスペースが自動的に削除されます。

SET カラムに格納された値は、取得されるときに、カラム定義で使用されていた大文字/小文字で表示されます。SET カラムには、文字セットと照合順序を割り当てることができます。バイナリ照合順序、または大文字と小文字を区別する照合順序の場合、カラムに値を割り当てるときに、大文字/小文字が考慮されます。

MySQL は、最初のセットメンバーに対応する格納値の低位ビットを使用して SET 値を数値で格納します。SET 値を数値コンテキストで取得した場合、その取得された値には、カラム値を構成するセットメンバーに対応するビットセットが含まれます。たとえば、次のように SET カラムから数値を取得できます。

mysql> SELECT set_col+0 FROM tbl_name;

メンバーが SET カラムに格納されると、その数字のバイナリ表現に設定されているビットからカラム値のセットメンバーが特定されます。カラムが SET('a','b','c','d') として指定されている場合、セットメンバーは次の 10 進値と 2 進値を持ちます。

SET メンバー 10 進値 2 進値
'a' 1 0001
'b' 2 0010
'c' 4 0100
'd' 8 1000

このカラムに 9 の値を割り当てた場合、2 進数では 1001 となるため、SET 値の最初と 4 番目のメンバーである 'a''d' が選択され、結果として得られる値は 'a,d' になります。

1 つ以上の SET 要素を含む値には、値を挿入するときに要素がどの順序でリストされているかは関係ありません。また、所定の要素が値の中で何回リストされているかも関係ありません。あとから値を取得するときに、値内のそれぞれの要素は、テーブル作成時に指定された順序に従って、一度表示されます。たとえば、カラムが SET('a','b','c','d') と指定されているとします。

mysql> CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));

'a,d''d,a''a,d,d''a,d,a'、および 'd,a,d' の値を挿入した場合、

mysql> INSERT INTO myset (col) VALUES 
-> ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

これらの値はすべて、取得されるときに 'a,d' と表示されます。

mysql> SELECT col FROM myset;
+------+
| col  |
+------+
| a,d  |
| a,d  |
| a,d  |
| a,d  |
| a,d  |
+------+
5 rows in set (0.04 sec)

サポートされていない値に SET カラムを設定すると、その値は無視され警告が表示されます。

mysql> INSERT INTO myset (col) VALUES ('a,d,d,s');
Query OK, 1 row affected, 1 warning (0.03 sec)

mysql> SHOW WARNINGS;
+---------+------+------------------------------------------+
| Level   | Code | Message                                  |
+---------+------+------------------------------------------+
| Warning | 1265 | Data truncated for column 'col' at row 1 |
+---------+------+------------------------------------------+
1 row in set (0.04 sec)

mysql> SELECT col FROM myset;
+------+
| col  |
+------+
| a,d  |
| a,d  |
| a,d  |
| a,d  |
| a,d  |
| a,d  |
+------+
6 rows in set (0.01 sec)

厳密な SQL モードが有効な場合、無効な SET 値を挿入しようとするとエラーが発生します。

SET 値は数値でソートされます。NULL 値は非 NULL SET 値の前にソートされます。

数値引数を取る SUM()AVG() などの関数は、必要に応じて引数を数値にキャストします。SET 値の場合は、キャスト操作によって数値が使用されます。

通常は、FIND_IN_SET() 関数か LIKE 演算子を使用して SET 値を検索します。

mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;
mysql> SELECT * FROM tbl_name WHERE set_col LIKE '%value%';

最初のステートメントは set_colvalue セットメンバーを含む行を見つけます。2 番目も似ていますが、同じではありません。ほかのセットメンバーの部分文字列としてであっても、set_colvalue を含む行を見つけます。

次のステートメントも使用できます。

mysql> SELECT * FROM tbl_name WHERE set_col & 1;
mysql> SELECT * FROM tbl_name WHERE set_col = 'val1,val2';

これらのうち最初のステートメントが最初のセットメンバーを含む値を探します。2 番目のステートメントは正確に一致する値を探します。2 番目の型は慎重に比較してください。セット値を 'val1,val2' と比較すると、値を 'val2,val1' と比較した場合とは異なる結果が返されます。カラム定義にリストされている順序どおりに値を指定する必要があります。

SET カラムの指定可能な値をすべて特定するには、SHOW COLUMNS FROM tbl_name LIKE set_col を使用して、出力の Type カラム内の SET 定義を構文解析します。

C API では、SET 値は文字列として返されます。結果セットのメタデータを使用してこれらをほかの文字列から区別する方法については、セクション23.8.5「C API データ構造」を参照してください。


User Comments
User comments in this section are, as the name implies, provided by MySQL users. The MySQL documentation team is not responsible for, nor do they endorse, any of the information provided here.
  Posted by John Kozura on April 12, 2011
Note that MySQL, at least 5.1+, seems to deal just fine with extra commas, so setting/deleting individual bits by name can be done very simply without creating a "proper" list. So even something like SET flags=',,,foo,,bar,,' works fine, if you don't care about a truncated data warning.

add bits:
UPDATE tbl SET flags=CONCAT_WS(',', flags, 'flagtoadd');

delete bits:
UPDATE tbl SET flags=REPLACE(flags, 'flagtoremove', '')

..or if you have a bit that's name is a subname of another bit like "foo" and "foot", slightly more complicated:
UPDATE tbl SET flags=REPLACE(CONCAT(',', flags, ','), ',foo,', ',')

If the warnings do cause issues from you, then the solutions posted above work:
add:
UPDATE tbl SET flags=TRIM(',' FROM CONCAT(flags, ',', 'flagtoadd'))

delete:
UPDATE tbl SET flags=TRIM(',' FROM REPLACE(CONCAT(',', flags, ','), ',flagtoremove,', ','))
  Posted by Chris Wagner on August 2, 2011
Code that elucidates Boris's example on using bit logic to remove a set value. Execute it on any table with a SET() column but change the column name and value as appropriate.

SELECT flag1set,
flag1set + 0 as decimal,
1 << (FIND_IN_SET('val', flag1set) - 1) as killbits,
~(1 << (FIND_IN_SET('val', flag1set) - 1)) as keepbits,
flag1set & ~(1 << (FIND_IN_SET('val', flag1set) - 1)) as newdecimal
FROM table;
  Posted by Guido Gambardella on November 9, 2011
The nice article quoted above has been moved to http://www.vbmysql.com/articles/mysql/the-mysql-set-datatype
Sign Up Login You must be logged in to post a comment.