Por que o modelo relacional de um banco de dados é importante?


61

Estou abordando um projeto em que terei que implementar um banco de dados com meu chefe; somos uma startup muito pequena, portanto o ambiente de trabalho é profundamente pessoal.

Ele havia me dado um dos bancos de dados da empresa antes e isso foi totalmente contra o que eu aprendi (e li sobre) na escola para RDBMS. Por exemplo, existem bancos de dados inteiros aqui que consistem em uma tabela (por banco de dados independente). Uma dessas tabelas tem mais de 20 colunas e, para o contexto, aqui estão alguns dos nomes de colunas de uma tabela:

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngProductID | vrProductName

O ponto é que, onde ele deve ter tabelas individuais que contêm os dados da entidade (nome, tamanho, data da compra, etc.), ele coloca tudo em uma tabela grande por banco de dados.

Desejo melhorar esse design, mas não sei por que um modelo de dados segmentado e normalizado adequadamente realmente melhoraria esse produto. Embora eu esteja familiarizado com o design de banco de dados da faculdade e entenda como fazê-lo, não sei por que isso realmente melhora os bancos de dados.

Por que um bom esquema relacional melhora um banco de dados?


33
Uma palavra: Normalização.
26716 Robert Harvey

9
Fechar eleitor - justifique-se! :-)
Robbie Dee

6
É comum que novos funcionários critiquem procedimentos estabelecidos sem entender os motivos por trás deles, mesmo que esses motivos não sejam tecnicamente sólidos. Primeiro, descubra por que seu chefe a construiu dessa maneira. Ele / ela pode muito bem saber que não é um bom design, mas não tem conhecimento (ou mais provavelmente, tempo) para fazê-lo melhor. Qualquer alteração que você propor provavelmente será recebida de maneira mais positiva se você reconhecer respeitosamente os motivos do design atual.
Pedro

5
He [the boss] had given me one of his databases before and it completely went against what I was taught (and read about) in school for RDBMS<- Bem-vindo ao mundo real!
Möoz

5
Lembro-me de minha citação favorita banco de dados relacional: "normalizar até ele fere, desnormalizar til funciona"
Jake

Respostas:


70

O argumento de desempenho é geralmente o mais intuitivo. Você deseja destacar especialmente como será difícil adicionar bons índices em um banco de dados normalizado incorretamente (nota: há casos extremos em que a desnormalização pode de fato melhorar o desempenho, mas quando você não tem experiência com bancos de dados relacionais, provavelmente não conseguirá facilmente veja esses casos).

Outro é o argumento do tamanho do armazenamento. Uma tabela desnormalizada com muitas redundâncias exigirá muito mais armazenamento. Isso também afeta o aspecto do desempenho: quanto mais dados você tiver, mais lentas serão as suas consultas.

Há também um argumento que é um pouco mais difícil de entender, mas é de fato mais importante porque você não pode resolvê-lo jogando mais hardware nele. Esse é o problema da consistência dos dados. Um banco de dados normalizado adequadamente cuidará por si só de que um produto com um ID específico sempre tenha o mesmo nome. Porém, em um banco de dados desnormalizado, essas inconsistências são possíveis; portanto, é necessário um cuidado especial para evitar inconsistências, o que levará tempo de programação para corrigir e ainda causará bugs que custarão a satisfação do cliente.


19
Um dos principais casos de desnormalização é o armazenamento de dados , especificamente, se você tiver uma grande quantidade de dados que nunca será alterada e desejar consultá-los com mais rapidez e eficiência, à custa do espaço de armazenamento. Boa resposta, este é apenas um FYI para qualquer iniciante em SQL que não saiba ao certo por que algo diferente de 3NF seria desejável.


11
Não sei por que o argumento da consistência é "mais difícil de entender". Parece-me muito mais simples: se um valor mudar, todas as cópias desse valor deverão ser atualizadas. Atualizar uma única cópia é muito menos suscetível a erros do que atualizar centenas ou milhares de cópias dos mesmos dados. Isso se aplica igualmente bem aos relacionamentos entre dados. (Se eu tiver o relacionamento armazenado de duas maneiras, preciso atualizar as duas cópias do relacionamento.) Esse é um problema extremamente comum em bancos de dados desnormalizados; é muito difícil evitar essa corrupção na prática (uma exceção é o uso do tipo de exibição materializado).
precisa saber é o seguinte

4
Esse último parágrafo deve ser destacado em negrito. :-) Sem normalização, é impossível garantir a integridade dos dados. Controlar a entrada exclusivamente na camada Business Logic é uma tarefa fácil, pois todo banco de dados não normalizado exibe algum tipo de anomalia de dados.
Dank

2
A prática usual do @IsmaelMiguel é que dados mestre como esse nunca sejam excluídos do banco de dados. Você o exclui apenas definindo um sinalizador que diz que não está mais disponível. Nesse caso específico, seria uma boa idéia ter um relacionamento de chave estrangeira entre produtos e pedidos, o que significa que o banco de dados emitirá um erro quando você tentar excluir um produto referenciado por qualquer pedido.
Philipp

24

Vou ter que implementar um banco de dados com meu chefe ...

Usar o software dedicado de Gerenciamento de Banco de Dados pode ser consideravelmente mais fácil (desculpe; não pude resistir).

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngProductID | vrProductName

Se esse banco de dados se importar apenas com o "registro" de qual produto foi vendido, onde, quando e por quem, você poderá estender a definição de "banco de dados OK" o suficiente para cobri-lo. Se esses dados estiverem sendo usados ​​para qualquer outra coisa , serão realmente muito ruins.

Mas ...

O aplicativo / consultas usando esses dados responde mal / lentamente? Caso contrário, não há problema real a ser resolvido. Claro, parece feio, mas se funcionar , você não receberá "pontos" por sugerir que "poderia" ser melhor.

Se você encontrar sintomas definidos (ou seja, problemas) que parecem causados ​​por uma modelagem de dados deficiente, protótipo de uma solução melhor. Faça uma cópia de um desses "bancos de dados", normalize os dados e veja se sua solução funciona melhor. Se for consideravelmente melhor (e eu esperaria plenamente que qualquer operação de atualização nesses dados fosse massivamente aprimorada), volte para o seu chefe e mostre a eles a melhoria.

É perfeitamente possível recriar sua "exibição de tabela única" dos dados com ... bem ... visualizações.


11
A resistência à tabela única weltanschauung geralmente vem daqueles inexperientes com SQL que não entendem junções - especialmente no que diz respeito à falta de dados, ou seja, junções externas.
Robbie Dee

6
@RobbieDee Mais comumente, é de pessoas que viram dados desnormalizados serem corrompidos ao se tornarem inconsistentes. Eu sou uma dessas pessoas. Eu consideraria apenas esse tipo de estrutura na situação que Phill sugere: este é um tipo de tabela de registro / relatório em que os dados nunca serão atualizados ou apenas atualizados por serem limpos e completamente derivados de outras fontes.
precisa saber é o seguinte

2
Mesmo que o aplicativo tenha um desempenho aceitável em um banco de dados como esse, ele ainda não é flexível como um banco de dados normalizado corretamente. Se o nome da loja ou o nome da empresa mudar, ele deverá ser atualizado em todos os lugares, em vez de apenas em uma tabela de loja ou empresa. Em alguns casos, isso pode realmente ser o que você deseja (como se os dados fossem coletados principalmente para fins de arquivamento), mas precisaríamos saber mais sobre o aplicativo específico.
Zach Lipton

1
@ Zach: concordou, é por isso que o registro de vendas é potencialmente um caso aceitável para isso. Supondo que você queira que cada venda seja associada a qualquer que seja o nome da loja no momento em que a venda foi feita, não "o nome atual da loja", e tentar "normalizar" isso introduz uma complexidade considerável (porque a tabela registra os nomes das lojas seria necessário uma série ao longo do tempo, e não apenas um valor por storeid)
Steve Jessop

Talvez uma regra prática seja que, se a única complexidade introduzida por uma normalização proposta é que agora algumas consultas precisem se juntar a elas para selecionar todas as colunas que precisam relatar, então você deve executar não caminhar para fazer essa alteração: - )
Steve Jessop

14

Por que um bom esquema relacional melhora um banco de dados?

A resposta é: nem sempre melhora um banco de dados. Você deve estar ciente de que o que você provavelmente aprendeu é chamado Terceira Forma Normal .

Outros formulários são válidos em algumas situações, o que é essencial para responder à sua pergunta. Seu exemplo se parece com o Primeiro formulário normal , se isso ajudar você a se sentir melhor sobre o estado atual.

As regras 3NF estabelecem relações entre dados que "melhoram" um banco de dados:

  1. Impedir a entrada de dados inválidos no sistema (se um relacionamento for 1 para 1, isso força um erro, apesar do código escrito em cima dele). Se seus dados forem consistentes no banco de dados, é menos provável que resulte em inconsistências fora do banco de dados.

  2. Ele fornece uma maneira de validar o código (por exemplo, um relacionamento muitos-para-um é um sinal para restringir as propriedades / comportamentos de um objeto). Ao escrever código para usar o banco de dados, às vezes os programadores percebem a estrutura de dados como um indicador de como o código deve funcionar. Ou eles podem fornecer feedback útil se o banco de dados não corresponder ao código. (Isso é mais como uma ilusão, infelizmente.)

  3. Forneça regras que possam ajudar significativamente a reduzir erros ao criar um banco de dados, para que você não o construa com base em requisitos arbitrários que possam surgir a qualquer momento durante a vida de um banco de dados. Em vez disso, você está avaliando sistematicamente as informações para atingir objetivos específicos.

  4. Estruturas de banco de dados adequadas levam a um desempenho aprimorado, conectando os dados de maneira a minimizar o armazenamento de dados, minimizar as chamadas de armazenamento para recuperar dados, maximizar os recursos na memória e / ou minimizar a classificação / manipulação de dados para o conjunto de dados específico que você possui, em comparação com a consulta que você está executando contra ele. Mas a estrutura "adequada" depende da quantidade de dados, natureza dos dados, tipo de consulta, recursos do sistema etc. Ao normalizar, você pode piorar o desempenho (ou seja, se você carregar todos os dados como uma tabela), a junção pode desacelerar uma consulta). O processamento de transações (OLTP) vs business intelligence (data warehouse) são muito diferentes.

Em uma empresa pequena com conjuntos de dados pequenos, você pode descobrir que não há nada errado com o que está ocorrendo agora. Exceto que, se você crescer, será difícil "consertar" mais tarde, porque, à medida que a tabela aumenta, os sistemas que a utilizam provavelmente serão mais lentos.

Geralmente, você deseja enfatizar transações rápidas à medida que a empresa cresce. No entanto, se você dedicar tempo a esse projeto agora, em vez de outras coisas que a empresa possa precisar com mais urgência, talvez nunca tenha esse problema, porque sua empresa nunca realmente cresce. Esse é o "desafio da pré-otimização" - onde gastar seu precioso tempo agora.

Boa sorte!


4
Não mencionado, mas acho que um ponto importante para os programadores é que editar uma "coisa" requer a edição de apenas uma única linha, em vez de ter que fazer um loop em todo o banco de dados para encontrar e substituir essa coisa.
precisa saber é

@slebetman Você nunca deve ter um loop do lado do código para atualizar várias linhas em uma única tabela, independentemente de estar normalizado. Use uma WHEREcláusula Obviamente, eles ainda podem dar errado, mas é menos provável em uma situação normalizada, pois você só precisa corresponder uma linha via chave primária.
jpmc26

@ jpmc26: Ao fazer um loop no banco de dados, quero dizer construir uma consulta para atualizar todas as linhas afetadas. Às vezes, um único WHERE é suficiente. Mas já vi estruturas profanas que exigem sub-seleções na mesma tabela para obter todas as linhas afetadas sem afetar as linhas que não devem mudar. Eu mesmo vi estruturas onde uma única consulta não pode fazer o trabalho (a entidade que precisa de mudança reside em colunas diferentes dependendo de linha)
slebetman

Muitas excelentes respostas para essa pergunta, e isso não foi exceção.
amigos estão

11

Existem várias razões pelas quais o uso de uma grande "mesa divina" é ruim. Vou tentar ilustrar os problemas com um banco de dados de exemplo inventado. Vamos supor que você esteja tentando modelar eventos esportivos. Diremos que você deseja modelar jogos e as equipes que jogam nesses jogos. Um design com várias tabelas pode se parecer com isso (isso é muito simplista de propósito, portanto, não seja pego em locais onde mais normalização possa ser aplicada):

Teams
Id | Name | HomeCity

Games
Id | StartsAt | HomeTeamId | AwayTeamId | Location

e um banco de dados de tabela única ficaria assim

TeamsAndGames
Id | TeamName | TeamHomeCity | GameStartsAt | GameHomeTeamId | GameAwayTeamId | Location

Primeiro, vejamos como criar índices nessas tabelas. Se eu precisasse de um índice na cidade natal para uma equipe, poderia adicioná-lo à Teamsmesa ou à TeamsAndGamesmesa com bastante facilidade. Lembre-se de que sempre que você cria um índice, ele precisa ser armazenado no disco em algum lugar e atualizado à medida que as linhas são adicionadas à tabela. No caso da Teamstabela, isso é bastante direto. Coloquei uma nova equipe, o banco de dados atualiza o índice. Mas e para TeamsAndGamesquê? Bem, o mesmo se aplica a partir doTeamsexemplo. Eu adiciono uma equipe, o índice é atualizado. Mas também acontece quando adiciono um jogo! Mesmo que esse campo seja nulo para um jogo, o índice ainda precisa ser atualizado e armazenado em disco para esse jogo. Para um índice, isso não parece muito ruim. Mas quando você precisa de muitos índices para as várias entidades amontoadas nesta tabela, você perde muito espaço armazenando os índices e muito tempo do processador atualizando-os para itens onde eles não se aplicam.

Segundo, consistência dos dados. No caso de usar duas mesas separadas, posso usar chaves estrangeiras Gamesda Teamsmesa para definir quais times estão jogando em um jogo. E, assumindo que as colunas HomeTeamIde AwayTeamIdnão são anuláveis, o banco de dados garantirá que todos os jogos que eu participe tenham 2 equipes e que essas equipes existam no meu banco de dados. Mas e o cenário de tabela única? Bem, como existem várias entidades nesta tabela, essas colunas devem ser anuláveis ​​(você pode torná-las não anuláveis ​​e colocar dados de lixo nela, mas isso é apenas uma ideia horrível). Se essas colunas forem anuláveis, o banco de dados não poderá mais garantir que, quando você insere um jogo, ele possui duas equipes.

Mas e se você decidir fazer isso de qualquer maneira? Você configura as chaves estrangeiras de modo que esses campos aponte para outra entidade na mesma tabela. Mas agora o banco de dados apenas garantirá que essas entidades existam na tabela, não que sejam do tipo correto. Você pode facilmente definir GameHomeTeamIdo ID de outro jogo e o banco de dados não irá reclamar. Se você tentasse isso no cenário de várias tabelas, o banco de dados seria adequado.

Você pode tentar mitigar esses problemas dizendo "bem, apenas garantiremos que nunca façamos isso no código". Se você está confiante em sua capacidade de escrever código sem erros pela primeira vez e em levar em conta todas as combinações estranhas de coisas que um usuário pode tentar, vá em frente. Pessoalmente, não estou confiante em minha capacidade de fazer uma dessas coisas, por isso deixarei o banco de dados fornecer uma rede de segurança extra.

(Isso fica ainda pior se seu design é aquele em que você copia todos os dados relevantes entre linhas em vez de usar chaves estrangeiras. Qualquer inconsistência ortográfica / de outros dados será difícil de resolver. Como você pode saber se "Jon" é um erro de ortografia de "John "ou se foi intencional (porque são duas pessoas separadas)?)

Terceiro, quase todas as colunas precisam ser anuláveis ​​ou devem ser preenchidas com dados copiados ou com lixo. Um jogo não precisa de um TeamNameou TeamHomeCity. Portanto, todo jogo precisa de algum tipo de espaço reservado ou precisa ser anulável. E se for anulável, o banco de dados terá prazer em jogar sem TeamName. Também será necessária uma equipe sem nome, mesmo que sua lógica de negócios diga que isso nunca deve acontecer.

Existem várias outras razões pelas quais você deseja tabelas separadas (incluindo a preservação da sanidade do desenvolvedor). Existem até algumas razões pelas quais uma tabela maior pode ser melhor (a desnormalização às vezes melhora o desempenho). Esses cenários são poucos e distantes entre si (e geralmente são mais bem tratados quando você tem métricas de desempenho para mostrar que esse é realmente o problema, não um índice ausente ou algo mais).

Por fim, desenvolva algo que seja fácil de manter. Só porque "funciona" não significa que está tudo bem. Tentar manter tabelas de deus (como classes de deus) é um pesadelo. Você está se preparando para a dor mais tarde.


1
"Equipes: Id | Nome | HomeCity". Apenas verifique se o esquema de dados não faz com que o seu aplicativo afirme incorretamente que o Super Bowl XXXIV foi ganho pelos LA Rams. Considerando que SB XXXIV deve aparecer em uma consulta para todos os campeonatos conquistados pela equipe atualmente conhecida como LA Rams. Existem "mesas divinas" melhores e piores, e você certamente apresentou uma ruim. Uma melhor seria "ID do jogo | nome da equipe local | cidade do time local | nome da equipe visitante | cidade do time visitante | jogo começa em | etc ...". O que ocorre como uma primeira tentativa de modelar informações como "New Orleans Saints @ Chicago Bears 1p Eastern".
21716 Steve

6

Citação do dia: " Teoria e prática devem ser as mesmas ... em teoria "

Tabela não normalizada

Sua tabela exclusiva, que contém todos os dados redundantes, tem uma vantagem: torna o relatório em suas linhas muito simples de codificar e rápido de executar, porque você não precisa fazer nenhuma junção. Mas isso a um alto custo:

  • Possui cópias redundantes de relações (por exemplo, IngCompanyIDe vrCompanyName). A atualização dos dados mestre pode exigir a atualização de muito mais linhas do que em um esquema normalizado.
  • Mistura tudo. Você não pode garantir um controle de acesso fácil no nível do banco de dados, por exemplo, garantindo que o usuário A possa atualizar apenas as informações da empresa e o usuário B apenas as informações do produto.
  • Você não pode garantir regras de consistência no nível do banco de dados (por exemplo, chave primária para garantir que haja apenas um nome de empresa para um ID de empresa).
  • Você não se beneficia totalmente do otimizador de banco de dados que pode identificar estratégias ideais de acesso para uma consulta complexa, aproveitando o tamanho de tabelas normalizadas e estatísticas de vários índices. Isso pode rapidamente compensar o benefício limitado de evitar junções.

Tabela normalizada

As desvantagens acima são vantagens para o esquema normalizado. Obviamente, as consultas podem ser um pouco mais complexas para escrever.

Em resumo, o esquema normalizado expressa muito melhor a estrutura e as relações entre seus dados. Vou ser provocativo e dizer que é o mesmo tipo de diferença que entre a disciplina necessária para usar um conjunto de gavetas ordenadas do escritório e a facilidade de uso de uma lixeira.


5

Eu acho que há pelo menos duas partes em sua pergunta:

1. Por que entidades de tipos diferentes não devem ser armazenadas na mesma tabela?

As respostas mais importantes aqui são legibilidade e velocidade do código. A SELECT name FROM companies WHERE id = ?é muito mais legível que ae SELECT companyName FROM masterTable WHERE companyId = ?é menos provável que você faça perguntas acudidas sem sentido (por exemplo SELECT companyName FROM masterTable WHERE employeeId = ?, não seria possível quando empresas e funcionários estiverem armazenados em tabelas diferentes). Quanto à velocidade, os dados de uma tabela de banco de dados são recuperados lendo a tabela completa sequencialmente ou lendo um índice. Ambos são mais rápidos se a tabela / índice contiver menos dados, e é o caso se os dados forem armazenados em tabelas diferentes (e você só precisará ler uma das tabelas / índices).

2. Por que as entidades de um único tipo devem ser divididas em subentidades armazenadas em tabelas diferentes?

Aqui, o motivo é principalmente para evitar inconsistências de dados. Com a abordagem de tabela única, para um sistema de gerenciamento de pedidos, você pode armazenar o nome do cliente, o endereço do cliente e o ID do produto que o cliente solicitou como uma única entidade. Se um cliente encomendasse vários produtos, você teria várias instâncias do nome e endereço do cliente em seu banco de dados. Na melhor das hipóteses, você acabou de obter dados duplicados no seu banco de dados, o que pode desacelerar um pouco. Mas o pior é que alguém (ou algum código) cometeu um erro quando os dados foram inseridos, para que as empresas terminem com endereços diferentes no seu banco de dados. Só isso já é ruim o suficiente. Mas se você consultar o endereço de uma empresa com base no nome (por exemplo,SELECT companyAddress FROM orders WHERE companyName = ? LIMIT 1) você apenas arbitrariamente obteria um dos dois endereços retornados e nem perceberia que havia uma inconsistência. Porém, toda vez que você executa a consulta, é possível obter um endereço diferente, dependendo de como sua consulta é resolvida internamente pelo DBMS. Isso provavelmente quebrará seu aplicativo em outro lugar, e a causa raiz dessa quebra será muito difícil de encontrar.

Com a abordagem de várias tabelas, você perceberia que existe uma dependência funcional do nome da empresa para o endereço da empresa (se uma empresa puder ter apenas um endereço), você armazenaria a tupla (companyName, companyAddress) em uma tabela (por exemplo, company) e a tupla (productId, companyName) em outra tabela (por exemplo order). Uma UNIQUErestrição na companytabela poderia impor que cada empresa tivesse apenas um único endereço no banco de dados, para que nenhuma inconsistência nos endereços da empresa pudesse surgir.

Nota: na prática, por motivos de desempenho, você provavelmente geraria um companyId exclusivo para cada empresa e o usaria como uma chave estrangeira em vez de usar diretamente o companyName. Mas a abordagem geral permanece a mesma.


3

TL; DR - Eles estão projetando o banco de dados com base em como eles foram ensinados quando estavam na escola.

Eu poderia ter escrito essa pergunta há 10 anos. Levei algum tempo para entender por que meus antecessores projetaram seus bancos de dados da maneira que eles fizeram. Você está trabalhando com alguém que:

  1. Obteve a maior parte de suas habilidades de design de banco de dados usando o Excel como banco de dados ou
  2. Eles estão usando as melhores práticas de quando saíram da escola.

Não suspeito que seja o número 1, pois você realmente tem números de identificação em sua tabela, portanto, assumirei o número 2.

Depois que saí da escola, estava trabalhando para uma loja que usava um AS / 400 (também conhecido como IBM i). Encontrei algumas coisas estranhas na maneira como eles projetaram seus bancos de dados e comecei a advogar que fizéssemos alterações para seguir como me ensinaram a projetar bancos de dados. (Eu era burro naquela época)

Foi preciso um programador mais velho e paciente para me explicar por que as coisas foram feitas dessa maneira. Eles não haviam mudado o esquema porque isso causaria a quebra de programas mais antigos do que eu. Literalmente, o código fonte de um programa tinha uma data de criação do ano anterior ao meu nascimento. No sistema em que estávamos trabalhando, os programas deles precisavam implementar toda a lógica e operações que o planejador de consultas do banco de dados gerencia para você. (Você pode ver isso executando EXPLAIN em uma de suas consultas)

Ele estava atualizado sobre as técnicas que eu estava tentando implementar, mas manter o sistema em execução era mais importante do que fazer alterações "porque foi contra o que me ensinaram". Todo novo projeto que qualquer um de nós começava fazia o melhor uso possível do modelo relacional. Infelizmente, outros programadores / consultores da época ainda projetavam seus bancos de dados como se estivessem trabalhando com as restrições anteriores desse sistema.


Alguns exemplos do que encontrei que não se encaixavam no modelo relacional:

  • As datas foram armazenadas como números do dia juliano que exigiam uma associação a uma tabela de datas para obter a data real.
  • Tabelas desnormalizadas com colunas sequenciais do mesmo tipo (por exemplo code1,code2, ..., code20)
  • Colunas CHAR de comprimento NxM representando uma matriz de N cadeias de comprimento M.

As razões que me foram dadas para essas decisões de design foram baseadas nas restrições do sistema quando o banco de dados foi projetado pela primeira vez.

Datas - Disseram-me que demorava mais tempo de processamento para usar as funções de data (que mês ou dia ou dia da semana) para processar uma data do que criar uma tabela de todas as datas possíveis com todas essas informações.

Colunas sequenciais do mesmo tipo - O ambiente de programação em que estavam permitia que um programa criasse uma variável de matriz ao longo de parte da linha. E era uma maneira mais fácil de reduzir o número de operações de leitura.

Colunas CHAR de comprimento NxM - Era mais fácil inserir valores de configuração em uma coluna para reduzir as operações de leitura de arquivos.

Um exemplo mal concebido em C equivalente para refletir o ambiente de programação que eles tinham:

#define COURSE_LENGTH 4
#define NUM_COURSES 4
#define PERIOD_LENGTH 2

struct mytable {
    int id;
    char periodNames[NUM_COURSES * PERIOD_LENGTH];  // NxM CHAR Column
    char course1[COURSE_LENGTH];
    char course2[COURSE_LENGTH];
    char course3[COURSE_LENGTH];
    char course4[COURSE_LENGTH];
};

...

// Example row
struct mytable row = {.id= 1, .periodNames="HRP1P2P8", .course1="MATH", .course2="ENGL", .course3 = "SCI ", .course4 = "READ"};

char *courses; // Pointer used to access the sequential columns
courses = (char *)&row.course1;


for(int i = 0; i < NUM_COURSES; i++) {

    printf("%d: %.*s -> %.*s\n",i+1, PERIOD_LENGTH, &row.periodNames[PERIOD_LENGTH * i], COURSE_LENGTH,&courses[COURSE_LENGTH*i]);
}

Saídas

1: HR -> MATEMÁTICA
2: P1 -> PORTUGUÊS
3: P2 -> SCI
4: P8 -> LER

De acordo com o que me disseram, parte disso foi considerada uma prática recomendada na época.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.