AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 17853
Accepted
ypercubeᵀᴹ
ypercubeᵀᴹ
Asked: 2012-05-15 15:02:25 +0800 CST2012-05-15 15:02:25 +0800 CST 2012-05-15 15:02:25 +0800 CST

Existem DBMS que permitem uma chave estrangeira que faz referência a uma exibição (e não apenas tabelas base)?

  • 772

Inspirado por uma questão de modelagem Django: Modelagem de banco de dados com múltiplas relações muitos-para-muitos em Django . O db-design é algo como:

CREATE TABLE Book
( BookID INT NOT NULL
, BookTitle VARCHAR(200) NOT NULL
, PRIMARY KEY (BookID)
) ;

CREATE TABLE Tag
( TagID INT NOT NULL
, TagName VARCHAR(50) NOT NULL
, PRIMARY KEY (TagID)
) ;

CREATE TABLE BookTag
( BookID INT NOT NULL
, TagID INT NOT NULL
, PRIMARY KEY (BookID, TagID)
, FOREIGN KEY (BookID)  REFERENCES Book (BookID)
, FOREIGN KEY (TagID)   REFERENCES Tag (TagID)
) ;

CREATE TABLE Aspect
( AspectID INT NOT NULL
, AspectName VARCHAR(50) NOT NULL
, PRIMARY KEY (AspectID)
) ;

CREATE TABLE TagAspect
( TagID INT NOT NULL
, AspectID INT NOT NULL
, PRIMARY KEY (TagID, AspectID) 
, FOREIGN KEY (TagID)   REFERENCES Tag (TagID)
, FOREIGN KEY (AspectID)  REFERENCES Aspect (AspectID)
) ;

diagrama db

e a questão é como definir a BookAspectRatingtabela e reforçar a integridade referencial, de modo que não se possa adicionar uma classificação para uma (Book, Aspect)combinação inválida.

CHECKAFAIK, restrições complexas (ou ASSERTIONS) que envolvem subconsultas e mais de uma tabela, que possivelmente poderiam resolver isso, não estão disponíveis em nenhum SGBD.

Outra ideia é usar (pseudocódigo) uma visão:

CREATE VIEW BookAspect_view
  AS
SELECT DISTINCT
    bt.BookId
  , ta.AspectId
FROM 
    BookTag AS bt
  JOIN 
    Tag AS t  ON t.TagID = bt.TagID
  JOIN 
    TagAspect AS ta  ON ta.TagID = bt.TagID 
WITH PRIMARY KEY (BookId, AspectId) ;

e uma tabela que possui uma Chave Estrangeira para a View acima:

CREATE TABLE BookAspectRating
( BookID INT NOT NULL
, AspectID INT NOT NULL
, PersonID INT NOT NULL
, Rating INT NOT NULL
, PRIMARY KEY (BookID, AspectID, PersonID)
, FOREIGN KEY (PersonID)   REFERENCES Person (PersonID)
, FOREIGN KEY (BookID, AspectID) 
    REFERENCES BookAspect_view (BookID, AspectID)
) ;

Três perguntas:

  • Existem DBMS que permitem um (possivelmente materializado) VIEWcom um PRIMARY KEY?

  • Existem SGBDs que permitem um FOREIGN KEYque REFERENCESum VIEW(e não apenas um base TABLE)?

  • Esse problema de integridade poderia ser resolvido de outra forma - com recursos de DBMS disponíveis?


Esclarecimento:

Já que provavelmente não existe uma solução 100% satisfatória - e a questão do Django nem é minha! - Estou mais interessado em uma estratégia geral de possível ataque ao problema, não em uma solução detalhada. Portanto, uma resposta como "no DBMS-X isso pode ser feito com triggers na tabela A" é perfeitamente aceitável.

database-design foreign-key
  • 5 5 respostas
  • 7402 Views

5 respostas

  • Voted
  1. Justin Cave
    2012-05-15T15:23:14+08:002012-05-15T15:23:14+08:00

    No Oracle, uma maneira de impor esse tipo de restrição de maneira declarativa seria criar uma visão materializada que é configurada para atualizar rapidamente na confirmação cuja consulta identifica todas as linhas inválidas (ou seja, BookAspectRatinglinhas que não correspondem a BookAspect_view). Você pode então criar uma restrição trivial nessa visão materializada que seria violada se houvesse alguma linha na visão materializada. Isso tem o benefício de minimizar a quantidade de dados que você precisa duplicar na visualização materializada. Isso pode causar problemas, no entanto, uma vez que a restrição só é aplicada no ponto em que você está confirmando a transação-- muitos aplicativos não são escritos para esperar que uma operação de confirmação possa falhar-- e porque a violação da restrição pode ser um pouco difícil para associar a uma linha ou tabela específica.

    • 10
  2. Best Answer
    A-K
    2012-05-16T08:08:55+08:002012-05-16T08:08:55+08:00

    Essa regra de negócios pode ser aplicada no modelo usando apenas restrições. A tabela a seguir deve resolver seu problema. Use-o em vez de sua exibição:

        CREATE TABLE BookAspectCommonTagLink
        (  BookID INT NOT NULL
        , AspectID INT NOT NULL
        , TagID INT NOT NULL
    --TagID is deliberately left out of PK
        , PRIMARY KEY (BookID, AspectID)
        , FOREIGN KEY (BookID, TagID) 
            REFERENCES BookTag (BookID, TagID)
        , FOREIGN KEY (AspectID, TagID) 
            REFERENCES AspectTag (AspectID, TagID)
        ) ;
    
    • 9
  3. Aaron Bertrand
    2012-05-15T15:14:19+08:002012-05-15T15:14:19+08:00

    Acho que você descobrirá que, em muitos casos, regras de negócios complexas não podem ser impostas apenas por meio do modelo. Este é um daqueles casos em que, pelo menos no SQL Server, acho que um gatilho (de preferência em vez de um gatilho) atende melhor ao seu propósito.

    • 8
  4. Erwin Smout
    2012-09-12T05:36:06+08:002012-09-12T05:36:06+08:00

    SIRA_PRISE permite isso.

    Embora o FK não seja mais chamado de "FK", mas apenas "restrição de banco de dados", e a "visualização" na verdade nem precise ser definida como uma exibição, você pode apenas incluir a expressão de definição de exibição dentro da declaração do restrição de banco de dados.

    Sua restrição seria algo como

    SEMIMINUS(BOOKASPECT , JOIN(BOOKTAG , TAGASPECT))
    

    e pronto.

    No entanto, na maioria dos DBMSs SQL, você teria que fazer o trabalho de análise em sua restrição, determinar como ela pode ser violada e implementar todos os gatilhos necessários.

    • 4
  5. dezso
    2012-05-16T00:11:53+08:002012-05-16T00:11:53+08:00

    No PostgreSQL, não consigo imaginar uma solução sem envolver gatilhos, mas certamente pode ser resolvido dessa forma (seja mantendo uma visão materializada de algum tipo ou um gatilho anterior em BookAspectRating). Não há chaves estrangeiras referenciando uma exibição ( ERROR: referenced relation "v_munkalap" is not a table), muito menos uma chave primária.

    • 3

relate perguntas

  • Os índices filtrados podem ajudar a melhorar as consultas baseadas em uma hora inserida ou isso deve ser evitado?

  • Qual é a diferença entre os tipos de dados MySQL VARCHAR e TEXT?

  • É melhor armazenar os valores calculados ou recalculá-los a pedido? [duplicado]

  • Armazenar vs calcular valores agregados

  • Quais são algumas maneiras de implementar um relacionamento muitos-para-muitos em um data warehouse?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve