digoal
2019-03-28
PostgreSQL , EDB , ppas , epas , enterprisedb , 阿里云
对比社区版PostgreSQL, EDB EPAS, 其他PG商业版的Oracle兼容性。
EDB EPAS 支持,社区PG+orafce少量支持(不支持的部分需要改写SQL),其他PG商业版少量支持(不支持的部分需要改写SQL)。
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
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
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
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
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
create table t2 (c1 varchar2, c2 nvarchar2);
1、EDB EPAS
支持
2、其他PG商业版
支持
3、社区 pg 11 + orafce
支持
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
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
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
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
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)
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
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
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
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)
select count(distinct proname) from pg_proc ;
1、EDB EPAS
支持 3155 个
2、其他PG商业版
支持 2514 个
3、社区 pg 11 + orafce
支持 2775 个
postgres=# select * from dual;
dummy
-------
X
(1 row)
1、EDB EPAS
支持
2、其他PG商业版
支持
3、社区 pg 11 + orafce
支持
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
支持
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
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
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
select NVL(9, 0);
1、EDB EPAS
支持
2、其他PG商业版
支持
3、社区 pg 11 + orafce
支持
select nvl2(100,1,2);
1、EDB EPAS
支持
2、其他PG商业版
支持
3、社区 pg 11 + orafce
支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
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
不支持
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
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
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
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
select *,object_type from dba_objects where object_type='PACKAGE';
\dn
1、EDB EPAS
支持 26 种包
2、其他PG商业版
支持 2 种包
3、社区 pg 11 + orafce
支持 7 种包
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 种包内函数
CREATE DATABASE LINK local
CONNECT TO hr IDENTIFIED BY hr
USING 'local';
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
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 个系统视图
Pro*C
1、EDB EPAS
支持 , ecpgplus
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
OCL (OCI Support)
1、EDB EPAS
支持
2、其他PG商业版
不支持
3、社区 pg 11 + orafce
不支持
社区PG支持,ORACLE不支持的功能
Easy creation of specialized indexes.
空间、范围、向量、相似、图像等均可支持。
Custom inverted indexes.
倒排索引,与搜索引擎类似功能。
DDL可以封装到事务中,确保原子性。
《PostgreSQL leakproof function in rule rewrite("attack" security_barrier views)》
视图栅栏。
会话级,quorum based 同步复制。
《PostgreSQL 一主多从(多副本,强同步)简明手册 - 配置、压测、监控、切换、防脑裂、修复、0丢失 - 珍藏级》
1、ORACLE仅支持JAVA
2、PG支持非常多:
PL/pgSQL (PostgreSQL's Procedural Language)
PL/Java
C
C++
PL/Perl
Python
PL/Tcl
ORACLE支持,EDB以及社区PG不支持的功能
《PostgreSQL Oracle 兼容性 之 - 数据采样与脱敏》
EDB data redact
《PostgreSQL flashback(闪回) 功能实现与介绍》
《PostgreSQL 闪回 - flash back query emulate by trigger》
《PostgreSQL Oracle 兼容性之 - 事件触发器实现类似Oracle的回收站功能》
《PostgreSQL 回收站功能 - 基于HOOK的recycle bin pgtrashcan》
https://commitfest.postgresql.org/22/1283/
《PostgreSQL 普通表在线转换为分区表 - online exchange to partition table》
《PostgreSQL 收缩膨胀表或索引 - pg_squeeze or pg_repack》
EDB 未支持,其他PG商业版支持
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可以作为列名,并无冲突
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)
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
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里面
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
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
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
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语法解析器
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;
内核建议:改进语法解析器
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热门书籍等,奖品丰富,快来许愿。开不开森.