2016-06-09 4 views
0

다른 스키마의 동일한 테이블 (사용자)이 있습니다. 하나의 스키마 - 한 명의 임차인. 사용자에게 고유 한 이메일이 있습니다. 모든 스키마에서 전자 메일 필드를 고유하게 설정하는 방법은 무엇입니까?다중 스키마의 고유 요소

그리고 이것이 불가능할 경우, 하나의 hql 쿼리 당 다른 스키마의 모든 사용자를 얻을 수 있습니까?

+0

스키마 (또는 테이블에 걸쳐 고유 한 제한 조건이있을 수 있다고 생각하지 않지만 그 중 하나가 틀릴 수도 있습니다.)하지만 동일한 데이터베이스에서 스키마에 대한 전체 쿼리를 수행 할 수 있습니다. 스키마 테이블의 이름을 지정하면됩니다. –

답변

1

당신은 users 테이블을 포함하는 글로벌 스키마를 만들 수 있습니다. 그런 다음 각 테넌트 스키마에 대해 해당 테넌트와 관련된 사용자 만 선택하는보기를 만듭니다.

create schema global; 
create schema tenant1; 
create schema tenant2; 

create table global.users 
(
    id serial primary key, 
    tenant integer not null, 
    email varchar(254) not null unique, 
    ... other columns 
); 

create view tenant1.users 
as 
select id, email, ... --<<< don't select the tenant here! 
from global.users 
where tenant = 1 
with check option; 

create view tenant2.users 
as 
select id, email, ... --<<< don't select the tenant here! 
from global.users 
where tenant = 2 
with check option; 

뷰는 트리거없이 자동으로 업데이트 할 수 있습니다.

기본 테이블 뷰는 다른 데이터베이스 사용자가 소유해야하며 각 테넌트 스키마에는 다른 테이블이 있어야합니다. 그런 다음 "글로벌"사용자는 각 테넌트에 대해 사용 된 데이터베이스 사용자가 다른 테넌트의 데이터를 볼 수 없도록보기에서 선택, 삽입, 업데이트, 삭제 권한을 부여해야합니다.

+0

나는 아직도 질문이있다. 내 사용자 엔티티가 user_permission에 일대일 참여를 많이합니다. 사용자 { ID 이메일 목록 } : 그래서 한 사용자가 많은 권한을 가질 수 있습니다 : 관리자, 사용자 등 내가보기를 쓸 수있는 방법을,이 같은 걸릴 매핑 – DamienMiheev

1

많은 스키마에서 고유성을 보장하는 표준 기능은 없습니다. 다음 예제와 같은 공통 테이블을 사용하여이를 구현할 수 있습니다.

기존 표.

create trigger users_before_insert_or_update 
before insert or update on tenant1.users 
for each row execute procedure sys.email_trigger(); 

create trigger users_before_insert_or_update 
before insert or update on tenant2.users 
for each row execute procedure sys.email_trigger(); 

를 그리고 두 테이블에서 동일한 이메일을 삽입하려고 :

create schema sys; 

create table sys.emails (email text primary key); 

create or replace function sys.email_trigger() 
returns trigger language plpgsql as $$ 
begin 
    if tg_op = 'INSERT' then 
     insert into sys.emails 
     values (new.email); 
    elsif tg_op = 'UPDATE' then 
     update sys.emails 
     set email = new.email 
     where email = old.email; 
    end if; 
    return new; 
end $$; 

모든 users 테이블에 대한 트리거를 정의합니다

create schema tenant1; 
create schema tenant2; 
create table tenant1.users (email text); 
create table tenant2.users (email text); 

공통 테이블과 트리거에 대한 함수를 작성

insert into tenant1.users values ('[email protected]'); 
insert into tenant2.users values ('[email protected]'); 

ERROR: duplicate key value violates unique constraint "emails_pkey" 
DETAIL: Key (email)=([email protected]) already exists. 

전체 이름 테이블을 사용하여 하나의 쿼리에서 다른 스키마의 테이블에 액세스 할 수 있습니다. 모든 사용자를 나열하는 노동 조합을 사용

select * from tenant1.users 
union all 
select * from tenant2.users; 
+0

모두 노조와 함께 노력했지만 좀 더 역동적 인 것이 필요합니다. 왜냐하면 내가 앱을 실행할 때 얼마나 많은 스키마가 있는지 모르기 때문에 모든 스키마 이름을 가져 와서 파리에서 쿼리를 작성하기 위해 추가 논리를 추가해야하므로 이렇게하지 않아야합니다. 하지만 고마워. – DamienMiheev