¿Por qué es importante el modelo relacional para una base de datos?


61

Me estoy acercando a un proyecto donde tendré que implementar una base de datos con mi jefe; Somos una empresa muy pequeña, por lo que el ambiente de trabajo es muy personal.

Me había dado una de las bases de datos de la compañía antes y estaba completamente en contra de lo que me enseñaron (y leí sobre) en la escuela para RDBMS. Por ejemplo, aquí hay bases de datos completas que consisten en una tabla (por base de datos independiente). Una de esas tablas tiene más de 20 columnas de largo y para el contexto, estos son algunos de los nombres de columna de una tabla:

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngProductID | vrProductName

El punto es que donde debería tener tablas individuales que contengan los datos de la entidad (nombre, tamaño, fecha de compra, etc.) lo coloca todo en una tabla grande por base de datos.

Quiero mejorar este diseño, pero no estoy seguro de por qué un modelo de datos correctamente normalizado y segmentado realmente mejoraría este producto. Si bien estoy familiarizado con el diseño de bases de datos de la universidad y entiendo cómo hacerlo, no estoy seguro de por qué esto realmente mejora las bases de datos.

¿Por qué un buen esquema relacional mejora una base de datos?


33
Una palabra: normalización.
Robert Harvey

99
Votante cercano: ¡justifícate! :-)
Robbie Dee

66
Es común que los nuevos empleados critiquen los procedimientos establecidos sin comprender las razones detrás de ellos, incluso si esas razones no son técnicamente sólidas. Primero descubra por qué su jefe lo construyó de esa manera. Es muy posible que él / ella sepa que no es un buen diseño, pero no tiene el conocimiento (o más probablemente, el tiempo) para hacerlo mejor. Los cambios que proponga probablemente se recibirán de manera más positiva si reconoce respetuosamente los motivos del diseño actual.
Pedro

55
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<- ¡Bienvenido al mundo real!
Möoz

55
Recuerdo mi cita favorita de la base de datos relacional: "Normalizar hasta que duela, desnormalizar hasta que funcione"
Jake

Respuestas:


70

El argumento del rendimiento suele ser el más intuitivo. Especialmente desea señalar cómo será difícil agregar buenos índices en una base de datos normalizada incorrectamente (nota: hay casos extremos en los que la desnormalización puede de hecho mejorar el rendimiento, pero cuando ambos no tienen experiencia con bases de datos relacionales, es probable que no sea fácil ver estos casos).

Otro es el argumento del tamaño de almacenamiento. Una tabla desnormalizada con muchas redundancias requerirá mucho más almacenamiento. Esto también influye en el aspecto del rendimiento: cuantos más datos tenga, más lentas serán sus consultas.

También hay un argumento que es un poco más difícil de entender, pero de hecho es más importante porque no puedes resolverlo arrojándole más hardware. Ese es el problema de consistencia de datos. Una base de datos correctamente normalizada se encargará de que un producto con una ID específica siempre tenga el mismo nombre. Pero en una base de datos desnormalizada, tales inconsistencias son posibles, por lo que se debe tener especial cuidado cuando se trata de evitar inconsistencias, lo que tomará tiempo de programación para hacerlo bien y aún causará errores que le costarán la satisfacción del cliente.


19
Un caso importante para la desnormalización es el almacenamiento de datos , específicamente, si tiene una gran cantidad de datos que se garantiza que nunca cambiará y desea consultarlos de manera más rápida y eficiente a expensas del espacio de almacenamiento. Buena respuesta, esto es solo un FYI para cualquier novato en SQL que no esté seguro de por qué sería deseable algo más que 3NF.


11
No estoy seguro de por qué el argumento de coherencia es "más difícil de entender". Me parece mucho más simple: si un valor cambia, entonces todas las copias de ese valor deben actualizarse. Actualizar una sola copia es mucho menos propenso a errores que actualizar cientos o miles de copias de los mismos datos. Esto se aplica igualmente bien a las relaciones entre datos. (Si tengo la relación almacenada de dos maneras, tengo que actualizar ambas copias de la relación). Este es un problema extremadamente común en las bases de datos desnormalizadas; Es muy difícil evitar esta corrupción en la práctica (una excepción es el uso del tipo de vista materializada).
jpmc26

44
Ese último párrafo debe resaltarse en negrita. :-) Sin normalización es imposible garantizar la integridad de los datos. Controlar la entrada únicamente en la capa de Business Logic es una tontería, ya que cada base de datos no normalizada finalmente exhibe algún tipo de anomalía en los datos.
DanK

2
@IsmaelMiguel La práctica habitual es que los datos maestros como este nunca se borran de la base de datos. Solo lo elimina de forma suave configurando una bandera que dice que ya no está disponible. En este caso particular, sería una buena idea tener una relación de clave externa entre productos y pedidos, lo que significa que la base de datos arrojará un error cuando intente eliminar un producto al que hace referencia cualquier pedido.
Philipp

24

Tendré que implementar una base de datos con mi jefe ...

El uso del software dedicado de gestión de bases de datos podría ser considerablemente más fácil (lo siento, no pude resistir).

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngProductID | vrProductName

Si esta base de datos solo se preocupa por "registrar" qué producto se vendió, dónde, cuándo y por quién, entonces podría extender la definición de "base de datos OK" lo suficiente como para cubrirla. Si estos datos se están utilizando para algo más, entonces es realmente bastante pobre.

Pero ...

¿La aplicación / consultas que utilizan estos datos responden mal / lentamente? Si no, entonces no hay un problema real para resolver. Claro, se ve y se siente feo, pero si funciona, entonces no obtendrá ningún "punto" por sugerir que "podría" ser mejor.

Si puede encontrar síntomas definitivos (es decir, problemas) que parecen ser causados ​​por un modelado de datos deficiente, prototipo de una solución mejor. Tome una copia de una de estas "bases de datos", normalice los datos y vea si su solución funciona mejor. Si es considerablemente mejor (y esperaría que cualquier operación de actualización de estos datos se mejorara enormemente ), vuelva a su jefe y muéstrele la mejora.

Es perfectamente posible recrear su "vista de tabla única" de los datos con ... bueno ... Vistas.


11
La resistencia a la tabla única weltanschauung a menudo proviene de aquellos inexpertos con SQL que no entienden las uniones, especialmente con respecto a los datos faltantes, es decir, las uniones externas.
Robbie Dee

66
@RobbieDee Más comúnmente, es de personas que han visto que los datos desnormalizados se corrompen al volverse inconsistentes. Soy una de esas personas. Solo consideraría este tipo de estructura en la situación que sugiere Phill: esta es una especie de tabla de registro / informe en la que los datos nunca se actualizarán o solo se actualizarán si se limpian y se vuelven a derivar completamente de otras fuentes.
jpmc26

2
Incluso si la aplicación funciona de manera aceptable con una base de datos como esta, todavía no es flexible como una base de datos correctamente normalizada. Si el nombre de la tienda o el nombre de la empresa cambian, tendrá que actualizarse en todas partes, en lugar de solo en una tabla de la tienda o empresa. En algunos casos, eso puede ser realmente lo que desea (como si los datos se recopilan principalmente para fines de archivo), pero necesitaríamos saber más sobre la aplicación específica.
Zach Lipton

1
@Zach: de acuerdo, es por eso que el registro de ventas es potencialmente un caso aceptable para esto. Suponiendo que desea que cada venta esté asociada a cualquier nombre de la tienda en el momento en que se realizó la venta, no "el nombre actual de la tienda", y luego intentar "normalizar" esto introduce una complejidad considerable (porque la tabla registra los nombres de las tiendas tendría que ser una serie a lo largo del tiempo, no solo un valor por storeid)
Steve Jessop

Tal vez una regla general sería que si la única complejidad introducida por una normalización propuesta es que algunas consultas ahora necesitan unirse en ellas para recoger todas las columnas que necesitan para informar, entonces debe correr, no caminar para hacer ese cambio: )
Steve Jessop

14

¿Por qué un buen esquema relacional mejora una base de datos?

La respuesta es: no siempre mejora una base de datos. Debes saber que lo que probablemente te enseñaron se llama Tercera forma normal .

Otros formularios son válidos en algunas situaciones, lo cual es clave para responder a su pregunta. Su ejemplo se parece a la primera forma normal , si eso lo ayuda a sentirse mejor sobre su estado actual.

Las reglas 3NF establecen relaciones entre los datos que "mejoran" una base de datos:

  1. Evite que los datos no válidos ingresen a su sistema (si una relación es 1 a 1, fuerza un error a pesar del código escrito encima). Si sus datos son consistentes en la base de datos, es menos probable que den lugar a inconsistencias fuera de su base de datos.

  2. Proporciona una forma de validar el código (por ejemplo, una relación de muchos a uno es una señal para restringir las propiedades / comportamientos de un objeto). Al escribir código para usar la base de datos, a veces los programadores notan la estructura de datos como un indicador de cómo debería funcionar su código. O pueden proporcionar comentarios útiles si la base de datos no coincide con su código. (Esto es más como una ilusión, desafortunadamente).

  3. Proporcione reglas que puedan ayudarlo significativamente a reducir los errores al crear una base de datos, de modo que no lo haga basándose en requisitos arbitrarios que pueden surgir en cualquier momento durante la vida de una base de datos. En cambio, está evaluando sistemáticamente la información para lograr objetivos específicos.

  4. Las estructuras adecuadas de la base de datos conducen a un mejor rendimiento al conectar los datos de manera que minimizan el almacenamiento de datos, minimizan las llamadas de almacenamiento para recuperar datos, maximizan los recursos en memoria y / o minimizan la clasificación / manipulación de datos para el conjunto de datos particular que tiene, en comparación con la consulta que está haciendo ejecutando en contra de ella. Pero la estructura "adecuada" depende de la cantidad de datos, la naturaleza de los datos, el tipo de consulta, los recursos del sistema, etc. Al normalizar puede empeorar el rendimiento (es decir, si carga todos los datos como 1 tabla, la unión puede ralentizarse una consulta). El procesamiento de transacciones (OLTP) frente a la inteligencia empresarial (almacén de datos) son muy diferentes.

En una pequeña empresa con pequeños conjuntos de datos, es posible que no haya nada de malo en la forma en que está ahora. Excepto que, si creces, será difícil "arreglar" más tarde, porque a medida que la tabla se agrande, los sistemas que la usan probablemente irán más despacio.

Por lo general, querrá enfatizar las transacciones rápidas a medida que una empresa crece. Sin embargo, si pasa tiempo en este proyecto ahora en lugar de otras cosas que la empresa puede necesitar con más urgencia, es posible que nunca tenga ese problema porque su empresa nunca crece realmente. Ese es el "desafío de optimización previa": dónde pasar su valioso tiempo en este momento.

¡Buena suerte!


44
Sin mencionar, pero creo que un punto importante para los programadores es que editar una "cosa" requiere la edición de una sola fila en lugar de tener que recorrer toda la base de datos para encontrar y reemplazar esa única cosa.
slebetman

@slebetman Nunca debería tener un bucle lateral de código para actualizar varias filas en una sola tabla, independientemente de si está normalizado. Usa una WHEREcláusula. Por supuesto, estos aún pueden salir mal, pero es menos probable en una situación normalizada ya que solo tiene que hacer coincidir una fila a través de la clave primaria.
jpmc26

@ jpmc26: al hacer un bucle en la base de datos me refiero a construir una consulta para actualizar todas las filas afectadas. A veces un solo DONDE es suficiente. Pero he visto estructuras impías que requieren subselecciones en la misma tabla para obtener todas las filas afectadas sin afectar las filas que no deberían cambiar. Incluso he visto a estructuras en las que una sola consulta no puede hacer el trabajo (la entidad que necesita un cambio reside en columnas diferentes en función de fila)
slebetman

Muchas respuestas excelentes a esta pregunta, y esta no fue la excepción.
Mike Chamberlain

11

Existen múltiples razones por las que usar una gran "tabla de Dios" es malo. Trataré de ilustrar los problemas con una base de datos de ejemplo inventada. Supongamos que está tratando de modelar eventos deportivos. Diremos que desea modelar juegos y los equipos que juegan en esos juegos. Un diseño con varias tablas podría verse así (esto es muy simplista a propósito, así que no te quedes atrapado en lugares donde podría aplicarse una mayor normalización):

Teams
Id | Name | HomeCity

Games
Id | StartsAt | HomeTeamId | AwayTeamId | Location

y una base de datos de una sola tabla se vería así

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

Primero, veamos cómo hacer índices en esas tablas. Si necesitaba un índice en la ciudad de origen para un equipo, podría agregarlo a la Teamstabla o a la TeamsAndGamestabla con bastante facilidad. Recuerde que siempre que cree un índice, debe almacenarse en el disco en algún lugar y actualizarse a medida que se agregan filas a la tabla. En el caso de la Teamstabla, esto es bastante sencillo. Puse un nuevo equipo, la base de datos actualiza el índice. ¿Pero para qué TeamsAndGames? Bueno, lo mismo se aplica desde elTeamsejemplo. Agrego un equipo, el índice se actualiza. ¡Pero también sucede cuando agrego un juego! Aunque ese campo será nulo para un juego, el índice aún debe actualizarse y almacenarse en el disco para ese juego de todos modos. Para un índice, esto no suena tan mal. Pero cuando necesita muchos índices para las múltiples entidades agrupadas en esta tabla, desperdicia mucho espacio almacenando los índices y mucho tiempo de procesador actualizándolos para cosas donde no se aplican.

En segundo lugar, la coherencia de los datos. En el caso de usar dos mesas separadas, puedo usar claves externas de la Gamesmesa a la Teamsmesa para definir qué equipos están jugando en un juego. Y suponiendo que las columnas HomeTeamIdy AwayTeamIdno sean anulables, la base de datos garantizará que cada juego que coloque tenga 2 equipos y que esos equipos existan en mi base de datos. Pero, ¿qué pasa con el escenario de una sola mesa? Bueno, dado que hay varias entidades en esta tabla, esas columnas deben ser anulables (puede hacer que no sean anulables y colocar datos basura allí, pero eso es solo una idea horrible). Si esas columnas son anulables, la base de datos ya no puede garantizar que cuando inserte un juego tenga dos equipos.

Pero, ¿qué pasa si decides ir de todos modos? Configura las claves foráneas de modo que esos campos apunten a otra entidad en la misma tabla. Pero ahora la base de datos solo se asegurará de que esas entidades existan en la tabla, no de que sean del tipo correcto. Podrías configurar fácilmente GameHomeTeamIdla ID de otro juego y la base de datos no se quejará en absoluto. Si lo intentara en el escenario de tablas múltiples, la base de datos arrojaría un ajuste.

Puede intentar mitigar estos problemas diciendo "bueno, nos aseguraremos de que nunca lo hagamos en código". Si confía en su capacidad para escribir código libre de errores la primera vez y en su capacidad para tener en cuenta todas las combinaciones extrañas de cosas que un usuario podría intentar, siga adelante. Personalmente, no confío en mi capacidad para hacer ninguna de esas cosas, así que dejaré que la base de datos me brinde una red de seguridad adicional.

(Esto empeora aún más si su diseño es uno en el que copia todos los datos relevantes entre filas en lugar de usar claves externas. Cualquier falta de ortografía / otras inconsistencias de datos será difícil de resolver. ¿Cómo puede saber si "Jon" es un error ortográfico de "John "o si fue intencional (porque son dos personas separadas)?)

En tercer lugar, casi todas las columnas deben ser anulables o deben llenarse con datos copiados o basura. Un juego no necesita un TeamNameo TeamHomeCity. Entonces, o cada juego necesita algún tipo de marcador de posición o debe ser anulable. Y si es anulable, la base de datos tomará un juego sin problemas TeamName. También tomará un equipo sin nombre, incluso si la lógica de su negocio dice que eso nunca debería suceder.

Hay un puñado de otras razones por las que desearía tablas separadas (incluida la preservación de la cordura del desarrollador). Incluso hay algunas razones por las que una tabla más grande podría ser mejor (la desnormalización a veces mejora el rendimiento). Esos escenarios son pocos y distantes entre sí (y generalmente se manejan mejor cuando tiene métricas de rendimiento para mostrar que ese es realmente el problema, no un índice faltante u otra cosa).

Finalmente, desarrolle algo que sea fácil de mantener. El hecho de que "funcione" no significa que esté bien. Tratar de mantener tablas de dioses (como las clases de dioses) es una pesadilla. Simplemente te estás preparando para el dolor más tarde.


1
"Equipos: Id | Nombre | HomeCity". Solo asegúrese de que su esquema de datos no haga que su solicitud afirme incorrectamente que los Rams de Los Ángeles ganaron el Super Bowl XXXIV. Mientras que SB XXXIV debería aparecer en una consulta para todos los campeonatos ganados por el equipo actualmente conocido como los LA Rams. Hay mejores y peores "tablas de Dios", y ciertamente has presentado una mala. Una mejor sería "ID del juego | nombre del equipo local | ciudad del equipo local | nombre del equipo visitante | ciudad del equipo visitante | el juego comienza en | etc ...". Lo que se produce como un primer intento de modelar información como "New Orleans Saints @ Chicago Bears 1p Eastern".
Steve Jessop

6

Cita del día: " Teoría y práctica deberían ser lo mismo ... en teoría "

Mesa desnormalizada

Su tabla única de retención de datos contiene datos redundantes tiene una ventaja: hace que los informes en sus líneas sean muy simples de codificar y rápidos de ejecutar porque no tiene que hacer ninguna unión. Pero esto a un alto costo:

  • Contiene copias redundantes de las relaciones (por ejemplo, IngCompanyIDy vrCompanyName). La actualización de datos maestros puede requerir la actualización de muchas más líneas que en un esquema normalizado.
  • Mezcla todo. No puede garantizar un control de acceso fácil a nivel de base de datos, por ejemplo, asegurarse de que el usuario A pueda actualizar solo la información de la empresa y la información del producto solo del usuario B.
  • No puede garantizar reglas de coherencia a nivel de base de datos (p. Ej., Clave principal para garantizar que solo haya un nombre de empresa para un ID de empresa).
  • No se beneficia completamente del optimizador de base de datos que podría identificar estrategias de acceso óptimas para una consulta compleja, aprovechando el tamaño de las tablas normalizadas y las estadísticas de varios índices. Esto podría compensar rápidamente el beneficio limitado de evitar uniones.

Tabla normalizada

Las desventajas anteriores son ventajas para el esquema normalizado. Por supuesto, las consultas pueden ser un poco más complejas de escribir.

En resumen, el esquema normalizado expresa mucho mejor la estructura y las relaciones entre sus datos. Seré provocativo y diré que es el mismo tipo de diferencia que entre la disciplina requerida para usar un conjunto de cajones de oficina ordenados y la facilidad de uso de un contenedor de basura.


5

Creo que hay al menos dos partes en su pregunta:

1. ¿Por qué no deberían almacenarse entidades de diferentes tipos en la misma tabla?

Las respuestas más importantes aquí son la legibilidad del código y la velocidad. A SELECT name FROM companies WHERE id = ?es mucho más legible que a SELECT companyName FROM masterTable WHERE companyId = ?y es menos probable que haga preguntas sin sentido (por ejemplo SELECT companyName FROM masterTable WHERE employeeId = ?, no sería posible cuando las empresas y los empleados se almacenan en tablas diferentes). En cuanto a la velocidad, los datos de una tabla de base de datos se recuperan leyendo la tabla completa secuencialmente o leyendo un índice. Ambos son más rápidos si la tabla / índice contiene menos datos, y ese es el caso si los datos se almacenan en tablas diferentes (y solo necesita leer una de las tablas / índices).

2. ¿Por qué las entidades de un solo tipo se dividen en subentidades que se almacenan en tablas diferentes?

Aquí, la razón es principalmente para evitar inconsistencias de datos. Con el enfoque de tabla única, para un sistema de gestión de pedidos, puede almacenar el nombre del cliente, la dirección del cliente y el ID del producto que el cliente solicitó como una entidad única. Si un cliente solicita varios productos, tendrá múltiples instancias del nombre y la dirección del cliente en su base de datos. En el mejor de los casos, acaba de obtener datos duplicados en su base de datos, lo que puede ralentizarlo un poco. Pero un caso peor es que alguien (o algún código) cometió un error cuando se ingresaron los datos para que una compañía termine con diferentes direcciones en su base de datos. Esto solo es bastante malo. Pero si tuviera que consultar la dirección de una empresa en función de su nombre (p. Ej.SELECT companyAddress FROM orders WHERE companyName = ? LIMIT 1) solo obtendría arbitrariamente una de las dos direcciones devueltas y ni siquiera se daría cuenta de que había una inconsistencia. Pero cada vez que ejecuta la consulta, en realidad puede obtener una dirección diferente, dependiendo de cómo DBMS resuelva internamente su consulta. Esto probablemente romperá su aplicación en otro lugar, y la causa raíz de esa ruptura será muy difícil de encontrar.

Con el enfoque de varias tablas, se daría cuenta de que existe una dependencia funcional del nombre de la empresa a la dirección de la empresa (si una empresa solo puede tener una dirección), almacenaría la tupla (companyName, companyAddress) en una tabla (p. Ej. company) y la tupla (productId, companyName) en otra tabla (p order. ej .). Una UNIQUErestricción en la companytabla podría obligar a que cada compañía solo tenga una única dirección en su base de datos para que nunca surjan inconsistencias en las direcciones de la compañía.

Nota: en la práctica, por razones de rendimiento, probablemente generaría un ID de compañía único para cada compañía y lo usaría como una clave externa en lugar de usar directamente el nombre de la compañía. Pero el enfoque general sigue siendo el mismo.


3

TL; DR : están diseñando la base de datos en función de cómo se les enseñó cuando estaban en la escuela.

Podría haber escrito esta pregunta hace 10 años. Me llevó algo de tiempo entender por qué mis predecesores diseñaron sus bases de datos de la manera en que lo hicieron. Estás trabajando con alguien que:

  1. Obtuvo la mayoría de sus habilidades de diseño de bases de datos utilizando Excel como base de datos o
  2. Están utilizando las mejores prácticas de cuando salieron de la escuela.

No sospecho que sea el número 1, ya que en realidad tiene números de identificación en su tabla, por lo que asumiré el número 2.

Después de salir de la escuela, estaba trabajando para una tienda que usaba un AS / 400 (también conocido como IBM i). Encontré algunas cosas extrañas en la forma en que diseñaron sus bases de datos, y comencé a recomendar que hagamos cambios para seguir cómo me enseñaron a diseñar bases de datos. (Yo era tonto en ese entonces)

Se necesitó un paciente programador mayor para explicarme por qué las cosas se hicieron de esa manera. No habían cambiado el esquema porque habría provocado la ruptura de programas que eran más antiguos que yo. Literalmente, el código fuente de un programa tenía una fecha de creación del año anterior a mi nacimiento. En el sistema en el que estábamos trabajando, sus programas tenían que implementar toda la lógica y las operaciones que el planificador de consultas de su base de datos maneja por usted. (Puede ver eso ejecutando EXPLAIN en una de sus consultas)

Estaba actualizado sobre las técnicas que estaba tratando de implementar, pero mantener el sistema en funcionamiento era más importante que hacer cambios "porque iba en contra de lo que me enseñaron". Cada nuevo proyecto que cualquiera de nosotros comenzó hizo un mejor uso del modelo relacional que pudimos. Desafortunadamente, otros programadores / consultores de esa época todavía diseñaron sus bases de datos como si estuvieran trabajando con las restricciones anteriores de ese sistema.


Algunos ejemplos de lo que encontré que no se ajustaban al modelo relacional:

  • Las fechas se almacenaron como números de días julianos que requerían una unión a una tabla de fechas para obtener la fecha real.
  • Tablas desnormalizadas con columnas secuenciales del mismo tipo (p code1,code2, ..., code20. Ej. )
  • Columnas CHAR de longitud NxM que representan una matriz de N cadenas de longitud M.

Las razones que se me dieron para tomar esas decisiones de diseño se basaron en las restricciones del sistema cuando se diseñó la base de datos por primera vez.

Fechas : me dijeron que llevó más tiempo de procesamiento usar las funciones de fecha (qué mes, día o día de la semana) para procesar una fecha que para crear una tabla de cada fecha posible con toda esa información.

Columnas secuenciales del mismo tipo : el entorno de programación en el que se encontraban permitió que un programa creara una variable de matriz sobre parte de la fila. Y fue una forma más fácil de reducir el número de operaciones de lectura.

Columnas CHAR de longitud NxM : fue más fácil insertar los valores de configuración en una columna para reducir las operaciones de lectura de archivos.

Un ejemplo mal concebido en C equivalente para reflejar el entorno de programación que tenían:

#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]);
}

Salidas

1: HR -> MATH
2: P1 -> ENGL
3: P2 -> SCI
4: P8 -> LEER

Según lo que me dijeron, parte de esto se consideró la mejor práctica en ese momento.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.