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 / 36698
Accepted
kevinskio
kevinskio
Asked: 2013-03-15 06:10:13 +0800 CST2013-03-15 06:10:13 +0800 CST 2013-03-15 06:10:13 +0800 CST

Imponha a integridade dos dados com uma tabela recursiva

  • 772

Eu tenho um esquema de banco de dados oracle 11g existente que funciona com um aplicativo da web. Estou planejando uma expansão para o aplicativo para que um serviço da Web possa fazer operações de dados no banco de dados. Como parte do planejamento, percebi que não há verificações de integridade de dados nas relações pai/filho, o que tornaria problemático permitir que outros aplicativos trabalhem com a tabela. Estou planejando fazer a validação no serviço da web, mas a melhor prática é ter validação no banco de dados e no serviço da web.

--the base lookup table has a table with text values that is not shown.
--Example Red, Green, 
CREATE TABLE PROPERTY
(
  ID                        NUMBER(9)           NOT NULL, --PRIMARY KEY
  TENANT_ID                 NUMBER(9)           NOT NULL
)
-- a property may or may not have a parent property. 
--Example "Weight" of an item is a child of the "Shipping Weight"
CREATE TABLE PROPERTY_DEPENDENCY  --PRIMARY KEY PROPERTY_ID,PROPERTY_TYPE_ID
(
  PROPERTY_ID               NUMBER(9)           NOT NULL,
  PARENT_PROPERTY_ID        NUMBER(9),
  PROPERTY_TYPE_ID          NUMBER(9)           NOT NULL,
  ACTIVE                    NUMBER(1)           NOT NULL
)
--examples "Item Colour", "Item Trim Colour","Shipping Weight", "Weight"
CREATE TABLE PROPERTY_TYPE
(
  ID                        NUMBER(9)           NOT NULL,  --PRIMARY KEY
  VALUE                     VARCHAR2(200 BYTE)  NOT NULL,
  PROPERTY_TYPE             NUMBER(10)          DEFAULT 1   NOT NULL
)

--and the table that you insert and update into
CREATE TABLE CASE_PROPERTY
(
  ID                        NUMBER(9)           NOT NULL, --PRIMARY KEY
  PARENT_ID                 NUMBER(9),          --constraint on PROPERTY
  CASE_ID                   NUMBER(9)           NOT NULL,--foreign key
  PROPERTY_ID               NUMBER(9),          --constraint on PROPERTY
  PROPERTY_TYPE_ID          NUMBER(9)           NOT NULL --constraint on PROPERTY_TYPE
)

Estes são os problemas que identifiquei:

  • você pode inserir em CASE_PROPERTY e tornar uma propriedade seu próprio pai ou avô
  • você pode inserir o PROPERTY_TYPE_ID errado para um PROPERTY_ID em CASE_PROPERTY
  • você pode inserir em CASE_PROPERTY um PARENT_ID que não faz sentido para um PROPERTY_TYPE_ID

Posso adicionar uma restrição de verificação para que PARENT_ID <> PROPERTY_IDvocê não possa ser pai de si mesmo.

Edição 3: O problema real é que as tabelas não são normalizadas corretamente, o que é ótimo para relatórios, mas difícil para validação de dados. CASE_PROPERTY.PROPERTY_TYPE_IDdeve ser sempre igual ao valor em PROPERTY_DEPENDENCY.PROPERTY_TYPE_IDmas não sei como validar isso.

Existem outras maneiras além de gatilhos para impor a integridade dos dados CASE_PROPERTY?

Editar: vou montar um exemplo completo. Se eu adicionasse restrições de chave estrangeira PROPERTY_DEPENDENCY, verificaria se apenas propriedades com pais foram inseridas, mas seriam os pais corretos?

Editar 2: Aqui está um exemplo completo das inserções permitidas. As duas últimas inserções são exemplos de dados que são permitidos, mas não deveriam ser.

ALTER TABLE CASE_PROPERTY ADD  CONSTRAINT CASE_PROPERTY_R01  FOREIGN
KEY (PARENT_ID)  REFERENCES CASE_PROPERTY (ID)  ENABLE  VALIDATE

Insert into PROPERTY    (ID, TENANT_ID)  Values    (2, 1); 
Insert into PROPERTY    (ID, TENANT_ID)  Values    (3, 1); 
Insert into PROPERTY    (ID, TENANT_ID)  Values    (4, 1); 

Insert into PROPERTY_TYPE    (ID, 
    VALUE, PROPERTY_TYPE)  Values    (10, 'Colour', 2);    
Insert into PROPERTY_TYPE    (ID, 
    VALUE, PROPERTY_TYPE)  Values    (11, 'Trim Colour', 1);    
Insert into PROPERTY_TYPE    (ID, 
    VALUE, PROPERTY_TYPE)  Values    (12, 'Shipping Weight', 1); 
Insert into PROPERTY_TYPE    (ID, 
    VALUE, PROPERTY_TYPE)  Values    (13, 'Weight', 3); 

Insert into PROPERTY_DEPENDENCY    (PROPERTY_ID, 
    PARENT_PROPERTY_ID, PROPERTY_TYPE_ID)  Values    (4, 3, 11); 
Insert into PROPERTY_DEPENDENCY    (PROPERTY_ID, 
    PARENT_PROPERTY_ID, PROPERTY_TYPE_ID)  Values    (3, NULL, 10);
Insert into PROPERTY_DEPENDENCY    (PROPERTY_ID, 
    PARENT_PROPERTY_ID, PROPERTY_TYPE_ID)  Values    (1, NULL, 12);    
Insert into PROPERTY_DEPENDENCY    (PROPERTY_ID, 
    PARENT_PROPERTY_ID, PROPERTY_TYPE_ID)  Values    (2, 1, 13); 

--example of a property validated data insert

--item 201 with type 13 is the child of item 200 of type 12
Insert into CASE_PROPERTY    (ID, 
    PARENT_ID, CASE_ID, PROPERTY_ID, PROPERTY_TYPE_ID)  Values    (200, NULL, 3000, 1, 12); 
Insert into CASE_PROPERTY    (ID, 
    PARENT_ID, CASE_ID, PROPERTY_ID, PROPERTY_TYPE_ID)  Values    (201, 200, 3000, 2, 13); 

--bad data inserts

-- a property is parent to itself with an incorrect property_type_id 

Insert into CASE_PROPERTY    (ID, 
    PARENT_ID, CASE_ID, PROPERTY_ID, PROPERTY_TYPE_ID)  Values    (202, 202, 4000, 3, 10);  
--should be 202, null,4000,3,10 

--a property is inserted with a parent that is not allowed 

Insert into CASE_PROPERTY    (ID, 
    PARENT_ID, CASE_ID, PROPERTY_ID, PROPERTY_TYPE_ID)  Values    (203, 200, 4000, 2, 13);  
--parent property should be 1 not 2
oracle database-design
  • 1 1 respostas
  • 1362 Views

1 respostas

  • Voted
  1. Best Answer
    Damir Sudarevic
    2013-03-16T09:25:38+08:002013-03-16T09:25:38+08:00

    Não sei se isso será útil para você porque requer algumas alterações, mas o problema é interessante, então vou tentar.

    Estas seriam as principais mudanças

    • Usando o fechamento da árvore em vez da lista de adjacência para a hierarquia de referência. A tabela de encerramento contém caminhos de cada pai para todos os seus descendentes, portanto, todas as combinações possíveis de pai-filho são expostas.

    Observe que, com o fechamento da árvore, cada nó ancestral aponta para si mesmo como um descendente, o que significa que a CasePropertyrecursão para em ID = ParentIDvez deParentID is NULL

    Não está claro para mim se um pai pode ser qualquer ancestral ou apenas o primeiro passo. A tabela de encerramento expõe o ancestral e todos os descendentes, portanto, Level Differenceé adicionado ao TreeClosure, que é subclassificado como AllowedCombospara LevelDifference in (0,1).

    • Propagando AK {PropertyID, PropertyTypeID} em vez de apenasPropertyID

    • Usando chave composta emCaseProperty


    insira a descrição da imagem aqui


    Aqui estão as principais restrições do modelo para esclarecer os relacionamentos (talvez seja necessário modificar a sintaxe)

    ALTER TABLE Property ADD
      CONSTRAINT PK_PR  PRIMARY KEY (PropertyID)
    
    , CONSTRAINT AK1_PR UNIQUE (PropertyID ,PropertyTypeID)
    
    , CONSTRAINT FK1_PR FOREIGN KEY (PropertyTypeID)
             REFERENCES PropertyType(PropertyTypeID)
    ;
    
    
    
    ALTER TABLE TreeClosure ADD
      CONSTRAINT PK_TC PRIMARY KEY (AncestorID ,DescendantID ,AncestorTypeID ,DescendantTypeID)
    
    , CONSTRAINT FK1_TC FOREIGN KEY (AncestorID ,AncestorTypeID) 
                 REFERENCES Property(PropertyID ,PropertyTypeID)
    
    , CONSTRAINT FK2_TC FOREIGN KEY (DescendantID ,DescendantTypeID)
                 REFERENCES Property(PropertyID   ,PropertyTypeID)
    ;
    
    
    
    ALTER TABLE CaseProperty ADD
      CONSTRAINT PK_CP PRIMARY KEY (CaseID, PropertyID, PropertyTypeID)
    
    , CONSTRAINT FK1_CP FOREIGN KEY (CaseID)
                     REFERENCES Case(CaseID)
    
    , CONSTRAINT FK2_CP FOREIGN KEY (PropertyID ,PropertyTypeID)
                 REFERENCES Property(PropertyID ,PropertyTypeID)
    
    , CONSTRAINT FK4_CP FOREIGN KEY (ParentCaseID ,ParentPropertyID ,ParentPropertyTypeID)
             REFERENCES CaseProperty(CaseID       ,PropertyID       ,PropertyTypeID)
    
    , CONSTRAINT FK5_CP FOREIGN KEY (ParentPropertyID ,PropertyID   , ParentPropertyTypeID ,PropertyTypeID) 
            REFERENCES AllowedCombos(AncestorID       ,DescendantID , AncestorTypeID       ,DescendantTypeID)
    
    ;
    
    • 3

relate perguntas

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

  • ORDER BY usando prioridades personalizadas para colunas de texto

  • Interface sqlplus confortável? [fechado]

  • Como encontrar as instruções SQL mais recentes no banco de dados?

  • Como posso consultar nomes usando expressões regulares?

Sidebar

Stats

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

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Conceder acesso a todas as tabelas para um usuário

    • 5 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 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

    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
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • 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

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