有一个数据库,以前设计的时候,是按城市划分表,每个城市一张表,表格式都相同。表的主键是编号(PID),15位或16位字符。
如广州区号是020, 则编号格式如: 020110101000001
  深圳区号是0755,则编号格式如:0755110101000001
每个表里已有大量的数据。
现在想将这些表合并成一个表,并按区号进行分区。由于编号是已有区号信息,于是想用如下表达式提取区号:
substr(pid,1,length(pid)-12),并以这个表达式作为分区字段,创建表的SQL语句如下:CREATE TABLE "TEST"."IMG" (
"PID" VARCHAR2(20 byte) NOT NULL, 
"USERID" VARCHAR2(20 byte) NOT NULL, 
"IMGFILENAME" VARCHAR2(50 byte) NOT NULL, 
"IMGNAME" VARCHAR2(100 byte), 
     "IMGTYPE" NUMBER(1), 
"IMGDESC" VARCHAR2(500 byte), 
"ADDTIME" DATE) 
PARTITION BY LIST (substr(pid,1,length(pid)-12)) 
(PARTITION IMG020 VALUES ('020'), 
PARTITION IMG0755 VALUES ('0755'), 
PARTITION IMG0769 VALUES ('0769')); 运行结果报错:
PARTITION BY LIST (substr(poiid,1,length(poiid)-12))
                         *
第 9 行出现错误: 
ORA-00907: 缺失右括号 
请问能这样分区吗?如果不增加字段,要怎么样才能达到上述要求?谢谢!

解决方案 »

  1.   

    根据虚拟列分区我们来看另一个常见问题。在名为 sales 的表中,您具有以下列: 
    SQL> desc sales
     Name                                      Null?    Type
     ----------------------------------------- -------- ------
     SALES_ID                                  NOT NULL NUMBER
     CUST_ID                                   NOT NULL NUMBER
     SALES_AMT                                          NUMBER假设您希望按照某个允许您进行清除的方案对该表进行分区,并且基于销售额进行存档。以下是销售的四个类别:
    如果 sale_amt 为 且 cust_id 为 则 sale_category 为 
    0-10000 任何内容 LOW 
    10001-100000 0-100 LOW 
    10001-100000 101-200 MEDIUM 
    10001-100000 >200 HIGH 
    100001-1000000 0-100 MEDIUM 
    100001-1000000 101-200 HIGH 
    100001-1000000 >200 ULTRA 
    >1000000 任何内容 ULTRA 您希望根据 sale_category 列对该表进行分区,但有一个问题:没有名为 sale_category 的列。这是您从 sale_amt 列派生的列。那么您如何对该表进行分区呢? 
    在 Oracle 的早期版本中,您可能已经在表中插入了名为 sale_category 的新列,并使用一个触发器用表中所示的逻辑填充该列。但是由于触发器,这个新列的存在可能会导致其他性能影响。在 Oracle 数据库 11g 中,一个称为虚拟列的新特性使您能够创建一个并不存储在表中的列,但在运行时将计算该列。您还可以根据该列进行分区。使用此特性,对该表进行分区就变得轻而易举。create table sales
    (
       sales_id      number,
       cust_id       number,
       sales_amt     number,
       sale_category varchar2(6)
       generated always as
       (
          case
             when sales_amt <= 10000
                then 'LOW'
             when sales_amt > 10000
                and sales_amt <= 100000
                then case
                   when cust_id < 101 then 'LOW'
                   when cust_id between 101 and 200 then 'MEDIUM'
                   else 'MEDIUM'
                end
             when sales_amt > 100000
                and sales_amt <= 1000000
                then case
                   when cust_id < 101 then 'MEDIUM'
                   when cust_id between 101 and 200 then 'HIGH'
                   else 'ULTRA'
                end
             else 'ULTRA'
          end
        ) virtual
    )
    partition by list (sale_category)
    (
       partition p_low values ('LOW'),
       partition p_medium values ('MEDIUM'),
       partition p_high values ('HIGH'),
       partition p_ultra values ('ULTRA')
    )