{"id":116,"date":"2010-06-19T18:51:14","date_gmt":"2010-06-20T01:51:14","guid":{"rendered":"https:\/\/gonzalo.aro.cl\/blog\/?p=116"},"modified":"2010-07-06T21:44:34","modified_gmt":"2010-07-07T04:44:34","slug":"modelamiento-de-base-de-datos","status":"publish","type":"post","link":"https:\/\/gonzalo.aro.cl\/blog\/2010\/06\/19\/modelamiento-de-base-de-datos\/","title":{"rendered":"Modelamiento de base de datos"},"content":{"rendered":"<p><strong>Introducci\u00f3n<\/strong><\/p>\n<p>Siempre existen diferencias al momento de modelar bases de datos, ya sea por la forma en c\u00f3mo se fue educado en esta \u00e1rea, como las costumbres que se fueron adoptando en la vida laboral. Es por eso que muchas veces se necesitan acuerdos y\/o restricciones del como modelar ciertas caracter\u00edsticas de las bases de datos, esto para que se logre una estandarizaci\u00f3n del trabajo.<br \/>\nLa estandarizaci\u00f3n es compleja, lo m\u00e1s complicado es prever un est\u00e1ndar que apoye la velocidad de desarrollo, que de la posibilidad de encuentro r\u00e1pido de errores y que pueda ser &#8216;le\u00eddo&#8217; de una forma similar por todos los que participan del desarrollo y mantenci\u00f3n.<br \/>\nSe presenta un trabajo sobre el modelamiento de bases de datos y la aplicaci\u00f3n de est\u00e1ndares dentro del modelamiento.<\/p>\n<p><strong>Nombramiento<\/strong><\/p>\n<p><strong><em>Nombramiento de tablas<\/em><\/strong><\/p>\n<p>El nombre de la tabla debe ser representativo para la entidad en cuesti\u00f3n, tratando de evitar la ambig\u00fcedad. El nombre debe ser en singular si la clave primaria se conforma de un campo, se utilizar\u00e1 plural cuando exista una clave compuesta, ya que esto indica que existe un concepto que se repite m\u00e1s de una vez dentro de la tabla, ese concepto es el que debiese estar en plural.<br \/>\n<a href=\"https:\/\/gonzalo.aro.cl\/blog\/wp-content\/uploads\/2010\/06\/aro_bllog_nbd1.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-126\" title=\"aro_bllog_nbd1\" src=\"https:\/\/gonzalo.aro.cl\/blog\/wp-content\/uploads\/2010\/06\/aro_bllog_nbd1-300x114.jpg\" alt=\"\" width=\"300\" height=\"114\" srcset=\"https:\/\/gonzalo.aro.cl\/blog\/wp-content\/uploads\/2010\/06\/aro_bllog_nbd1-300x114.jpg 300w, https:\/\/gonzalo.aro.cl\/blog\/wp-content\/uploads\/2010\/06\/aro_bllog_nbd1.jpg 504w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nEn el ejemplo se representa lo descrito anteriormente, se puede discutir sobre el nombre de la tabla que relaciona a ambas, esto porque el nombre es CATEGORIAS_CLIENTES, esto implica a primera vista que un cliente puede estar en muchas categor\u00edas, y una categor\u00eda puede contener muchos clientes. Si el nombre fuese cambiado por ejemplo a CATEGORIA_CLIENTES, significar\u00eda que una categor\u00eda puede tener muchos clientes y un cliente solo podr\u00eda estar en una categor\u00eda. Si se dan cuenta existe la sutileza que la tabla CATEGORIA_CLIENTES tendr\u00eda la misma estructura de CATEGORIAS_CLIENTES, si la dibuj\u00e1semos ser\u00edan id\u00e9nticas. Debido a que la estructura de la tabla lo permite, igualmente podr\u00edamos introducir varios clientes a varias categor\u00edas y cada categor\u00eda contener m\u00e1s de un cliente, por lo mismo, para lograr el uso correcto con el significado que se le est\u00e1 dando al nombramiento se debiese generar un trigger que hiciese respetar el significado que le deseamos dar al modelamiento.<\/p>\n<p><strong><em>Prefijo del nombre de la tabla<\/em><\/strong><\/p>\n<p>En general las tablas no debiesen tener ning\u00fan prefijo espec\u00edfico, sobre todo cuando existe un buen manejo de esquemas o bases de datos en general. Por ejemplo, cuando se crea un esquema por cada negocio o escenario que se atiende tendr\u00edamos separadas las tablas en su esquema o base de datos respectiva, por ejemplo: CONTABILIDAD, INVERSIONES, TESORERIA, etc.<br \/>\nLa necesidad de prefijo surge cuando, por ejemplo, al desarrollar el sistema de inversiones, que ocupa el esquema o base de datos INVERSIONES te establecen la restricci\u00f3n de no escribir directamente al esquema CONTABILIDAD, por lo que debes generar tablas de paso en tu esquema de base de datos, para luego, por alg\u00fan otro proceso enviar los datos hacia el esquema de CONTABILIDAD. Otro punto en donde se genera la necesidad de un prefijo es cuando por alg\u00fan motivo tenemos solo una base de datos o esquema disponible, la mayor\u00eda de las veces por alg\u00fan tipo de restricci\u00f3n del cliente, as\u00ed la posibilidad de que el escenario que estamos evaluando tenga muchos subescenarios distintos dentro del mismo desarrollo surge la necesidad de dar un prefijo asociado en la tabla, para tener un mayor orden tanto en la lectura del modelo, as\u00ed como en la utilizaci\u00f3n de este, ya que con lectores o administradores de bases de datos disponibles las tablas con el mismo prefijo te saldr\u00e1n agrupadas por culpa de su ordenamiento alfab\u00e9tico. Por ejemplo:<\/p>\n<p>Prefijo para las tablas del escenario contabilidad CNT_<br \/>\nPrefijo para las tablas del escenario inversiones INV_<br \/>\nPrefijo para las tablas del escenario facturaci\u00f3n FCT_<\/p>\n<p>En general es bueno utilizar de tres a cuatro letras para la identificaci\u00f3n del escenario, para decidir que letras tambi\u00e9n hay que proveer una estructuraci\u00f3n para que dos personas siempre lleguen a prefijos similares; por ejemplo la siguiente: mantener la primera letra con que se nombra al escenario, sea vocal o consonante, luego de eso s\u00f3lo ocupo las consonantes, a menos que se diera el caso que el escenario este compuesto de dos palabras en donde trato de ocupar la primera letra de la primera palabra y luego las consonantes de la segunda palabra siguiendo las consideraciones ya explicadas. Ejemplos de utilizaci\u00f3n de la norma de nombramiento:<\/p>\n<p>CONTABILIDAD prefijo CNT<br \/>\nCONTABILIDAD_TESORERIA  prefijo CTS<br \/>\nINVERSIONES prefijo INV<br \/>\nINVERSIONES_RESUMIDAS  prefijo IRS<\/p>\n<p>Siguiendo esta f\u00f3rmula es f\u00e1cil hacer que un grupo de dise\u00f1adores llegue siempre a nombres similares.<\/p>\n<p><strong><em>Tablas temporales<\/em><\/strong><\/p>\n<p>En m\u00e1s de una oportunidad existe la necesidad de generar tablas temporales, para datos que son de paso, n\u00f3tese que es temporal para el caso de los datos, no para el caso de la estructura, o sea, no es que se elimine la tabla para luego construir la misma pero con otra estructura (cr\u00e9anme que ese tipo de solicitudes existen de parte de clientes y de hecho muchos utilizan este tipo de tablas). Aun cuando las ocupo, las evito completamente, pero cuando el cliente o el modelo realmente lo exige sugiero adicionar luego del prefijo TMP si pertenece al esquema o _TMP_ si pertenece al subescenario. Esto nos ayuda a tener agrupadas todas las tablas temporales. Debe quedar claro que en las tablas temporales se borrar\u00e1n los datos, o sea, son solo para guardado de resultados parciales que por motivos de velocidad o estructuraci\u00f3n, pero no se debe esperar que en la tabla permanezcan los datos.<br \/>\nAsociados a tablas temporales tambi\u00e9n debe existir un Jobs o proceso batch posterior que limpie la informaci\u00f3n con n tiempo de antig\u00fcedad. Puede ser que el mismo proceso que genera la informaci\u00f3n borre las tablas, pero el borrado igual requiere tiempo, por lo que para hacer m\u00e1s veloz el proceso que utiliza los datos temporales en general el borrado debe hacerse despu\u00e9s.<\/p>\n<p><strong><em>Nombramiento de claves primarias<\/em><\/strong><\/p>\n<p>El nombre de una clave primaria debe ser PKY_ seguido del nombre de la tabla, de esta forma se podr\u00e1 identificar la tabla o el problema de inserci\u00f3n cuando suceda, ya que el error saldr\u00e1 relacionado con el nombre del constraint. Es habitual encontrar en modelamientos que las claves primarias comiencen con el prefijo PK_, el problema es que en algunos motores de base de datos podemos encontrar paquetes (packages) que mas adelante se definir\u00e1n con prefijo PKG_, entonces utilizo PKY_ para un orden m\u00e1s especifico.<br \/>\nSi cre\u00e1semos la tabla CLIENTE en un motor de bases de datos Oracle en un esquema ARO pero sin dar nombre a la clave primaria, tendr\u00edamos:<\/p>\n<pre class=\"brush: sql\">CREATE TABLE CLIENTE  (\r\nRUT       NUMBER NOT NULL PRIMARY KEY,\r\nDV        VARCHAR2(1),\r\nNOMBRE    VARCHAR2(50),\r\nA_PATERNO VARCHAR2(50),\r\nA_MATERNO VARCHAR2(50)\r\n);\r\n<\/pre>\n<p>Esto crea la tabla con RUT como clave primaria pero no existe un nombre asociado a la clave primaria de la tabla por lo tanto al intentar insertar dos veces el mismo registro se tiene:<\/p>\n<pre class=\"brush: sql\">INSERT INTO CLIENTE (RUT, DV, NOMBRE, A_PATERNO, A_MATERNO) VALUES (1,9,'Nombre', 'Paterno','Materno');\r\n\r\nError que empieza en la l\u00ednea 9 del comando:\r\nINSERT INTO CLIENTE (RUT, DV, NOMBRE, A_PATERNO, A_MATERNO) VALUES (1,9,'Nombre', 'Paterno','Materno')\r\nInforme de error:\r\nError SQL: ORA-00001: unique constraint (ARO.SYS_C0079521) violated\r\n00001. 00000 -  \"unique constraint (%s.%s) violated\"\r\n*Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.\r\nFor Trusted Oracle configured in DBMS MAC mode, you may see\r\nthis message if a duplicate entry exists at a different level.\r\n*Action:   Either remove the unique restriction or do not insert the key.\r\n<\/pre>\n<p>Aparece un nombre que fue asignado por el motor de base de datos ARO.SYS_C0079521 lo que no nos dice nada. En contraposici\u00f3n, la forma correcta ser\u00eda:<\/p>\n<pre class=\"brush: sql\">CREATE TABLE CLIENTE  (\r\nRUT       NUMBER NOT NULL,\r\nDV        VARCHAR2(1),\r\nNOMBRE    VARCHAR2(50),\r\nA_PATERNO VARCHAR2(50),\r\nA_MATERNO VARCHAR2(50),\r\nCONSTRAINT PKY_CLIENTE PRIMARY KEY (RUT)\r\n);\r\n<\/pre>\n<p>Con esto el error anterior ser\u00eda m\u00e1s localizado:<\/p>\n<pre class=\"brush: sql\">Error que empieza en la l\u00ednea 11 del comando:\r\nINSERT INTO CLIENTE (RUT, DV, NOMBRE, A_PATERNO, A_MATERNO) VALUES (1,9,'Nombre', 'Paterno','Materno')\r\nInforme de error:\r\nError SQL: ORA-00001: unique constraint (ARO.PKY_CLIENTE) violated\r\n00001. 00000 -  \"unique constraint (%s.%s) violated\"\r\n*Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.\r\nFor Trusted Oracle configured in DBMS MAC mode, you may see\r\nthis message if a duplicate entry exists at a different level.\r\n*Action:   Either remove the unique restriction or do not insert the key.\r\n<\/pre>\n<p>Ahora se tiene que el error es en una PKY_CLIENTE, que nos lleva inmediatamente a la tabla CLIENTE, por lo que el log se hace much\u00edsimo m\u00e1s entendible.<\/p>\n<p><strong>Referencias<\/strong><\/p>\n<p>El nombre de una referencia esta dada por las tablas que participan. Utilizo el prefijo REF_ m\u00e1s el nombre de la tabla origen de la referencia y el nombre de la tabla destino. En el ejemplo se tiene que existen dos referencias:<\/p>\n<p>REF_CATEGORIAS_CLIENTES_CLIENTE, que es la referencia desde la tabla CATEGORIAS_CLIENTES hacia la tabla CLIENTE, lo que significa que en la tabla origen CATEGORIAS_CLIENTES existe la clave primaria de la tabla CLIENTE.<br \/>\nREF_CATEGORIAS_CLIENTES_CATEGORIA que es la referencia desde la tabla CATEGORIAS_CLIENTES hacia la tabla CATEGORIA, lo que significa que en la tabla origen CATEGORIAS_CLIENTES existe la clave primaria de la tabla CATEGORIA.<\/p>\n<p>No es necesario que en la tabla origen las referencias sean parte de las claves primarias, obviamente es un caso puntual. Por ejemplo, aqu\u00ed no se tiene a sexo como parte de la clave primaria.<\/p>\n<p><a href=\"https:\/\/gonzalo.aro.cl\/blog\/wp-content\/uploads\/2010\/06\/aro_bllog_nbd2.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gonzalo.aro.cl\/blog\/wp-content\/uploads\/2010\/06\/aro_bllog_nbd2.jpg\" alt=\"\" title=\"aro_bllog_nbd2\" width=\"188\" height=\"270\" class=\"alignnone size-full wp-image-129\" \/><\/a><\/p>\n<p>Una acotaci\u00f3n, en el motor Oracle los nombres de los objetos no deben superar los 30 caracteres, por lo mismo en la imagen del modelo los nombres de las referencias aparecen cortados a ese largo.<br \/>\nExisten ocasiones en donde las tablas de origen y destino son las mismas para dos o mas referencias pero tienen un significado distinto, por lo que al finalizar establezco el diferenciador a las referencias. Por ejemplo, asumamos que deseamos modelar que nuestro cliente puede invitar a otros clientes, y deseamos guardan quien recomend\u00f3 a quien, son dos relaciones desde la misma tabla origen a la misma tabla destino, por lo que bajo la normativa de nombramiento debiese tener el mismo nombre, es por eso que debemos agregarle un diferenciador. Ejemplo:<\/p>\n<p><a href=\"https:\/\/gonzalo.aro.cl\/blog\/wp-content\/uploads\/2010\/06\/aro_bllog_nbd31.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/gonzalo.aro.cl\/blog\/wp-content\/uploads\/2010\/06\/aro_bllog_nbd31-300x238.jpg\" alt=\"\" title=\"aro_bllog_nbd3\" width=\"300\" height=\"238\" class=\"alignnone size-medium wp-image-133\" srcset=\"https:\/\/gonzalo.aro.cl\/blog\/wp-content\/uploads\/2010\/06\/aro_bllog_nbd31-300x238.jpg 300w, https:\/\/gonzalo.aro.cl\/blog\/wp-content\/uploads\/2010\/06\/aro_bllog_nbd31.jpg 307w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Por lo tanto si nos da un error en REF_INVITADO_CLIENTE_INVITADO sabemos que el error es que nos falto el RUT_INVITADO, si es en REF_INVITADO_CLIENTE_INVITADOR, sabemos que el error esta en el RUT_CLIENTE.<\/p>\n<p><strong>Nombramiento de \u00edndices<\/strong><\/p>\n<p>Se utiliza el prefijo IDX_ adicionalmente se establece un sufijo con los caracteres C o N para indicar clusterizado o no y U o N para indicar si es \u00fanico o no \u00fanico. Finalmente pongo alg\u00fan nombre representativo para el \u00edndice. Aqu\u00ed se puede adem\u00e1s utilizar un acr\u00f3nimo de tres letras para la tabla, para utilizarlo despu\u00e9s del prefijo, esto tambi\u00e9n es \u00fatil para la ordenaci\u00f3n de los \u00edndices. Ejemplo:<br \/>\nIDX_CLI_ID_SEXO_NN indicar\u00eda un \u00edndice en la tabla cliente (asumiendo que CLI es el acr\u00f3nimo de esta tabla) es sobre el campo ID_SEXO, no clusterizado y no \u00fanico.<br \/>\nPara algunos puede ser paranoico el tema de nombramiento de \u00edndices, pero se transforma en una buena herramienta cuando se utiliza explain plain o herramientas similares, estas herramientas nos permiten saber si una consulta \u2018se va\u2019 por un \u00edndice o no, y nos otorgan la posibilidad de dudar del dise\u00f1o que existe detr\u00e1s del \u00edndice, ya que existen algunos \u00edndices que no son adecuados para las tablas, porque en muchos casos empeora el rendimiento de las consultas asociadas.<\/p>\n<p><strong>Nombramientos de chequeos (o reglas)<\/strong><\/p>\n<p>Cuando existe la posibilidad de nombrar los chequeos utilizo el prefijo CHK_ y luego el nombre representativo para el chequeo. El acr\u00f3nimo creado para la tabla tambi\u00e9n es \u00fatil ac\u00e1.<\/p>\n<p><strong>Nombramiento de campos<\/strong><\/p>\n<p>En general el nombre del campo es representativo al atributo que se desea modelar, por lo tanto RUT ser\u00e1 un Rol \u00danico Tributario, NOMBRE ser\u00e1 el nombre, y as\u00ed, no hay necesidad de complejizarlo a menos que sea absolutamente necesario.<\/p>\n<p><strong>\u00bfCu\u00e1ndo es necesario?<\/strong><\/p>\n<p>Existen usuarios que conocen la base de datos, esos usuarios tienen cargos de importancia, y en algunos casos modifican directamente los datos que un proceso hizo, luego del tiempo aparecen los esc\u00e1ndalos por fraude, o en otros casos, aparecen datos an\u00f3malos. Por lo tanto aparecen necesidades que no son de los modeladores de base de datos, sino que son de negocio, y que busca evitar que los usuarios modifiquen directamente datos que son realmente campos de cuidado, por ejemplo consolidaciones de balance, valorizaciones de cartera, etc.<br \/>\nEntonces, para las empresas que quieran modelos de datos sean m\u00e1s dif\u00edciles de entender a esos usuarios, o que por ventas de bases de datos quieren complicar alguna ingenier\u00eda reversa es bueno llegar a un consenso de nombramiento de campos de forma que tenga grados de dificultad para su traducci\u00f3n o verbalizaci\u00f3n pero que sean entendibles para el desarrollador. Realmente este punto es m\u00e1s \u00fatil para las empresas paranoicas con su seguridad sobre sus bases de datos.<br \/>\nLo siguiente es una propuesta para ello.<\/p>\n<p><strong>Prefijo<\/strong><\/p>\n<p>Comencemos por un prefijo que corresponde a tres caracteres que sirven de acr\u00f3nimo para la tabla.<\/p>\n<p>INSTRUMENTOS todos los campos comenzaran con INS_<br \/>\nPERSONA todos los campos comenzaran con PRS_<\/p>\n<p>Tambi\u00e9n es \u00fatil para disminuir un error muy com\u00fan, el de las columnas ambiguas, que ocurre cuando haces un select a dos tablas que contienen un campo del mismo nombre, si bien es cierto un desarrollador ordenado evitar\u00eda que le ocurriera, muchas veces pasa, incluso en proyectos en funcionamiento. Puede pasar que la segunda tabla hoy no tenga el campo, pero ma\u00f1ana con alg\u00fan nuevo desarrollo ese campo se incluya dentro de esta y algunas consultas ya hechas acusen el error.<\/p>\n<p><strong>Sufijo<\/strong><\/p>\n<p>En algunos casos dependiendo como sea la forma de trabajo del equipo de desarrollo es \u00fatil considerar un sufijo asociado al tipo de dato o al rol que juega el campo dentro de la tabla, pera este cado se tiene<\/p>\n<p>_PK para todas las que participan en la clave primaria<br \/>\n_FK para representar todas las que provienen de otra tabla<br \/>\n_NI para especificar n\u00fameros enteros<br \/>\n_ND para especificar n\u00fameros decimales<br \/>\n_CR para especificar caracteres<br \/>\n_RE para especificar campos si\/no o campos de un solo car\u00e1cter que indiquen una regla<br \/>\n_FC para campos fecha<br \/>\n_TM para campos timestamp, que incluyen fecha y hora<\/p>\n<p><strong>Mayor seguridad en el nombre<\/strong><\/p>\n<p>Como se vi\u00f3 si se utiliza prefijo y sufijo se tiene un campo m\u00e1s o menos as\u00ed<br \/>\nXXX_nombreDescriptivo_XX<br \/>\nEn el caso de asegurar el desarrollo de un producto y hacer m\u00e1s dif\u00edcil la comprensi\u00f3n del campo el nombre descriptivo se escribir\u00e1 como un par de conjunto de tres letras, de forma de nombrar el campo, quedando de la forma<br \/>\nXXX_XXX_XXX_XX<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introducci\u00f3n Siempre existen diferencias al momento de modelar bases de datos, ya sea por la forma en c\u00f3mo se fue educado en esta \u00e1rea, como las costumbres que se fueron adoptando en la vida laboral. Es por eso que muchas veces se necesitan acuerdos y\/o restricciones del como modelar ciertas caracter\u00edsticas de las bases de [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,4],"tags":[],"class_list":["post-116","post","type-post","status-publish","format-standard","hentry","category-base-de-datos","category-desarrollo"],"_links":{"self":[{"href":"https:\/\/gonzalo.aro.cl\/blog\/wp-json\/wp\/v2\/posts\/116"}],"collection":[{"href":"https:\/\/gonzalo.aro.cl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gonzalo.aro.cl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gonzalo.aro.cl\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gonzalo.aro.cl\/blog\/wp-json\/wp\/v2\/comments?post=116"}],"version-history":[{"count":19,"href":"https:\/\/gonzalo.aro.cl\/blog\/wp-json\/wp\/v2\/posts\/116\/revisions"}],"predecessor-version":[{"id":140,"href":"https:\/\/gonzalo.aro.cl\/blog\/wp-json\/wp\/v2\/posts\/116\/revisions\/140"}],"wp:attachment":[{"href":"https:\/\/gonzalo.aro.cl\/blog\/wp-json\/wp\/v2\/media?parent=116"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gonzalo.aro.cl\/blog\/wp-json\/wp\/v2\/categories?post=116"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gonzalo.aro.cl\/blog\/wp-json\/wp\/v2\/tags?post=116"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}