PostgreSql 中的表继承是否适合这种情况?

Lee*_*337 7 schema postgresql database-design

首先让我们说,我是 PSQL 的新手并且来自 MSSQL 背景。我开始在 PSQL 中设计一个数据库。

所以我的主要目标是在这个数据库中有一个主模式,我将用它来控制某些服务,并有多个模式链接到这个,这将是不同的客户端数据。

我已经阅读了表继承,但从来没有遇到过任何人使用继承的效果类似于 DB Migrations 的效果。我想要实现的基本上是有一个默认架构,客户端架构都继承自默认架构。这对我来说,只需更改一个模式,就可以控制创建/删除/更改所有模式的对象。

这可行吗?有没有其他人有过做类似事情的经验?有人有什么建议吗?

更新

这就是我所做的。但是,我的印象是,如果您查看下面的代码,我需要做的就是模式“client1”,但是我错了。:D

所以无论如何,下面是我所做的脚本,它应该处理我现在需要的一切 - 我将使用脚本作为“client2”模式。是好是坏?

-- public schema --
CREATE TABLE public.Users (
   Id bigserial primary key,
   Login text unique,
   check (false) NO INHERIT 
);

CREATE TABLE public.Roles (
   Id bigserial primary key,
   RoleName text unique,
   check (false) NO INHERIT 
);

CREATE TABLE public.UserRoles (
   Id bigserial primary key,
   UserId bigint references users(id),
   RoleId bigint references roles(id),
   unique (UserId, RoleId),
   check (false) NO INHERIT 
);


-- client1 schema --
CREATE TABLE client1.Users (
)
INHERITS(public.Users);

CREATE TABLE client1.Roles (
)
INHERITS(public.Roles);

CREATE TABLE client1.UserRoles (
)
INHERITS(public.UserRoles);


-- client2 schema --
CREATE TABLE client2.Users (
  primary key (id),
  Unique (Login)
)
INHERITS(public.Users);

CREATE TABLE client2.Roles (
  primary key (id),
  Unique (RoleName)
)
INHERITS(public.Roles);

CREATE TABLE client2.UserRoles (
  primary key (id),
  foreign key (UserId) REFERENCES client2.Users(id),
  foreign key (RoleId) REFERENCES client2.Roles(id),
  unique (UserId, RoleId)
)
INHERITS(public.UserRoles);
Run Code Online (Sandbox Code Playgroud)

Chr*_*ers 5

如果您注意到必须在每个子表上声明键和索引,那么这是可行的。

事实上,这非常接近表继承的理想用途。只需确保您熟悉陷阱,并密切关注用户模式中的外键创建。

需要注意的是,您不能将 CREATE 语句级联到所有模式中。这必须编写脚本。不过,您可以创建 plpgsql 函数来执行此操作。请注意,此类语句通常不会参数化,因此您需要根据需要使用 quote_ident() 和 quote_literal。

根据要求,这里有一个例子。在主架构中。请注意,此处的关键和唯一约束仅用于文档目的。

CREATE SCHEMA master;
SET SEARCH_PATH="master;

CREATE TABLE users (
   id bigserial not null unique,
   login text primary key,
   check (false) NO INHERIT -- 9.2 ONLY, prevents any rows in this table
);

CREATE TABLE roles (
   id bigserial not null unique,
   role_name text primary key,
   check (false) NO INHERIT -- 9.2 ONLY, prevents any rows in this table
);

CREATE TABLE user_roles (
   user_id bigint references users(id),
   role_id bigint references roles(id),
   primary key (user_id, role_id)
   check (false) NO INHERIT -- 9.2 ONLY, prevents any rows in this table
);

RESET SEARCH_PATH;
Run Code Online (Sandbox Code Playgroud)

当然,如果不是在 PostgreSQL 9.2 上,请删除检查约束,因为它们将在以前的版本中继承,然后任何表都不能有行。

然后在子模式中:

CREATE SCHEMA customer123;
SET SEARCH_PATH 'customer123';

CREATE TABLE users(unique (id), primary key(login)) INHERITS (master.users);
CREATE TABLE roles(unique (id), prikary key(role_name)) INHERITS (master.roles);
CREATE TABLE user_roles(
     foreign key users_id REFERENCES customer123.users(id),
     foreign key role_id REFERENCES customer123.roles(id),
     primary key (users_id, role_id)
);
RESET SEARCH_PATH; 
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,您必须仔细控制对主模式的访问,因为:

SELECT tableoid, login from master.users;
Run Code Online (Sandbox Code Playgroud)

为您提供每个租户的每个用户帐户以及足够的信息来确定它是哪个租户。