DEFAULT 或 MAXVALUE 分区或二级分区将捕获不符合为表定义的其他分区规则的所有行。

定义 DEFAULT 分区

DEFAULT 分区将捕获不属于 LIST 分区(或二级分区)表中的任何其他分区的所有行。如果未包含 DEFAULT 规则,则与分区约束中的某一值不匹配的任何行都将导致错误。每个 LIST 分区或二级分区都可以有其自己的 DEFAULT 规则。DEFAULT 分区将捕获不属于 LIST 分区(或二级分区)表中的任何其他分区的所有行。如果未包含 DEFAULT 规则,则与分区约束中的某一值不匹配的任何行都将导致错误。每个 LIST 分区或二级分区都可以有其自己的 DEFAULT 规则。

DEFAULT 规则的语法如下:

PARTITION [partition_name] VALUES (DEFAULT)

其中 partition_name 指定了将存储与为其他分区指定的规则不匹配的所有行的分区或二级分区的名称。

上一示例创建了一个列表分区表,在该表中服务器根据 country 列的值确定哪一分区将存储数据。如果您尝试添加一行,其 country 列的值包含规则中未列出的值,则 POLARDB for Oracle 会报告错误:

acctg=# INSERT INTO sales VALUES
acctg-#  (40, '3000x', 'IRELAND', '01-Mar-2012', '45000');
ERROR:  no partition of relation "sales_2012" found for row
DETAIL:  Partition key of the failing row contains (country) = (IRELAND).

以下示例创建同一表,但新增了 DEFAULT 分区。服务器将与 europe、asia 或 americas 分区的分区规则中指定的值不匹配的所有行存储在 others 分区中:

CREATE TABLE sales
(
  dept_no     number,
  part_no     varchar2,
  country     varchar2(20),
  date        date,
  amount      number
)
PARTITION BY LIST(country)
(
  PARTITION europe VALUES('FRANCE', 'ITALY'),
  PARTITION asia VALUES('INDIA', 'PAKISTAN'),
  PARTITION americas VALUES('US', 'CANADA'),
  PARTITION others VALUES (DEFAULT)
);

要测试 DEFAULT 分区,请添加一行,其 country 列中的值与分区约束中指定的某一国家不匹配:

INSERT INTO sales VALUES
  (40, '3000x', 'IRELAND', '01-Mar-2012', '45000');

通过查询 sales 表的内容,确认先前被拒绝的行现在存储在 sales_others 分区中:

acctg=# SELECT tableoid::regclass, * FROM sales;
    tableoid    | dept_no | part_no | country  |        date        | amount
----------------+---------+---------+----------+--------------------+--------
 sales_americas |      40 | 9519b   | US       | 12-APR-12 00:00:00 | 145000
 sales_americas |      40 | 4577b   | US       | 11-NOV-12 00:00:00 |  25000
 sales_americas |      30 | 7588b   | CANADA   | 14-DEC-12 00:00:00 |  50000
 sales_americas |      30 | 9519b   | CANADA   | 01-FEB-12 00:00:00 |  75000
 sales_americas |      30 | 4519b   | CANADA   | 08-APR-12 00:00:00 | 120000
 sales_americas |      40 | 3788a   | US       | 12-MAY-12 00:00:00 |   4950
 sales_americas |      40 | 4788a   | US       | 23-SEP-12 00:00:00 |   4950
 sales_americas |      40 | 4788b   | US       | 09-OCT-12 00:00:00 |  15000
 sales_europe   |      10 | 4519b   | FRANCE   | 17-JAN-12 00:00:00 |  45000
 sales_europe   |      10 | 9519b   | ITALY    | 07-JUL-12 00:00:00 |  15000
 sales_europe   |      10 | 9519a   | FRANCE   | 18-AUG-12 00:00:00 | 650000
 sales_europe   |      10 | 9519b   | FRANCE   | 18-AUG-12 00:00:00 | 650000
 sales_asia     |      20 | 3788a   | INDIA    | 01-MAR-12 00:00:00 |  75000
 sales_asia     |      20 | 3788a   | PAKISTAN | 04-JUN-12 00:00:00 |  37500
 sales_asia     |      20 | 3788b   | INDIA    | 21-SEP-12 00:00:00 |   5090
 sales_asia     |      20 | 4519a   | INDIA    | 18-OCT-12 00:00:00 | 650000
 sales_asia     |      20 | 4519b   | INDIA    | 02-DEC-12 00:00:00 |   5090
 sales_others   |      40 | 3000x   | IRELAND  | 01-MAR-12 00:00:00 |  45000
(18 rows)

POLARDB for Oracle 提供以下一些方法来重新分配 DEFAULT 分区或二级分区的内容:

  • 您可以使用 ALTER TABLE… ADD PARTITION 命令向具有 DEFAULT 规则的表中添加分区,只要表中现有行的值与要添加分区的值之间不存在冲突。您也可以使用 ALTER TABLE… SPLIT PARTITION 命令拆分现有分区。在此要点列表后面显示了一些示例。
  • 您可以使用 ALTER TABLE… ADD SUBPARTITION 命令向具有 DEFAULT 规则的表添加二级分区,只要表中现有行的值与要添加二级分区的值之间不存在冲突。您也可以使用 ALTER TABLE… SPLIT SUBPARTITION 命令拆分现有二级分区。

向具有 DEFAULT 分区的表添加分区

通过使用 CREATE TABLE sales 命令创建的表(如本节开头所示),以下示例显示如何使用 ALTER TABLE... ADD PARTITION 命令(假设表中现有行的值与要添加分区的值不存在冲突):

edb=# ALTER TABLE sales ADD PARTITION africa values ('SOUTH AFRICA', 'KENYA');
ALTER TABLE

但是,当以下行插入到表时,如果存在冲突的值,则以下示例会显示错误:

edb=# INSERT INTO sales (dept_no, country) VALUES (1,'FRANCE'),(2,'INDIA'),(3,'US'),(4,'SOUTH AFRICA'),(5,'NEPAL');
INSERT 0 5

行 (4,'SOUTH AFRICA') 与 VALUES 列表(位于 ALTER TABLE... ADD PARTITION 语句中)冲突,因而导致错误。

edb=# ALTER TABLE sales ADD PARTITION africa values ('SOUTH AFRICA', 'KENYA');
ERROR:  updated partition constraint for default partition "sales_others" would be violated by some row

拆分 DEFAULT 分区

以下示例拆分 DEFAULT 分区,将该分区的内容重新分配到两个新分区中。表是使用 CREATE TABLE sales 命令创建的,如本节开头中所示。

以下示例将行插入表中,该表将行包含到 DEFAULT 分区中:

INSERT INTO sales VALUES
  (10, '4519b', 'FRANCE', '17-Jan-2012', '45000'),
  (10, '9519b', 'ITALY', '07-Jul-2012', '15000'),
  (20, '3788a', 'INDIA', '01-Mar-2012', '75000'),
  (20, '3788a', 'PAKISTAN', '04-Jun-2012', '37500'),
  (30, '9519b', 'US', '12-Apr-2012', '145000'),
  (30, '7588b', 'CANADA', '14-Dec-2012', '50000'),
  (40, '4519b', 'SOUTH AFRICA', '08-Apr-2012', '120000'),
  (40, '4519b', 'KENYA', '08-Apr-2012', '120000'),
  (50, '3788a', 'CHINA', '12-May-2012', '4950');

分区包括 DEFAULT others 分区:

edb=# SELECT partition_name, high_value FROM all_tab_partitions;
 partition_name |             high_value
----------------+-------------------------------------
 EUROPE         | FOR VALUES IN ('FRANCE', 'ITALY')
 ASIA           | FOR VALUES IN ('INDIA', 'PAKISTAN')
 AMERICAS       | FOR VALUES IN ('US', 'CANADA')
 OTHERS         | DEFAULT
(4 rows)

以下示例显示在分区之间分配的行:

edb=# SELECT tableoid::regclass, * FROM sales;
   tableoid   | dept_no | part_no |   country    |        date        | amount
--------------+--------+---------+--------------+--------------------+--------
sales_americas|     30 | 9519b   | US           | 12-APR-12 00:00:00 | 145000
sales_americas|     30 | 7588b   | CANADA       | 14-DEC-12 00:00:00 |  50000
sales_europe  |     10 | 4519b   | FRANCE       | 17-JAN-12 00:00:00 |  45000
sales_europe  |     10 | 9519b   | ITALY        | 07-JUL-12 00:00:00 |  15000
sales_asia    |     20 | 3788a   | INDIA        | 01-MAR-12 00:00:00 |  75000
sales_asia    |     20 | 3788a   | PAKISTAN     | 04-JUN-12 00:00:00 |  37500
sales_others  |     40 | 4519b   | SOUTH AFRICA | 08-APR-12 00:00:00 | 120000
sales_others  |     40 | 4519b   | KENYA        | 08-APR-12 00:00:00 | 120000
sales_others  |     50 | 3788a   | CHINA        | 12-MAY-12 00:00:00 |   4950
(9 rows)

以下命令将 DEFAULT others 分区拆分为名为 africa 和 others 的两个分区:

ALTER TABLE sales SPLIT PARTITION others VALUES
  ('SOUTH AFRICA', 'KENYA')
  INTO (PARTITION africa, PARTITION others);

现在,分区包括 africa 分区以及 DEFAULT others 分区:

edb=# SELECT partition_name, high_value FROM all_tab_partitions;
 partition_name |               high_value
----------------+-----------------------------------------
 EUROPE         | FOR VALUES IN ('FRANCE', 'ITALY')
 ASIA           | FOR VALUES IN ('INDIA', 'PAKISTAN')
 AMERICAS       | FOR VALUES IN ('US', 'CANADA')
 AFRICA         | FOR VALUES IN ('SOUTH AFRICA', 'KENYA')
 OTHERS         | DEFAULT
(5 rows)

以下示例显示行已在新分区中重新分配:

edb=# SELECT tableoid::regclass, * FROM sales;
   tableoid    |dept_no | part_no |   country   |        date        | amount
---------------+--------+---------+-------------+--------------------+--------
sales_americas |     30 | 9519b   | US          | 12-APR-12 00:00:00 | 145000
sales_americas |     30 | 7588b   | CANADA      | 14-DEC-12 00:00:00 |  50000
sales_europe   |     10 | 4519b   | FRANCE      | 17-JAN-12 00:00:00 |  45000
sales_europe   |     10 | 9519b   | ITALY       | 07-JUL-12 00:00:00 |  15000
sales_asia     |     20 | 3788a   | INDIA       | 01-MAR-12 00:00:00 |  75000
sales_asia     |     20 | 3788a   | PAKISTAN    | 04-JUN-12 00:00:00 |  37500
sales_africa   |     40 | 4519b   | SOUTH AFRICA| 08-APR-12 00:00:00 | 120000
sales_africa   |     40 | 4519b   | KENYA       | 08-APR-12 00:00:00 | 120000
sales_others_1 |     50 | 3788a   | CHINA       | 12-MAY-12 00:00:00 |   4950
(9 rows)

定义 MAXVALUE 分区

MAXVALUE 分区(或二级分区)将捕获不属于范围分区(或二级分区)表中任何其他分区的所有行。如果未包含 MAXVALUE 规则,则任何超过分区规则指定的最大限制的行都将导致错误。每个分区或二级分区都有其自己的 MAXVALUE 分区。

MAXVALUE 规则的语法如下:

PARTITION [partition_name] VALUES LESS THAN (MAXVALUE)

其中,partition_name 指定了将存储与为其他分区指定的规则不匹配的所有行的分区的名称。

上一示例创建了一个范围分区表,其中的数据是根据 date 列的值进行分区的。如果您尝试添加的行的 date 超出分区约束中列出的日期,则 POLARDB for Oracle 会报告错误:

acctg=# INSERT INTO sales VALUES
acctg-#   (40, '3000x', 'IRELAND', '01-Mar-2013', '45000');
ERROR:  no partition of relation "sales" found for row
DETAIL:  Partition key of the failing row contains (date) = (01-MAR-13 00:00:00).

以下 CREATE TABLE 命令创建同一表,但该表具有 MAXVALUE 分区。服务器不会引发错误,而是将与先前分区约束不匹配的所有行存储在 others 分区中:

CREATE TABLE sales
(
  dept_no     number,
  part_no     varchar2,
  country     varchar2(20),
  date        date,
  amount      number
)
PARTITION BY RANGE(date)
(
  PARTITION q1_2012 VALUES LESS THAN('2012-Apr-01'),
  PARTITION q2_2012 VALUES LESS THAN('2012-Jul-01'),
  PARTITION q3_2012 VALUES LESS THAN('2012-Oct-01'),
  PARTITION q4_2012 VALUES LESS THAN('2013-Jan-01'),
  PARTITION others VALUES LESS THAN (MAXVALUE)
);

要测试 MAXVALUE 分区,请在日期列中添加一行,该行的值超出分区规则中列出的最后一个日期值。服务器会将该行存储在 others 分区中:

INSERT INTO sales VALUES
  (40, '3000x', 'IRELAND', '01-Mar-2013', '45000');

通过查询 sales 表的内容,确认先前被拒绝的行现在存储在 sales_others 分区中:

acctg=# SELECT tableoid::regclass, * FROM sales;
   tableoid    | dept_no | part_no | country  |        date        | amount
---------------+---------+---------+----------+--------------------+--------
 sales_q1_2012 |      10 | 4519b   | FRANCE   | 17-JAN-12 00:00:00 |  45000
 sales_q1_2012 |      20 | 3788a   | INDIA    | 01-MAR-12 00:00:00 |  75000
 sales_q1_2012 |      30 | 9519b   | CANADA   | 01-FEB-12 00:00:00 |  75000
 sales_q2_2012 |      40 | 9519b   | US       | 12-APR-12 00:00:00 | 145000
 sales_q2_2012 |      20 | 3788a   | PAKISTAN | 04-JUN-12 00:00:00 |  37500
 sales_q2_2012 |      30 | 4519b   | CANADA   | 08-APR-12 00:00:00 | 120000
 sales_q2_2012 |      40 | 3788a   | US       | 12-MAY-12 00:00:00 |   4950
 sales_q3_2012 |      10 | 9519b   | ITALY    | 07-JUL-12 00:00:00 |  15000
 sales_q3_2012 |      10 | 9519a   | FRANCE   | 18-AUG-12 00:00:00 | 650000
 sales_q3_2012 |      10 | 9519b   | FRANCE   | 18-AUG-12 00:00:00 | 650000
 sales_q3_2012 |      20 | 3788b   | INDIA    | 21-SEP-12 00:00:00 |   5090
 sales_q3_2012 |      40 | 4788a   | US       | 23-SEP-12 00:00:00 |   4950
 sales_q4_2012 |      40 | 4577b   | US       | 11-NOV-12 00:00:00 |  25000
 sales_q4_2012 |      30 | 7588b   | CANADA   | 14-DEC-12 00:00:00 |  50000
 sales_q4_2012 |      40 | 4788b   | US       | 09-OCT-12 00:00:00 |  15000
 sales_q4_2012 |      20 | 4519a   | INDIA    | 18-OCT-12 00:00:00 | 650000
 sales_q4_2012 |      20 | 4519b   | INDIA    | 02-DEC-12 00:00:00 |   5090
 sales_others  |      40 | 3000x   | IRELAND  | 01-MAR-13 00:00:00 |  45000
(18 rows)

请注意,POLARDB for Oracle 无法重新分配 MAXVALUE 分区或二级分区的内容:

  • 您不能使用 ALTER TABLE… ADD PARTITION 语句向具有 MAXVALUE 规则的表添加分区,但可以使用 ALTER TABLE… SPLIT PARTITION 语句拆分现有分区。
  • 您不能使用 ALTER TABLE… ADD SUBPARTITION 语句向具有 MAXVALUE 规则的表添加二级分区,但可以使用 ALTER TABLE… SPLIT SUBPARTITION 语句拆分现有二级分区。