更新时间:2025-09-12 GMT+08:00
分享

集合类型

SET数据类型是一种常量字符串类型数据,该类型只在建表时可以创建,适用于存储确定集合的子集的场景,这些字符串常量必须是SET定义时指定的常量字符串集合的子集。

SET创建语法如下:

SET('val1','val2',...) [CHARACTER SET charset_name] [COLLATE collation_name]

SET类型底层存储是以bitmap的形式存储,每个集合成员对应于一个比特位。每个集合的子集有字符串形式和整型两种表示方法,在操作时含义相同,以SET('beijing', 'shanghai', 'nanjing', 'wuhan') 为例,集合的字符串值和整型值对应的关系如表1所示。

表1 集合子集字符串值和整型值对应关系

集合字符串值

集合对应二进制值

整型值

'beijing'

0001

1

'shanghai'

0010

2

'nanjing'

0100

4

'wuhan'

1000

8

'beijing,nanjing'

0101

5

M-Compatibility支持的SET类型如表2所示。

表2 集合类型

名称

描述

存储空间

SET

集合类型,用于存储确定集合的子集的场景。

  • 输入格式:
    • 字符串,子集合之一,成员间以','分隔。
    • 整型,子集合对应的整型值。
  • 输出格式:
    • 子集合的字符串,成员间以','分隔。
  • 取值范围:
    • 最多支持创建64个成员。
    • 创建时给出集合的子集之一。

4字节~8字节

  • SET数据类型的输入合法校验受sql_mode影响。宽松模式下,SET类型列输入不合法的值,会插入0值,即空串,严格模式下,插入不合法的值,会报错。
  • SET数据类型创建时的每个成员值需要唯一。出现重复成员值,严格模式下报错,宽松模式下支持创建,但默认使用重复值中第一个出现的。
  • SET数据类型支持字符集与字符序特性,且校验成员值是否重复与SET列上的字符序特性有关。
  • SET数据类型不支持作为分区键。
  • SET数据类型上的索引仅支持通过整型查找,使用字符串值无法走索引。
  • 当前SET类型与其它类型比较不支持走索引扫描,需要在SET类型的列上,根据需要查询的数据类型,创建函数表达式索引来支持走索引扫描。

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
-- 创建表和SET数据类型
m_db=# CREATE TABLE test_set(c1 SET('abc','efg','中文','汉字'));
CREATE TABLE

-- 查看表结构
m_db=# SELECT pg_get_tabledef('test_set');
                                     pg_get_tabledef                                      
------------------------------------------------------------------------------------------
 SET search_path = public;                                                               +
 CREATE TABLE test_set (                                                                 +
     c1 SET('abc', 'efg', '中文', '汉字') CHARACTER SET `UTF8` COLLATE utf8mb4_general_ci+
 )                                                                                       +
 CHARACTER SET = "UTF8" COLLATE = "utf8mb4_general_ci"                                   +
 WITH (orientation=row, compression=no, storage_type=USTORE, segment=off);
(1 row)

-- 插入字符串数据
m_db=# INSERT INTO test_set VALUES('abc,efg'),('efg,汉字,中文'), ('abc');
INSERT 0 3

-- 插入整型数据
m_db=# INSERT INTO test_set VALUES(5),(12);
INSERT 0 2

-- 查询数据
m_db=# SELECT * FROM test_set;
      c1       
---------------
 abc,efg
 efg,中文,汉字
 abc
 abc,中文
 中文,汉字
(5 rows)

-- 字符串形式查询数据
m_db=# SELECT * FROM test_set WHERE c1 = 'abc,efg';
   c1    
---------
 abc,efg
(1 row)

-- 整型值形式查询数据
m_db=# SELECT * FROM test_set WHERE c1 = 12;
    c1     
-----------
 中文,汉字
(1 row)

-- 删除表
m_db=# DROP TABLE test_set;
DROP TABLE

-- 创建表和SET数据类型
m_db=# CREATE TABLE t1(id int, c1 set('a','bb','ccc'));
CREATE TABLE

-- 直接创建SET类型的索引无法支持走索引扫描
m_db=# CREATE INDEX idx_1 ON t1(c1);
CREATE INDEX

m_db=# EXPLAIN SELECT c1 FROM t1 WHERE c1 = 'a';
                     QUERY PLAN                      
-----------------------------------------------------
 Seq Scan on t1  (cost=0.00..59.00 rows=15 width=32)
   Filter: (cast_to_cstring(c1) = 'a'::text)
(2 rows)

-- 字符串查询,创建cast_to_cstring 函数索引,支持索引扫描
m_db=# CREATE INDEX id_t1 ON t1((cast_to_cstring(c1)));
CREATE INDEX

m_db=# EXPLAIN SELECT c1 FROM t1 WHERE c1 = 'a';
                             QUERY PLAN                             
--------------------------------------------------------------------
 Bitmap Heap Scan on t1  (cost=4.30..13.78 rows=6 width=32)
   Recheck Cond: (cast_to_cstring(c1) = 'a'::text)
   ->  Bitmap Index Scan on id_t1  (cost=0.00..4.30 rows=6 width=0)
         Index Cond: (cast_to_cstring(c1) = 'a'::text)
(4 rows)

-- 整型查询,创建cast_to_int8函数索引,支持索引扫描
m_db=# CREATE INDEX id_t2 ON t1((cast_to_int8(c1)));
CREATE INDEX

m_db=#  EXPLAIN SELECT c1 FROM t1 WHERE c1 = 5;
                             QUERY PLAN                             
--------------------------------------------------------------------
 Bitmap Heap Scan on t1  (cost=4.30..13.78 rows=6 width=32)
   Recheck Cond: (cast_to_int8(c1) = 5)
   ->  Bitmap Index Scan on id_t2  (cost=0.00..4.30 rows=6 width=0)
         Index Cond: (cast_to_int8(c1) = 5)
(4 rows)

相关文档