Tenho uma tabela especificando tipos para distinguir entre escalares e listas. Quando existe "escalar" o valor é um escalar e quando é nulo é uma lista.
drop table type1 cascade;
create table type1 (
id integer primary key,
scalar "char",
name text,
unique (id, scalar)
);
insert into type1 values
(1, 'x', 'single'),
(2, null, 'multi');
Agora tenho uma tabela com valores, que faz referência ao tipo e adiciona uma restrição exclusiva à tupla (tipo, escalar). Isso funciona porque NULL é distinto. Se "escalar" for NULL é possível ter mais de uma linha por "tipo", pois todos os "escalares" são distintos.
drop table value1 cascade;
create table value1 (
id integer primary key,
type integer,
scalar "char",
value text,
foreign key (type, scalar) references type1 (id, scalar),
unique (type, scalar)
);
É possível inserir um único valor:
insert into value1 values
(11, 1, 'x', 'just one');
Mas não é possível adicionar outro:
insert into value1 values
(12, 1, 'x', 'another one'); -- ERROR
Mas se o escalar for NULL, é possível ter mais de um:
insert into value1 values
(21, 2, null, 'first'),
(22, 2, null, 'second');
Meu problema: é possível fazer referência a tipos que não existem.
Isso funciona, embora não devesse:
insert into value1 values
(12, 1, null, 'another');
É permitido usar (1, NULL) como tipo, embora na tabela de tipos estejam apenas (1, 'x') e (2, NULL).
Tentei usar match full
a chave estrangeira, mas parece fazer algo diferente. Impede também o uso pretendido de vários valores nulos, porque rejeita vários valores nulos.
Quero permitir vários NULLs se value1.scalar
for type1.scalar
NULL. Mas quero rejeitar qualquer NULL se value1.scalar
não type1.scalar
for NULL. Como posso expressar isso?
Você tem dois problemas separados:
unique
restriçãovalue1
é impor uma única linha por conjunto de(type, scalar)
, mas você deseja que os não escalares permitam múltiplos. Restrições exclusivas não permitem filtros. No entanto,você pode usar um índice exclusivo filtrado .....
where (scalar is not null)
MATCH SIMPLE
eMATCH FULL
não fazem o que querem. Você precisaMATCH PARTIAL
, mas isso ainda não foi implementado.Em vez disso, use um valor de sinalizador como
\x0
(o caractere NUL) para sinalizar um não escalar e tornar ascalar
coluna não anulável emtype1
.banco de dados<> violino