PostgreSQL Oracle 兼容性 - synonym 匿名

  1. 云栖社区>
  2. 阿里云数据库ApsaraDB>
  3. 博客>
  4. 正文

PostgreSQL Oracle 兼容性 - synonym 匿名

德哥 2017-10-28 23:13:15 浏览2280

标签

PostgreSQL , 匿名 , synonym


背景

Oracle 的一个功能,支持对其他对象建立别名(匿名:synonym),它有什么用呢?

比如某些业务系统中,代码中写死了要访问的对象是在哪个用户下的。当迁移时,如果遇到用户名冲突,我们可能会选择将对象同步到其他用户下。那么问题来了,程序也要改动,如果是很老的程序,估计找不到人来做这件事情。用synonym(匿名)可以很好的解决这个问题。

匿名语法如下

CREATE [ OR REPLACE ] [ PUBLIC ] SYNONYM  
   [ schema. ]synonym   
   FOR [ schema. ]object [ @ dblink ] ;  

https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7001.htm

对于状态可变的对象(例如表、序列)来说,匿名可以使用类似于指针引用的方法来实现。对于状态不可变的对象(例如函数、视图),匿名可以拷贝的方式来实现。实际上没有永久不变的东西,函数内容,视图的结构都是可能变化的。

下面给出一些例子,在PostgreSQL中如何实现synonym(非内核实现)。

PostgreSQL synonym的方法

我们可以对多种对象建立匿名,方法各异。

1、表

代码写死了b.tbl123:

create table a.tbl(id int);  

通过视图,

create view b.tbl123 as select * from a.tbl;  
  
这种简单视图,支持增删改查,和直接使用a.tbl是一样的。  
  
相当于建立了a.tbl的b.tbl123匿名。  

通过search_path,

如果对象名没变,只是在不同的schema下,使用search_path是最通用的方法:

set search_path=a,"$user",public;  
  
那么会先访问a这个schema下的对象。  

2、函数

代码写死了b.fun123:

create or replace function a.fun(int) returns int as $$  
....  
$$ language plpgsql strict;  

通过函数嵌套,

create or replace function b.fun123(int) returns int as $$  
select a.fun($1);  
$$ language sql strict;  

通过search_path,与1类似。

3、视图

通过视图,与1类似。

通过search_path

4、物化视图

通过视图,与1类似。

通过search_path,与1类似。

5、DBLINK

通过重定义一样的dblink。

通过search_path,与1类似。

6、外部表

通过视图,与1类似。

通过search_path,与1类似。

7、自定义类型

通过重定义一样的类型。

通过search_path,与1类似。

8、序列

如果名字改变,可以通过覆盖nextval,setval,currval来实现,例子

create or replace function nextval(name) returns int8 as $$  
declare  
  res int8;  
begin  
  if $1='目标seq对象名字' then  
    select pg_catalog.nextval('已存在seq对象'::regclass) into res;  
  else  
    select pg_catalog.nextval($1::regclass) into res;  
  end if;  
  return res;  
end;  
$$ language plpgsql strict;  
postgres=# select nextval('已存在seq对象');  
 nextval   
---------  
       1  
(1 row)  
  
postgres=# select nextval('目标seq对象名字');  
 nextval   
---------  
       2  
(1 row)  
  
postgres=# select nextval('已存在seq对象');  
 nextval   
---------  
       3  
(1 row)  

如果只是search_path的问题,通过search_path解决,与1方法类似。

内核实现

内核实现当然是最好的,很早以前社区有提过这样的PATCH,有兴趣的同学可以考虑把它port到PG最新的版本来。

https://www.postgresql.org/message-id/440D446E.7040509@cybertec.at

使用了类似HOOK的方法。