Gerenciando uma informação individual
Supondo que, no seu domínio comercial,
- um usuário pode ter zero ou um ou muitos amigos ;
- um amigo deve primeiro ser registrado como um usuário ; e
- você pesquisará e / ou adicionará, e / ou removerá e / ou modificará valores únicos de uma Lista de Amigos ;
em seguida, cada um datum específico reunidos na Friendlist_IDs
coluna de valor múltiplo representa um pedaço de informação que carrega um significado muito exata. Portanto, a referida coluna
- implica um grupo adequado de restrições explícitas e
- seus valores têm o potencial de serem manipulados individualmente por meio de várias operações relacionais (ou combinações das mesmas).
Resposta curta
Conseqüentemente, você deve reter cada um dos Friendlist_IDs
valores em (a) uma coluna que aceita exclusivamente um único valor por linha em (b) uma tabela que represente o tipo de associação em nível conceitual que pode ocorrer entre os Usuários , ou seja, uma Amizade - como Vou exemplificar nas seções a seguir.
Dessa forma, você será capaz de lidar com (i) a referida tabela como uma relação matemática e (ii) a referida coluna como um atributo da relação matemática - tanto quanto o MySQL e seu dialeto SQL permitirem, é claro -.
Por quê?
Como o modelo relacional de dados , criado pelo Dr. E. F. Codd , exige ter tabelas compostas de colunas que contêm exatamente um valor do domínio ou tipo aplicável por linha; portanto, declarar uma tabela com uma coluna que pode conter mais de um valor do domínio ou tipo em questão (1) não representa uma relação matemática e (2) não permitiria obter as vantagens propostas no referencial teórico acima mencionado.
Modelando amizades entre usuários : definindo primeiro as regras do ambiente de negócios
Eu recomendo começar a modelar um banco de dados delimitando - antes de mais nada - o esquema conceitual correspondente em virtude da definição das regras de negócios relevantes que, entre outros fatores, devem descrever os tipos de inter-relações existentes entre os diferentes aspectos de interesse, ou seja, , os tipos de entidade aplicáveis e suas propriedades ; por exemplo:
- Um usuário é identificado principalmente por seu UserId
- Um usuário é identificado alternadamente pela combinação de seu nome , sobrenome , sexo e data de nascimento
- Um usuário é identificado alternadamente por seu nome de usuário
- Um usuário é o solicitante de zero ou uma ou muitas amizades
- Um usuário é o destinatário de zero ou uma ou muitas amizades
- Uma amizade é identificada principalmente pela combinação de seu RequesterId e seu AddresseeId
Diagrama do IDEF1X expositivo
Dessa maneira, consegui derivar o diagrama IDEF1X 1 mostrado na Figura 1 , que integra a maioria das regras formuladas anteriormente:
Conforme representado, Solicitante e Destinatário são denotações que expressam as Funções desempenhadas pelos Usuários específicos que participam de uma determinada Amizade .
Sendo assim, o tipo de entidade Amizade retrata um tipo de associação da proporção de cardinalidade muitos para muitos (M: N) que pode envolver ocorrências diferentes do mesmo tipo de entidade, ou seja, Usuário . Como tal, é um exemplo do construto clássico conhecido como "Lista de materiais" ou "Explosão de peças".
1 Definição de Integração para Modelagem de Informações ( IDEF1X ) é uma técnica altamente recomendável que foi estabelecida como padrão em dezembro de 1993 pelo Instituto Nacional de Padrões e Tecnologia dos EUA (NIST). É solidamente baseado em (a) o material teórico inicial criado pelo único autordo modelo relacional, ou seja, Dr. EF Codd ; (b) avisão de dados entre entidades e relacionamentos , desenvolvida pelo Dr. PP Chen ; e também (c) a Logical Database Design Technique, criada por Robert G. Brown.
Projeto lógico SQL-DDL ilustrativo
Então, a partir do diagrama IDEF1X apresentado acima, declarar um arranjo DDL como o que se segue é muito mais "natural":
-- You should determine which are the most fitting
-- data types and sizes for all the table columns
-- depending on your business context characteristics.
-- At the physical level, you should make accurate tests
-- to define the mostconvenient INDEX strategies based on
-- the pertinent query tendencies.
-- As one would expect, you are free to make use of
-- your preferred (or required) naming conventions.
CREATE TABLE UserProfile ( -- Represents an independent entity type.
UserId INT NOT NULL,
FirstName CHAR(30) NOT NULL,
LastName CHAR(30) NOT NULL,
BirthDate DATE NOT NULL,
GenderCode CHAR(3) NOT NULL,
Username CHAR(20) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT UserProfile_PK PRIMARY KEY (UserId),
CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
FirstName,
LastName,
GenderCode,
BirthDate
),
CONSTRAINT UserProfile_AK2 UNIQUE (Username) -- Single-column ALTERNATE KEY.
);
CREATE TABLE Friendship ( -- Stands for an associative entity type.
RequesterId INT NOT NULL,
AddresseeId INT NOT NULL, -- Fixed with a well-delimited data type.
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Friendship_PK PRIMARY KEY (RequesterId, AddresseeId), -- Composite PRIMARY KEY.
CONSTRAINT FriendshipToRequester_FK FOREIGN KEY (RequesterId)
REFERENCES UserProfile (UserId),
CONSTRAINT FriendshipToAddressee_FK FOREIGN KEY (AddresseeId)
REFERENCES UserProfile (UserId)
);
Desta forma:
- cada tabela base representa um tipo de entidade individual;
- cada coluna representa uma única propriedade do respectivo tipo de entidade;
- um específico tipo de dados que um é fixo em cada coluna , a fim de garantir que todos os valores que contém pertencem a uma específica e bem definida conjunto , seja INT, DATETIME, CHAR, etc .; e
- várias restrições b são configuradas (declarativamente) para garantir que as asserções na forma de linhas retidas em todas as tabelas atendam às regras de negócios determinadas no esquema conceitual.
Vantagens de uma coluna de valor único
Como demonstrado, você pode, por exemplo:
Aproveite a integridade referencial imposta pelo sistema de gerenciamento de banco de dados (DBMS por brevidade) para a Friendship.AddresseeId
coluna, pois a restrição como uma FOREIGN KEY (FK por brevidade) que faz uma referência à UserProfile.UserId
coluna garante que todo valor aponte para uma linha existente .
Criar um composto chave primária (PK) composta da combinação de colunas (Friendship.RequesterId, Friendship.AddresseeId)
, ajudando a elegantemente distinguir todas as linhas inseridas e, naturalmente, proteger a sua singularidade .
Obviamente, isso significa que o anexo de uma coluna extra para valores substitutos atribuídos pelo sistema (por exemplo, um configurado com a propriedade IDENTITY no Microsoft SQL Server ou com o atributo AUTO_INCREMENT no MySQL) e o INDEX auxiliar são totalmente supérfluos .
Restrinja os valores retidos Friendship.AddresseeId
para um tipo de dados preciso c (que deve corresponder, por exemplo, ao estabelecido para UserProfile.UserId
, neste caso, INT), permitindo que o DBMS cuide da validação automática pertinente .
Esse fator também pode ajudar a (a) utilizar as funções do tipo interno correspondentes e (b) otimizar o uso do espaço em disco .
Otimize a recuperação de dados no nível físico, configurando INDEXes subordinados pequenos e rápidos para a Friendship.AddresseeId
coluna, pois esses elementos físicos podem ajudar substancialmente a acelerar as consultas que envolvem a coluna.
Certamente, você pode, por exemplo, colocar um INDEX de coluna única Friendship.AddresseeId
apenas, um de coluna múltipla que inclua Friendship.RequesterId
e Friendship.AddresseeId
, ou ambos.
Evite a complexidade desnecessária introduzida pela “pesquisa” de valores distintos que são coletados na mesma coluna (provavelmente duplicados, digitados incorretamente etc.), um curso de ação que acabaria por retardar o funcionamento do seu sistema, porque você precisa recorrer a métodos não relacionais que consomem recursos e tempo para realizar a tarefa.
Portanto, há vários motivos que exigem a análise cuidadosa do ambiente de negócios relevante para marcar com precisão o tipo d de cada coluna da tabela.
Conforme exposto, o papel desempenhado pelo criador do banco de dados é primordial para fazer o melhor uso (1) dos benefícios de nível lógico oferecidos pelo modelo relacional e (2) dos mecanismos físicos fornecidos pelo DBMS de sua escolha.
a , b , c , d Evidentemente, ao trabalhar com plataformas SQL (por exemplo, Firebird e PostgreSQL ) que suportam a criação de DOMAIN (umrecurso relacional distinto), você pode declarar colunas que aceitam apenas valores que pertencem a seus respectivos compartilhado) DOMAINs.
Um ou mais programas aplicativos que compartilham o banco de dados em consideração
Quando você precisar empregar arrays
o código do (s) programa (s) aplicativo (s) acessando o banco de dados, basta recuperar o (s) conjunto (s) de dados relevante (s) na íntegra e, em seguida, "vinculá-lo (s) à estrutura de código relacionada ou executar o processo (s) de aplicativos associado (s) que devem ocorrer.
Benefícios adicionais de colunas com valor único: as extensões da estrutura do banco de dados são muito mais fáceis
Outra vantagem de manter o AddresseeId
ponto de dados em sua coluna reservada e com o tipo correto é que ele facilita consideravelmente a extensão da estrutura do banco de dados, como exemplificarei abaixo.
Progressão do cenário: Incorporando o conceito Status da Amizade
Como as Amizades podem evoluir ao longo do tempo, talvez seja necessário acompanhar esse fenômeno; portanto, você deverá (i) expandir o esquema conceitual e (ii) declarar mais algumas tabelas no layout lógico. Portanto, vamos organizar as próximas regras de negócios para delinear as novas incorporações:
- Uma Amizade mantém um para muitos Estatutos de Amizade
- Um FriendshipStatus é identificado principalmente pela combinação de RequesterId , AddresseeId e SpecifiedDateTime
- Um usuário especifica zero-um-ou-muitos FriendshipStatuses
- Um Status classifica zero-um-ou-muitos FriendshipStatuses
- Um Status é identificado principalmente por seu StatusCode
- Um status é alternadamente identificado por seu nome
Diagrama IDEF1X estendido
Sucessivamente, o diagrama IDEF1X anterior pode ser estendido para incluir os novos tipos de entidade e tipos de inter-relacionamento descritos acima. Um diagrama representando os elementos anteriores associados aos novos é apresentado na Figura 2 :
Adições à estrutura lógica
Posteriormente, podemos prolongar o layout DDL com as seguintes declarações:
--
CREATE TABLE MyStatus ( -- Denotes an independent entity type.
StatusCode CHAR(1) NOT NULL,
Name CHAR(30) NOT NULL,
--
CONSTRAINT MyStatus_PK PRIMARY KEY (StatusCode),
CONSTRAINT MyStatus_AK UNIQUE (Name) -- ALTERNATE KEY.
);
CREATE TABLE FriendshipStatus ( -- Represents an associative entity type.
RequesterId INT NOT NULL,
AddresseeId INT NOT NULL,
SpecifiedDateTime DATETIME NOT NULL,
StatusCode CHAR(1) NOT NULL,
SpecifierId INT NOT NULL,
--
CONSTRAINT FriendshipStatus_PK PRIMARY KEY (RequesterId, AddresseeId, SpecifiedDateTime), -- Composite PRIMARY KEY.
CONSTRAINT FriendshipStatusToFriendship_FK FOREIGN KEY (RequesterId, AddresseeId)
REFERENCES Friendship (RequesterId, AddresseeId), -- Composite FOREIGN KEY.
CONSTRAINT FriendshipStatusToMyStatus_FK FOREIGN KEY (StatusCode)
REFERENCES MyStatus (StatusCode),
CONSTRAINT FriendshipStatusToSpecifier_FK FOREIGN KEY (SpecifierId)
REFERENCES UserProfile (UserId)
);
Consequentemente, toda vez que o status de uma determinada amizade precisar ser atualizado, os usuários precisarão apenas INSERIR uma nova FriendshipStatus
linha, contendo:
o adequado RequesterId
e os AddresseeId
valores - retirados da linha em questão - Friendship
;
o novo e significativo StatusCode
valor - retirado de MyStatus.StatusCode
-;
o instante exato da INSERÇÃO, ou seja, - de SpecifiedDateTime
preferência , usando uma função de servidor para que você possa recuperá-la e retê-la de maneira confiável -; e
o SpecifierId
valor que indicaria o respectivo UserId
que inseriu o novo FriendshipStatus
no sistema - idealmente, com a ajuda dos recursos de seus aplicativos -.
Nessa medida, suponhamos que a MyStatus
tabela inclui os seguintes dados -com valores de PK que são (a) pelo usuário final, app programmer- e amigável-DBA e (b) pequena e rápida em termos de bytes no físico nível de implementação -:
+ -—————————- + -————————— +
| StatusCode | nome |
+ -—————————- + -————————— +
| R Solicitado |
+ ------------ + ----------- +
| A Aceito |
+ ------------ + ----------- +
| D Recusado |
+ ------------ + ----------- +
| B Bloqueado |
+ ------------ + ----------- +
Portanto, a FriendshipStatus
tabela pode conter dados como mostrado abaixo:
+ -——————————- + -——————————- + -——————————————— ———- + -—————————- + -—————————— +
| RequesterId | AddresseeId | SpecifiedDateTime | StatusCode | SpecifierId |
+ -——————————- + -——————————- + -——————————————— ———- + -—————————- + -—————————— +
| 1750 1748 01-04-2016 16: 58: 12.000 | R 1750
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 1748 02-04-2016 09: 12: 05.000 | A 1748
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 1748 04-04-2016 10: 57: 01.000 | B 1750
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 1748 07-04-2016 07: 33: 08.000 | R 1748
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 1748 08-04-2016 12: 12: 09.000 | A 1750
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
Como você pode ver, pode-se dizer que a FriendshipStatus
tabela serve para o propósito de compreender uma série temporal .
Postagens relevantes
Você também pode estar interessado em:
- Esta resposta, na qual sugiro um método básico para lidar com um relacionamento muitos-para-muitos comum entre dois tipos de entidades diferentes.
- O diagrama IDEF1X mostrado na Figura 1 que ilustra essa outra resposta . Preste atenção especial aos tipos de entidade denominados Casamento e Progênie , porque são mais dois exemplos de como lidar com o "Problema de explosão de peças".
- Este post que apresenta uma breve deliberação sobre a retenção de diferentes informações em uma única coluna.