Skip to content

Latest commit

 

History

History
2041 lines (1355 loc) · 45.5 KB

20190328_01.md

File metadata and controls

2041 lines (1355 loc) · 45.5 KB

EDB EPAS, 社区PG, 某商业PG发行版 Oracle兼容性对比

作者

digoal

日期

2019-03-28

标签

PostgreSQL , EDB , ppas , epas , enterprisedb , 阿里云


背景

对比社区版PostgreSQL, EDB EPAS, 其他PG商业版的Oracle兼容性。

EDB EPAS 兼容性优势

EDB EPAS 支持,社区PG+orafce少量支持(不支持的部分需要改写SQL),其他PG商业版少量支持(不支持的部分需要改写SQL)。

一、分区表

1 PARTITION BY RANGE

CREATE TABLE sales  
  ( prod_id       NUMBER(6)  
  , cust_id       NUMBER  
  , time_id       DATE  
  , channel_id    CHAR(1)  
  , promo_id      NUMBER(6)  
  , quantity_sold NUMBER(3)  
  , amount_sold   NUMBER(10,2)  
  )  
 PARTITION BY RANGE (time_id)  
 ( PARTITION sales_q1_2006 VALUES LESS THAN (TO_DATE('01-APR-2006','dd-MON-yyyy'))  
    TABLESPACE pg_default  
 , PARTITION sales_q2_2006 VALUES LESS THAN (TO_DATE('01-JUL-2006','dd-MON-yyyy'))  
    TABLESPACE pg_default  
 , PARTITION sales_q3_2006 VALUES LESS THAN (TO_DATE('01-OCT-2006','dd-MON-yyyy'))  
    TABLESPACE pg_default  
 , PARTITION sales_q4_2006 VALUES LESS THAN (TO_DATE('01-JAN-2007','dd-MON-yyyy'))  
    TABLESPACE pg_default  
 );  

1、EDB EPAS

支持

2、其他PG商业版

不支持

ERROR:  42601: syntax error at or near "("  
LINE 11:  ( PARTITION sales_q1_2006 VALUES LESS THAN (TO_DATE('01-APR...  
          ^  
LOCATION:  scanner_yyerror, scan.l:1355  

3、社区 pg 11 + orafce

不支持

ERROR:  42601: syntax error at or near "("  
LINE 11:  ( PARTITION sales_q1_2006 VALUES LESS THAN (TO_DATE('01-APR...  
          ^  
LOCATION:  scanner_yyerror, scan.l:1134  

2 PARTITION BY HASH

CREATE TABLE dept (deptno NUMBER, deptname VARCHAR(32))  
     PARTITION BY HASH(deptno)  
       (PARTITION p1 TABLESPACE pg_default, PARTITION p2 TABLESPACE pg_default,  
        PARTITION p3 TABLESPACE pg_default, PARTITION p4 TABLESPACE pg_default);  

1、EDB EPAS

支持

2、其他PG商业版

不支持

ERROR:  42601: syntax error at or near "("  
LINE 3:        (PARTITION p1 TABLESPACE pg_default, PARTITION p2 TAB...  
               ^  
LOCATION:  scanner_yyerror, scan.l:1355  

3、社区 pg 11 + orafce

不支持

ERROR:  42601: syntax error at or near "("  
LINE 3:        (PARTITION p1 TABLESPACE pg_default, PARTITION p2 TAB...  
               ^  
LOCATION:  scanner_yyerror, scan.l:1134  

3 PARTITION BY LIST

CREATE TABLE q1_sales_by_region  
      (deptno number,   
       deptname varchar2(20),  
       quarterly_sales number(10, 2),  
       state varchar2(2))  
   PARTITION BY LIST (state)  
      (PARTITION q1_northwest VALUES ('OR', 'WA'),  
       PARTITION q1_southwest VALUES ('AZ', 'UT', 'NM'),  
       PARTITION q1_northeast VALUES  ('NY', 'VM', 'NJ'),  
       PARTITION q1_southeast VALUES ('FL', 'GA'),  
       PARTITION q1_northcentral VALUES ('SD', 'WI'),  
       PARTITION q1_southcentral VALUES ('OK', 'TX'));  

1、EDB EPAS

支持

2、其他PG商业版

不支持

ERROR:  42601: syntax error at or near "("  
LINE 7:       (PARTITION q1_northwest VALUES ('OR', 'WA'),  
              ^  
LOCATION:  scanner_yyerror, scan.l:1355  

3、社区 pg 11 + orafce

不支持

ERROR:  42601: syntax error at or near "("  
LINE 7:       (PARTITION q1_northwest VALUES ('OR', 'WA'),  
              ^  
LOCATION:  scanner_yyerror, scan.l:1134  

4 SUB-PARTITIONING

CREATE TABLE sales ( dept_no number, part_no varchar2, country varchar2(20), date date, amount number )   
PARTITION BY RANGE(date)   
SUBPARTITION BY LIST(country)  
( PARTITION q1_2012 VALUES LESS THAN('2012-Apr-01')   
( SUBPARTITION q1_europe VALUES ('FRANCE', 'ITALY'),   
SUBPARTITION q1_asia VALUES ('INDIA', 'PAKISTAN'),   
SUBPARTITION q1_americas VALUES ('US', 'CANADA') ),   
PARTITION q2_2012 VALUES LESS THAN('2012-Jul-01')   
( SUBPARTITION q2_europe VALUES ('FRANCE', 'ITALY'),   
SUBPARTITION q2_asia VALUES ('INDIA', 'PAKISTAN'),   
SUBPARTITION q2_americas VALUES ('US', 'CANADA') ),   
PARTITION q3_2012 VALUES LESS THAN('2012-Oct-01')   
( SUBPARTITION q3_europe VALUES ('FRANCE', 'ITALY'),   
SUBPARTITION q3_asia VALUES ('INDIA', 'PAKISTAN'),   
SUBPARTITION q3_americas VALUES ('US', 'CANADA') ),   
PARTITION q4_2012 VALUES LESS THAN('2013-Jan-01')   
( SUBPARTITION q4_europe VALUES ('FRANCE', 'ITALY'),   
SUBPARTITION q4_asia VALUES ('INDIA', 'PAKISTAN'),   
SUBPARTITION q4_americas VALUES ('US', 'CANADA') ) );  

1、EDB EPAS

支持

2、其他PG商业版

不支持

ERROR:  42601: syntax error at or near "SUBPARTITION"  
LINE 1: ...te date, amount number ) PARTITION BY RANGE(date) SUBPARTITI...  
                                                             ^  
LOCATION:  scanner_yyerror, scan.l:1355  

3、社区 pg 11 + orafce

不支持

ERROR:  42601: syntax error at or near "SUBPARTITION"  
LINE 1: ...te date, amount number ) PARTITION BY RANGE(date) SUBPARTITI...  
                                                             ^  
LOCATION:  scanner_yyerror, scan.l:1134  

二、类型

1 NUMBER

create table t1(id number);  

1、EDB EPAS

支持

2、其他PG商业版

支持

3、社区 pg 11 + orafce

不支持

ERROR:  42704: type "number" does not exist  
LINE 1: create table t1(id number);  
                           ^  
LOCATION:  typenameType, parse_type.c:257  

2 VARCHAR2 , NVARCHAR2

create table t2 (c1 varchar2, c2 nvarchar2);  

1、EDB EPAS

支持

2、其他PG商业版

支持

3、社区 pg 11 + orafce

支持

3 CLOB

create table t3 (c1 clob);  

1、EDB EPAS

支持

2、其他PG商业版

支持

3、社区 pg 11 + orafce

不支持

ERROR:  42704: type "clob" does not exist  
LINE 1: create table t3 (c1 clob);  
                            ^  
LOCATION:  typenameType, parse_type.c:257  

4 BLOB

create table t4 (c1 blob);  

1、EDB EPAS

支持

postgres=# \d t4  
                Table "public.t4"  
 Column | Type  | Collation | Nullable | Default   
--------+-------+-----------+----------+---------  
 c1     | bytea |           |          |   

2、其他PG商业版

支持

postgresdb=> \d t4  
               Table "public.t4"  
 Column | Type | Collation | Nullable | Default   
--------+------+-----------+----------+---------  
 c1     | blob |           |          |   

3、社区 pg 11 + orafce

不支持

ERROR:  42704: type "blob" does not exist  
LINE 1: create table t4 (c1 blob);  
                            ^  
LOCATION:  typenameType, parse_type.c:257  

5 RAW

create table t5 (c1 raw);  

1、EDB EPAS

支持

2、其他PG商业版

不支持

ERROR:  42601: syntax error at or near ")"  
LINE 1: create table t5 (c1 raw);  
                               ^  
LOCATION:  scanner_yyerror, scan.l:1355  
  
  
postgresdb=> create table t5 (c1 raw(16));  
CREATE TABLE  
postgresdb=> \d t5  
                  Table "public.t5"  
 Column |   Type    | Collation | Nullable | Default   
--------+-----------+-----------+----------+---------  
 c1     | "raw"(16) |           |          |   
  
postgresdb=> create table t6 (c1 "raw");  
CREATE TABLE  
postgresdb=> \d t6  
                Table "public.t6"  
 Column | Type  | Collation | Nullable | Default   
--------+-------+-----------+----------+---------  
 c1     | "raw" |           |          |   

3、社区 pg 11 + orafce

不支持

ERROR:  42704: type "raw" does not exist  
LINE 1: create table t5 (c1 raw);  
                            ^  
LOCATION:  typenameType, parse_type.c:257  

6 LONG RAW

create table t6 (c1 LONG RAW);  

1、EDB EPAS

支持

postgres=# \d t6  
                Table "public.t6"  
 Column | Type  | Collation | Nullable | Default   
--------+-------+-----------+----------+---------  
 c1     | bytea |           |          |   

2、其他PG商业版

不支持

ERROR:  42601: syntax error at or near "RAW"  
LINE 1: create table t6 (c1 LONG RAW);  
                                 ^  
LOCATION:  scanner_yyerror, scan.l:1355  

3、社区 pg 11 + orafce

不支持

postgres=# create table t6 (c1 LONG RAW);  
ERROR:  42601: syntax error at or near "RAW"  
LINE 1: create table t6 (c1 LONG RAW);  
                                 ^  
LOCATION:  scanner_yyerror, scan.l:1134  

7 DATE

1、EDB EPAS

支持,兼容Oracle

postgres=# select date '2019-01-01 10:10:10';  
        date          
--------------------  
 01-JAN-19 10:10:10  
(1 row)  

2、其他PG商业版

不支持,不兼容ORACLE

postgresdb=> select date '2019-01-01 10:10:10';  
    date      
------------  
 2019-01-01  
(1 row)  

3、社区 pg 11 + orafce

不支持,不兼容ORACLE

postgresdb=> select date '2019-01-01 10:10:10';  
    date      
------------  
 2019-01-01  
(1 row)  

三、SQL语法

1 HIERARCHICAL QUERIES

create table te1 (id int, pid int, n name);  
insert into te1 values   
(1,null,'lead'),  
(2,1,'l1'),  
(3,1,'l1'),  
(4,3,'l1'),  
(5,1,'l1'),  
(6,4,'l1');  
  
SELECT *, LEVEL  
   FROM te1  
   CONNECT BY PRIOR id = pid;  

1、EDB EPAS

支持

2、其他PG商业版

不支持

ERROR:  42601: syntax error at or near "BY"  
LINE 3:    CONNECT BY PRIOR id = pid;  
                   ^  
LOCATION:  scanner_yyerror, scan.l:1355  

3、社区 pg 11 + orafce

不支持

ERROR:  42601: syntax error at or near "BY"  
LINE 3:    CONNECT BY PRIOR id = pid;  
                   ^  
LOCATION:  scanner_yyerror, scan.l:1134  

2 SYNONYMS (PUBLIC AND PRIVATE)

CREATE PUBLIC SYNONYM customers FOR te1;  

1、EDB EPAS

支持

2、其他PG商业版

不支持

ERROR:  42601: syntax error at or near "PUBLIC"  
LINE 1: CREATE PUBLIC SYNONYM customers FOR te1;  
               ^  
LOCATION:  scanner_yyerror, scan.l:1355  

3、社区 pg 11 + orafce

不支持

ERROR:  42601: syntax error at or near "PUBLIC"  
LINE 1: CREATE PUBLIC SYNONYM customers FOR te1;  
               ^  
LOCATION:  scanner_yyerror, scan.l:1134  

3 SEQUENCE GENERATOR

create sequence seq1;  
  
select seq1.nextval;  

1、EDB EPAS

支持

2、其他PG商业版

支持

3、社区 pg 11 + orafce

不支持

ERROR:  42P01: missing FROM-clause entry for table "seq1"  
LINE 1: select seq1.nextval;  
               ^  
LOCATION:  errorMissingRTE, parse_relation.c:3240  

4 HINT

QUERY HINTS

create table t6 (id int primary key, info text);  
EXPLAIN SELECT /*+ FULL(t6) */ * FROM t6 WHERE id = 100;  

1、EDB EPAS

支持

2、其他PG商业版

不支持

INFO:  00000: pg_hint_plan: hint syntax error at or near "FULL(t6) "  
DETAIL:  Unrecognized hint keyword "FULL".  
LOCATION:  parse_hints, pg_hint_plan.c:1691  
                            QUERY PLAN                               
-------------------------------------------------------------------  
 Index Scan using t6_pkey on t6  (cost=0.15..8.17 rows=1 width=36)  
   Index Cond: (id = 100)  
(2 rows)  

3、社区 pg 11 + orafce

不支持

INFO:  00000: pg_hint_plan: hint syntax error at or near "FULL(t6) "  
DETAIL:  Unrecognized hint keyword "FULL".  
LOCATION:  parse_hints, pg_hint_plan.c:1707  
                            QUERY PLAN                               
-------------------------------------------------------------------  
 Index Scan using t6_pkey on t6  (cost=0.15..2.37 rows=1 width=36)  
   Index Cond: (id = 100)  
(2 rows)  

四、函数

1 总共支持的函数个数

select count(distinct proname) from pg_proc ;  

1、EDB EPAS

支持 3155 个

2、其他PG商业版

支持 2514 个

3、社区 pg 11 + orafce

支持 2775 个

2 DUAL

postgres=# select * from dual;  
 dummy   
-------  
 X  
(1 row)  

1、EDB EPAS

支持

2、其他PG商业版

支持

3、社区 pg 11 + orafce

支持

3 DECODE

postgres=# select DECODE(3, 1,'One', 2,'Two', 3,'Three', 'Not found');  
 decode   
--------  
 Three  
(1 row)  

1、EDB EPAS

支持

2、其他PG商业版

支持

3、社区 pg 11 + orafce

支持

4 ROWNUM

select * from pg_class where rownum<10;  

1、EDB EPAS

支持

2、其他PG商业版

支持(但是有问题)。

慢、并且不可重复调用

3、社区 pg 11 + orafce

不支持

ERROR:  42703: column "rownum" does not exist  
LINE 1: select * from pg_class where rownum<10;  
                                     ^  
LOCATION:  errorMissingColumn, parse_relation.c:3294  

5 SYSDATE

postgres=# select sysdate;  
      sysdate         
--------------------  
 28-MAR-19 16:00:57  
(1 row)  

1、EDB EPAS

支持

2、其他PG商业版

不兼容oracle

postgresdb=> select sysdate;  
  sysdate     
------------  
 2019-03-28  
(1 row)  

3、社区 pg 11 + orafce

不支持

ERROR:  42703: column "sysdate" does not exist  
LINE 1: select sysdate;  
               ^  
LOCATION:  errorMissingColumn, parse_relation.c:3294  

6 SYSTIMESTAMP

1、EDB EPAS

支持

postgres=# select SYSTIMESTAMP();  
           systimestamp             
----------------------------------  
 28-MAR-19 16:01:44.203498 +08:00  
(1 row)  

2、其他PG商业版

不兼容oracle

postgresdb=> select SYSTIMESTAMP;  
         systimestamp            
-------------------------------  
 2019-03-28 16:01:46.759459+08  
(1 row)  

3、社区 pg 11 + orafce

不支持

ERROR:  42703: column "systimestamp" does not exist  
LINE 1: select SYSTIMESTAMP;  
               ^  
LOCATION:  errorMissingColumn, parse_relation.c:3294  

7 NVL

select NVL(9, 0);  

1、EDB EPAS

支持

2、其他PG商业版

支持

3、社区 pg 11 + orafce

支持

8 NVL2

select nvl2(100,1,2);  

1、EDB EPAS

支持

2、其他PG商业版

支持

3、社区 pg 11 + orafce

支持

五、安全

1 DATA REDACTION

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

2 Database Firewall Only (SQL/Protect)

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

3 VPD

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

4 PL/SQL内容加密

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

5 PROFILES FOR PASSWORDS

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

六、PL/SQL

1 SPL (PL/SQL Compatible) (Block Structured Language)

CREATE OR REPLACE FUNCTION cs_fmt_browser_version(v_name varchar2,  
                                                  v_version varchar2)  
RETURN varchar2 IS  
BEGIN  
    IF v_version IS NULL THEN  
        RETURN v_name;  
    END IF;  
    RETURN v_name || '/' || v_version;  
END;  
/  

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

2 NAMED PARAMETER NOTATION FOR STORED PROCEDURES

CREATE OR REPLACE PROCEDURE cs_update_referrer_type_proc IS  
    CURSOR referrer_keys IS  
        SELECT * FROM cs_referrer_keys  
        ORDER BY try_order;  
    func_cmd VARCHAR(4000);  
BEGIN  
    func_cmd := 'CREATE OR REPLACE FUNCTION cs_find_referrer_type(v_host IN VARCHAR2,  
                 v_domain IN VARCHAR2, v_url IN VARCHAR2) RETURN VARCHAR2 IS BEGIN';  
  
    FOR referrer_key IN referrer_keys LOOP  
        func_cmd := func_cmd ||  
          ' IF v_' || referrer_key.kind  
          || ' LIKE ''' || referrer_key.key_string  
          || ''' THEN RETURN ''' || referrer_key.referrer_type  
          || '''; END IF;';  
    END LOOP;  
  
    func_cmd := func_cmd || ' RETURN NULL; END;';  
  
    EXECUTE IMMEDIATE func_cmd;  
END;  
/  
CREATE OR REPLACE PROCEDURE cs_parse_url(  
    v_url IN VARCHAR2,  
    v_host OUT VARCHAR2,  -- This will be passed back  
    v_path OUT VARCHAR2,  -- This one too  
    v_query OUT VARCHAR2) -- And this one  
IS  
    a_pos1 INTEGER;  
    a_pos2 INTEGER;  
BEGIN  
    v_host := NULL;  
    v_path := NULL;  
    v_query := NULL;  
    a_pos1 := instr(v_url, '//');  
  
    IF a_pos1 = 0 THEN  
        RETURN;  
    END IF;  
    a_pos2 := instr(v_url, '/', a_pos1 + 2);  
    IF a_pos2 = 0 THEN  
        v_host := substr(v_url, a_pos1 + 2);  
        v_path := '/';  
        RETURN;  
    END IF;  
  
    v_host := substr(v_url, a_pos1 + 2, a_pos2 - a_pos1 - 2);  
    a_pos1 := instr(v_url, '?', a_pos2 + 1);  
  
    IF a_pos1 = 0 THEN  
        v_path := substr(v_url, a_pos2);  
        RETURN;  
    END IF;  
  
    v_path := substr(v_url, a_pos2, a_pos1 - a_pos2);  
    v_query := substr(v_url, a_pos1 + 1);  
END;  
/  

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

3 TRIGGERS

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

4 REF CURSORS

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

5 IMPLICIT / EXPLICIT CURSORS

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

6 ANONYMOUS BLOCKS

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

7 BULK COLLECT/BIND

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

8 ASSOCIATIVE ARRAYS

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

9 NESTED TABLES

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

10 VARRAYS

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

11 PL/SQL SUPPLIED PACKAGES

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

12 PRAGMA RESTRICT_REFERENCES

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

13 PRAGMA EXCEPTION_INIT

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

14 PRAGMA AUTONOMOUS_TRANSACTION

CREATE OR REPLACE PROCEDURE cs_create_job(v_job_id IN INTEGER) IS  
    a_running_job_count INTEGER;  
BEGIN  
    LOCK TABLE cs_jobs IN EXCLUSIVE MODE;  
  
    SELECT count(*) INTO a_running_job_count FROM cs_jobs WHERE end_stamp IS NULL;  
  
    IF a_running_job_count > 0 THEN  
        COMMIT;   --  free lock  
        raise_application_error(-20000,  
                 'Unable to create a new job: a job is currently running.');  
    END IF;  
  
    DELETE FROM cs_active_job;  
    INSERT INTO cs_active_job(job_id) VALUES (v_job_id);  
  
    BEGIN  
        INSERT INTO cs_jobs (job_id, start_stamp) VALUES (v_job_id, sysdate);  
    EXCEPTION  
        WHEN dup_val_on_index THEN NULL; -- don't worry if it already exists  
    END;  
    COMMIT;  
END;  
/  

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

15 USER DEFINED EXCEPTIONS

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

16 OBJECT TYPES

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

17 SUB-TYPES

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

七、包

1 支持的包数量

select *,object_type from dba_objects where object_type='PACKAGE';  
  
\dn  

1、EDB EPAS

支持 26 种包

2、其他PG商业版

支持 2 种包

3、社区 pg 11 + orafce

支持 7 种包

2 支持的包内函数数量

select proname from pg_proc where pronamespace= any (array(select oid from pg_namespace where nspname in (select nspname from pg_namespace where nspname ~ 'dbms' or nspname='utl_file')));  

1、EDB EPAS

支持 317 种包内函数

2、其他PG商业版

支持 6 种包内函数

3、社区 pg 11 + orafce

支持 97 种包内函数

八、高级功能

1 DATABASE LINKS

CREATE DATABASE LINK local   
   CONNECT TO hr IDENTIFIED BY hr  
   USING 'local';  

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

2 AWR

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

3 sql profile

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

4 索引推荐

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

5 用户级 cpu, memory 资源隔离

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

6 TUNING PACKAGE

Tuning Wizard, Index Advisor, Postgres Expert

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

九、系统视图

select * from dba_objects where schema_name ='SYS' and object_type='VIEW' order by object_name;  
  
select distinct on (relkind,relnamespace,relname) oid,relkind,relname,relnamespace::regnamespace from pg_class where relname ~ '^dba|^user|^all|^v\$|^dbms' and relnamespace='sys'::regnamespace order by 2,4,3;  
  
\dv oracle.*  

1、EDB EPAS

支持 88 个系统视图

2、其他PG商业版

支持 40 个系统视图

3、社区 pg 11 + orafce

支持 11 个系统视图

十、C内嵌编程

1 EMBEDDED C

Pro*C  

1、EDB EPAS

支持 , ecpgplus

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

十一、客户端驱动

1 APPLICATION CLIENT LIBRARY SUPPORT

OCL  (OCI Support)  

1、EDB EPAS

支持

2、其他PG商业版

不支持

3、社区 pg 11 + orafce

不支持

社区PG优势,ORACLE弱势

社区PG支持,ORACLE不支持的功能

一、GiST

Easy creation of specialized indexes.

空间、范围、向量、相似、图像等均可支持。

二、GIN

Custom inverted indexes.

倒排索引,与搜索引擎类似功能。

三、TRANSACTIONAL DDL

DDL可以封装到事务中,确保原子性。

四、VIEW SECURITY BARRIERS

《PostgreSQL leakproof function in rule rewrite("attack" security_barrier views)》

视图栅栏。

五、SESSION BASED SYNCHRONOUS REPLICATION

会话级,quorum based 同步复制。

《PostgreSQL 一主多从(多副本,强同步)简明手册 - 配置、压测、监控、切换、防脑裂、修复、0丢失 - 珍藏级》

六、ADDITIONAL PROGRAMMING LANGUAGES FOR DATABASE SERVER STORED PROCEDURES, TRIGGERS, AND FUNCTIONS

1、ORACLE仅支持JAVA

2、PG支持非常多:

PL/pgSQL (PostgreSQL's Procedural Language)  
PL/Java  
C  
C++  
PL/Perl  
Python  
PL/Tcl  

社区PG弱势,ORACLE优势

ORACLE支持,EDB以及社区PG不支持的功能

一、DATABASE VAULT

二、DATA MASKING

《PostgreSQL Oracle 兼容性 之 - 数据采样与脱敏》

EDB data redact

三、FLASHBACK QUERY

《PostgreSQL flashback(闪回) 功能实现与介绍》

《PostgreSQL 闪回 - flash back query emulate by trigger》

四、FLASHBACK TABLE, DATABASE AND TRANSACTION QUERY

《PostgreSQL Oracle 兼容性之 - 事件触发器实现类似Oracle的回收站功能》

《PostgreSQL 回收站功能 - 基于HOOK的recycle bin pgtrashcan》

五、REAL APPLICATION CLUSTERS (RAC)

六、IN-MEMORY DATABASE

七、SUPPORT FOR XML NAMESPACES, DOM, XQUERY, SQL/XML AND XSLT.

八、COMPRESSION (TABLES, FILES, NETWORK, AND BACKUPS)

九、TRANSPORTABLE CROSS-PLATFORM TABLE SPACES

《PostgreSQL 的表传输功能》

十、ADVANCED COMPRESSION

https://commitfest.postgresql.org/22/1283/

十一、ONLINE REORGANIZATION

《PostgreSQL 普通表在线转换为分区表 - online exchange to partition table》

《PostgreSQL 收缩膨胀表或索引 - pg_squeeze or pg_repack》

十二、AUTOMATIC MEMORY MANAGEMENT

十三、AUTOMATIC STORAGE MANAGEMENT

十四、BINARY_FLOAT 类型

十五、BINARY_DOUBLE 类型

十六、NCLOB 类型

其他PG商业版优势,EDB弱势

EDB 未支持,其他PG商业版支持

1、oid 冲突

CREATE TABLE TEMP_X_MIGRATE(          
    OID NUMBER,  
    NID NUMBER  
) ;  

1、其他PG商业版

CREATE TABLE TEMP_X_MIGRATE(          
    OID NUMBER,  
    NID NUMBER  
) ;  
  
  
CREATE TABLE TEMP_X_MIGRATE(          
    OID NUMBER,  
    NID NUMBER  
) with oids;  -- 此时才冲突  
ERROR:  42701: column name "oid" conflicts with a system column name  
LOCATION:  CheckAttributeNamesTypes, heap.c:453  

2、EDB EPAS

postgres=# CREATE TABLE TEMP_X_MIGRATE(  
    OID NUMBER,  
    NID NUMBER  
) without oids;  
ERROR:  42701: column name "oid" conflicts with a system column name  
LOCATION:  CheckAttributeNamesTypes, heap.c:474  

内核建议:可以先判断一下是否有with oids,without oids时,oid可以作为列名,并无冲突

2、不支持 sys_guid()

select sys_guid();  

1、其他PG商业版

postgresdb=> select sys_guid();  
             sys_guid               
----------------------------------  
 81DBA63C5FFF4677BEF994CB2553A90A  
(1 row)  
  
postgresdb-> \df+ sys_guid  
                                                                                                           List of functions  
   Schema   |   Name   | Result data type | Argument data types | Type | Volatility | Parallel |  Owner   | Security | Access privileges | Language |                        Source code                         |     Description        
------------+----------+------------------+---------------------+------+------------+----------+----------+----------+-------------------+----------+------------------------------------------------------------+----------------------  
 pg_catalog | sys_guid | "raw"            |                     | func | volatile   | safe     | rdsAdmin | invoker  |                   | sql      | select replace(gen_pg_random_uuid()::text,'-','')::RAW(16) | generate random uuid  
(1 row)  
  
postgresdb-> \sf+ sys_guid  
        CREATE OR REPLACE FUNCTION pg_catalog.sys_guid()  
         RETURNS "raw"  
         LANGUAGE sql  
         PARALLEL SAFE STRICT COST 1  
        AS $function$select replace(gen_pg_random_uuid()::text,'-','')::RAW(16)$function$  
postgresdb-> \df+ gen_pg_random_uuid  
                                                                                            List of functions  
   Schema   |        Name        | Result data type | Argument data types | Type | Volatility | Parallel |  Owner   | Security | Access privileges | Language |    Source code     |     Description        
------------+--------------------+------------------+---------------------+------+------------+----------+----------+----------+-------------------+----------+--------------------+----------------------  
 pg_catalog | gen_pg_random_uuid | uuid             |                     | func | volatile   | safe     | rdsAdmin | invoker  |                   | internal | gen_pg_random_uuid | generate random uuid  
(1 row)  
  
postgresdb=> select gen_pg_random_uuid();  
          gen_pg_random_uuid            
--------------------------------------  
 f268eec7-389b-4e0a-ba32-4b6a081d1392  
(1 row)  
  
postgresdb=> select replace('f268eec7-389b-4e0a-ba32-4b6a081d1392','-','')::raw(16);  
             replace                
----------------------------------  
 F268EEC7389B4E0ABA324B6A081D1392  
(1 row)  

2、EDB EPAS

ERROR:  42883: function sys_guid() does not exist  
LINE 1: select sys_guid();  
               ^  
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.  
LOCATION:  ParseFuncOrColumn, parse_func.c:858  

内核建议:通过pgcrypto提取gen_random_uuid函数代码,封装一下即可得到sys_uuid(),如下

postgresdb=> select upper(rawtohex(hextoraw(replace('f268eec7-389b-4e0a-ba32-4b6a081d1392','-',''))));  
              upper                 
----------------------------------  
 F268EEC7389B4E0ABA324B6A081D1392  
(1 row)  

3、number * 未支持

CREATE TABLE GRDK_DK_ZDPK_SBYY(  
    ID NUMBER(*, 0) DEFAULT 0 NOT NULL,  
    YHBM VARCHAR2(10) DEFAULT ' ' NOT NULL,  
    YHMC VARCHAR2(60) DEFAULT ' ' NOT NULL,  
    PKRQ DATE,  
    PKJD VARCHAR2(2) DEFAULT ' ' NOT NULL,  
    MSG VARCHAR2(100) DEFAULT ' ' NOT NULL,  
    PCID NUMBER(*, 0) DEFAULT 0 NOT NULL,  
    ZXJGBM VARCHAR2(60) DEFAULT ' ' NOT NULL  
);  

1、其他PG商业版

postgresdb=> \d+ GRDK_DK_ZDPK_SBYY  
                                            Table "public.grdk_dk_zdpk_sbyy"  
 Column |          Type          | Collation | Nullable |        Default         | Storage  | Stats target | Description   
--------+------------------------+-----------+----------+------------------------+----------+--------------+-------------  
 id     | numeric(38,0)          |           | not null | 0                      | main     |              |   
 yhbm   | character varying(10)  |           | not null | ' '::character varying | extended |              |   
 yhmc   | character varying(60)  |           | not null | ' '::character varying | extended |              |   
 pkrq   | date                   |           |          |                        | plain    |              |   
 pkjd   | character varying(2)   |           | not null | ' '::character varying | extended |              |   
 msg    | character varying(100) |           | not null | ' '::character varying | extended |              |   
 pcid   | numeric(38,0)          |           | not null | 0                      | main     |              |   
 zxjgbm | character varying(60)  |           | not null | ' '::character varying | extended |              |   

2、EDB EPAS

ERROR:  42601: syntax error at or near "*"  
LINE 2:     ID NUMBER(*, 0) DEFAULT 0 NOT NULL,  
                      ^  
LOCATION:  scanner_yyerror, scan.l:1419  

内核建议:number(* 直接替换为最大长度38

4、索引不支持schema

CREATE INDEX public.TMP_HR_USERXX_XXBG_SURE_ID ON public.t1(id);  

1、其他PG商业版

hack做法,实际上是在TABLE同一个SCHEMA里面

postgresdb=> CREATE INDEX wt.TMP_HR_USERXX_XXBG_SURE_ID ON public.t1(id);  
CREATE INDEX  
  
postgresdb=> CREATE INDEX public.TMP_HR_USERXX_XXBG_SURE_ID ON public.t1(id);  
ERROR:  42P07: relation "tmp_hr_userxx_xxbg_sure_id" already exists  
LOCATION:  index_create, index.c:877  
  
postgresdb=> \di tmp_hr_userxx_xxbg_sure_id   
                      List of relations  
 Schema |            Name            | Type  | Owner | Table   
--------+----------------------------+-------+-------+-------  
 public | tmp_hr_userxx_xxbg_sure_id | index | root  | t1  
(1 row)  

2、EDB EPAS

postgres=# CREATE INDEX public.TMP_HR_USERXX_XXBG_SURE_ID ON public.t1(id);  
ERROR:  42601: syntax error at or near "."  
LINE 1: CREATE INDEX public.TMP_HR_USERXX_XXBG_SURE_ID ON public.t1(...  
                           ^  
LOCATION:  scanner_yyerror, scan.l:1419  

内核建议:hack做法,实际上是在TABLE同一个SCHEMA里面

5、不支持char指定byte, char长度

CREATE TABLE CHAR_DATA_TYPE_TEST(  
    CHAR2 CHAR(1),  
    CHAR3 CHAR(1 byte),  
    CHAR4 CHAR(1 CHAR),  
    VARCHAR21 VARCHAR2(1),  
    VARCHAR22 VARCHAR2(1),  
    VARCHAR23 VARCHAR2(1 CHAR),  
    NCHAR2 NCHAR(1),  
    NVARCHAR21 NVARCHAR2(1)  
);  

1、其他PG商业版

hack做法,byte, char都作为char

postgresdb=> \d char_data_type_test   
                 Table "public.char_data_type_test"  
   Column   |         Type         | Collation | Nullable | Default   
------------+----------------------+-----------+----------+---------  
 char2      | character(1)         |           |          |   
 char3      | character(1)         |           |          |   
 char4      | character(1)         |           |          |   
 varchar21  | character varying(1) |           |          |   
 varchar22  | character varying(1) |           |          |   
 varchar23  | character varying(1) |           |          |   
 nchar2     | character(1)         |           |          |   
 nvarchar21 | "nvarchar2"(1)       |           |          |   

2、EDB EPAS

ERROR:  42601: syntax error at or near "byte"  
LINE 3:     CHAR3 CHAR(1 byte),  
                         ^  
LOCATION:  scanner_yyerror, scan.l:1419  

内核建议:hack做法,byte, char都作为char

6、CONSTRAINT DISABLE

ALTER TABLE a ADD CONSTRAINT a_pk PRIMARY KEY(ID) DISABLE;  

1、其他PG商业版

hack 做法,DISABLE CONSTRAINT隐式替换为ENABLE CONSTRAINT

WARNING:  01000: DISABLE CONSTRAINT is redirected to ENABLE CONSTRAINT.  
LOCATION:  base_yyparse, gram.y:4280  
ALTER TABLE  

2、EDB EPAS

ERROR:  42601: syntax error at or near "DISABLE"  
LINE 1: ALTER TABLE a ADD CONSTRAINT a_pk PRIMARY KEY(ID) DISABLE;  
                                                          ^  
LOCATION:  scanner_yyerror, scan.l:1419  

内核建议::hack 做法,DISABLE CONSTRAINT隐式替换为ENABLE CONSTRAINT

7、sequence 不支持order

CREATE SEQUENCE EF_MLH_BM  
    MINVALUE 1  
    MAXVALUE 9999999999  
    INCREMENT BY 1 START WITH 8  
    NOCACHE  
    NOORDER  
    CYCLE;  

1、其他PG商业版

hack做法,实际上都是noorder, 即使指定了order

2、EDB EPAS

ERROR:  42601: syntax error at or near "NOORDER"  
LINE 6:     NOORDER  
            ^  
LOCATION:  scanner_yyerror, scan.l:1419  

内核建议:hack做法,实际上都是noorder,即使指定order

8、PARTITION 不能作为列名

CREATE TABLE SCHEDULER_CONFIGRATION(  
    ID numeric NOT NULL,  
    GMT_CREATED TIMESTAMP(6),  
    GMT_MODIFIED TIMESTAMP(6),  
    CREATOR VARCHAR2(32),  
    MODIFIER VARCHAR2(32),  
    JOB_NAME VARCHAR2(128) NOT NULL,  
    TRIGGER_NAME VARCHAR2(128),  
    CRON_EXPRESSION VARCHAR2(128) NOT NULL,  
    STATUS VARCHAR2(32) NOT NULL,  
    EXECUTE_SERVERS VARCHAR2(512),  
    PARTITION VARCHAR2(512),  
    PERSISTENT VARCHAR2(32) DEFAULT 'N',  
    PRIORITY numeric DEFAULT 5  
);  

1、其他PG商业版

支持

2、社区版本PG

支持

3、EDB EPAS 报错

ERROR:  42601: syntax error at or near "PARTITION"  
LINE 12:     PARTITION VARCHAR2(512),  
             ^  
LOCATION:  scanner_yyerror, scan.l:1419  

内核建议:改进EPAS语法解析器

9、关键字必须使用as才支持作为alias name

create view v(name) as select relname from pg_class union all select '' name;  

1、其他PG商业版

支持

2、EDB EPAS 以及 社区版本PG 报错

ERROR:  42601: syntax error at or near "name"  
LINE 1: ...e) as select relname from pg_class union all select '' name;  
                                                                  ^  
LOCATION:  scanner_yyerror, scan.l:1419  

改成如下SQL后通过

create view v(name) as select relname from pg_class union all select '' as name;  

内核建议:改进语法解析器

10、隐式转换不全面

select nvl2(a,b,c) from (values ('a'::text,'b',to_char('a')) ) as t(a,b,c);  

1、其他PG商业版

支持

2、EDB EPAS 以及 社区版本PG 报错

ERROR:  42883: function nvl2(text, text, character varying) does not exist  
LINE 1: select nvl2(a,b,c) from (values ('a'::text,'b',to_char('a'))...  
               ^  
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.  
LOCATION:  ParseFuncOrColumn, parse_func.c:858  

内核建议:增加隐式转换。

小结

1、EDB优势,其他PG商用发行版弱势

分类1 分类2 EDB EPAS 其他商用发行版PG 社区版本PG+orafce插件
分区表 PARTITION BY RANGE 兼容 不兼容 不兼容
分区表 PARTITION BY HASH 兼容 不兼容 不兼容
分区表 PARTITION BY LIST 兼容 不兼容 不兼容
分区表 SUB-PARTITIONING 兼容 不兼容 不兼容
类型 NUMBER 兼容 兼容 不兼容
类型 VARCHAR2 , NVARCHAR2 兼容 兼容 兼容
类型 CLOB 兼容 兼容 不兼容
类型 BLOB 兼容 兼容 不兼容
类型 RAW 兼容 不兼容 不兼容
类型 LONG RAW 兼容 不兼容 不兼容
类型 DATE 兼容 不兼容 不兼容
SQL语法 HIERARCHICAL QUERIES 兼容 不兼容 不兼容
SQL语法 SYNONYMS (PUBLIC AND PRIVATE) 兼容 不兼容 不兼容
SQL语法 SEQUENCE GENERATOR 兼容 兼容 不兼容
SQL语法 HINT 兼容 不兼容 不兼容
函数 支持个数 3155 2514 2775
函数 DUAL 兼容 兼容 兼容
函数 DECODE 兼容 兼容 兼容
函数 ROWNUM 兼容 不兼容 不兼容
函数 SYSDATE 兼容 不兼容 不兼容
函数 SYSTIMESTAMP 兼容 不兼容 不兼容
函数 NVL 兼容 兼容 兼容
函数 NVL2 兼容 兼容 兼容
安全 DATA REDACTION 兼容 不兼容 不兼容
安全 Database Firewall Only (SQL/Protect) 兼容 不兼容 不兼容
安全 VPD 兼容 不兼容 不兼容
安全 PL/SQL代码加密 兼容 不兼容 不兼容
安全 PROFILES FOR PASSWORDS 兼容 不兼容 不兼容
PL/SQL PL/SQL Compatible 兼容 不兼容 不兼容
PL/SQL NAMED PARAMETER NOTATION FOR STORED PROCEDURES 兼容 不兼容 不兼容
PL/SQL TRIGGERS 兼容 不兼容 不兼容
PL/SQL REF CURSORS 兼容 不兼容 不兼容
PL/SQL IMPLICIT / EXPLICIT CURSORS 兼容 不兼容 不兼容
PL/SQL ANONYMOUS BLOCKS 兼容 不兼容 不兼容
PL/SQL BULK COLLECT/BIND 兼容 不兼容 不兼容
PL/SQL ASSOCIATIVE ARRAYS 兼容 不兼容 不兼容
PL/SQL NESTED TABLES 兼容 不兼容 不兼容
PL/SQL VARRAYS 兼容 不兼容 不兼容
PL/SQL PL/SQL SUPPLIED PACKAGES 兼容 不兼容 不兼容
PL/SQL PRAGMA RESTRICT_REFERENCES 兼容 不兼容 不兼容
PL/SQL PRAGMA EXCEPTION_INIT 兼容 不兼容 不兼容
PL/SQL PRAGMA AUTONOMOUS_TRANSACTION 兼容 不兼容 不兼容
PL/SQL USER DEFINED EXCEPTIONS 兼容 不兼容 不兼容
PL/SQL OBJECT TYPES 兼容 不兼容 不兼容
PL/SQL SUB-TYPES 兼容 不兼容 不兼容
支持的包 26 2 7
包内置函数 317 6 97
高级功能 DATABASE LINKS 兼容 不兼容 不兼容
高级功能 AWR 兼容 不兼容 不兼容
高级功能 sql profile 兼容 不兼容 不兼容
高级功能 索引推荐 兼容 不兼容 不兼容
高级功能 用户级 cpu, memory 资源隔离 兼容 不兼容 不兼容
高级功能 TUNING PACKAGE 兼容 不兼容 不兼容
系统视图 系统视图个数 88 40 11
C内嵌编程 Pro*C 兼容 不兼容 不兼容
客户端驱动 OCI 兼容 不兼容 不兼容

2、社区PG优势,ORACLE弱势

功能点 PG Oracle 说明
GiST 索引 支持 不支持 空间、范围、向量、相似、图像等均可支持
GIN 索引 支持 不支持 倒排索引,与搜索引擎类似功能
TRANSACTIONAL DDL 支持 不支持 DDL可以封装到事务中,确保原子性。
VIEW SECURITY BARRIERS 支持 不支持 视图安全
SESSION BASED SYNCHRONOUS REPLICATION 支持 不支持 会话级事务同步模式可选
数据库编程语言 支持 仅java 几乎任意语言都可以成为PG的存储过程编程语言

3、社区PG弱势,ORACLE优势

功能点 PG Oracle 说明
DATABASE VAULT 不支持 支持 -
DATA MASKING 不支持 支持 数据脱敏
FLASHBACK QUERY 不支持(通过插件支持) 支持 闪回
FLASHBACK TABLE, DATABASE AND TRANSACTION QUERY 不支持(通过插件支持) 支持 回收站
REAL APPLICATION CLUSTERS (RAC) 不支持 支持 -
IN-MEMORY DATABASE 不支持 支持 内存数据库
SUPPORT FOR XML NAMESPACES, DOM, XQUERY, SQL/XML AND XSLT. 不支持 支持 -
COMPRESSION (TABLES, FILES, NETWORK, AND BACKUPS) 不支持 支持 压缩
TRANSPORTABLE CROSS-PLATFORM TABLE SPACES 不支持(通过插件支持) 支持 传输表
ADVANCED COMPRESSION 不支持(通过插件支持) 支持 压缩
ONLINE REORGANIZATION 不支持(通过插件支持) 支持 在线重组表
AUTOMATIC MEMORY MANAGEMENT 不支持 支持 自动内存管理
AUTOMATIC STORAGE MANAGEMENT 不支持 支持 自动存储管理

4、EDB弱势,其他PG商用发行版优势

功能点 EDB EPAS 其他PG商用发行版 说明
oid 冲突 报错 通过 oid作为列名
sys_guid 报错 通过 sys_guid函数
number * 报错 通过 自动将*转换为最大长度
索引不支持指定schema 报错 通过 隐式转换为table相同schema
不支持char指定byte, char长度 报错 通过 隐式转换为字符长度
CONSTRAINT DISABLE 报错 通过 隐式转换为enable
sequence 不支持order 报错 通过 隐式转换为noorder
PARTITION 不能作为列名 报错 通过 语义解析错误
关键字必须使用as才支持作为alias name 报错 通过 语义解析错误
隐式转换不全面 报错 通过 隐式转换问题

有几个点其他商用PG发行版兼容性好于EDB EPAS,采用的是HACK的做法,(例如:sequence order hack做法,实际上都是noorder,即使指定order)。

EDB EPAS 是当前ORACLE兼容性最好的版本,深度兼容ORACLE。

您的愿望将传达给PG kernel hacker、数据库厂商等, 帮助提高数据库产品质量和功能, 说不定下一个PG版本就有您提出的功能点. 针对非常好的提议,奖励限量版PG文化衫、纪念品、贴纸、PG热门书籍等,奖品丰富,快来许愿。开不开森.

digoal's wechat