Não, não está ok. Referências circulares entre tabelas são confusas. Veja este artigo (há uma década):SQL By Design:The Circular Reference
Alguns DBMS podem lidar com isso e com cuidado especial, mas o MySQL terá problemas.
Opção 1
Como seu projeto, para tornar um dos dois FKs anuláveis. Isso permite que você resolva o problema do ovo e da galinha (em qual tabela devo inserir primeiro?).
Porém, há um problema com seu código. Isso permitirá que um produto tenha uma imagem padrão onde essa imagem fará referência a outro produto!
Para não permitir tal erro, sua restrição FK deve ser:
CONSTRAINT FK_products_1
FOREIGN KEY (id, default_picture_id)
REFERENCES products_pictures (product_id, id)
ON DELETE RESTRICT --- the SET NULL options would
ON UPDATE RESTRICT --- lead to other issues
Isso exigirá um
UNIQUE
restrição/índice na tabela products_pictures
em (product_id, id)
para que o FK acima seja definido e funcione corretamente. Opção 2
Outra abordagem é remover o
Default_Picture_ID
coluna do product
table e adicione um IsDefault BIT
coluna na picture
tabela. O problema com esta solução é como permitir que apenas uma imagem por produto tenha esse bit e todas as outras o desativem. No SQL-Server (e acho que no Postgres) isso pode ser feito com um índice parcial:CREATE UNIQUE INDEX is_DefaultPicture
ON products_pictures (Product_ID)
WHERE IsDefault = 1 ;
Mas o MySQL não tem esse recurso.
Opção 3
Essa abordagem permite que você tenha as duas colunas FK definidas como
NOT NULL
é usar restrições adiáveis. Isso funciona no PostgreSQL e acho que no Oracle. Verifique esta pergunta e a resposta de @Erwin:Restrição de chave estrangeira complexa no SQLAlchemy
(as Todas as colunas-chave NÃO NULAS Papel). Restrições no MySQL não podem ser postergadas.
Opção 4
A abordagem (que acho mais limpa) é remover o
Default_Picture_ID
coluna e adicione outra tabela. Nenhum caminho circular nas restrições FK e todas as colunas FK serão NOT NULL
com esta solução:product_default_picture
----------------------
product_id NOT NULL
default_picture_id NOT NULL
PRIMARY KEY (product_id)
FOREIGN KEY (product_id, default_picture_id)
REFERENCES products_pictures (product_id, id)
Isso também exigirá um
UNIQUE
restrição/índice na tabela products_pictures
em (product_id, id)
como na solução 1. Para resumir, com o MySQL você tem duas opções:
-
opção 1 (uma coluna FK anulável) com a correção acima para impor a integridade corretamente
-
opção 4 (sem colunas FK anuláveis)