====== SQL ====== ===== Normalización ===== Metodología para optimizar las bases de datos. 3 formas normales. El ABC de las bases de datos relacionales. Son una serie de reglas que se deben cumplir a la hora de diseñar una base de datos, con sus tablas, campos y relaciones. ==== Primera forma normal ==== No se deben repetir datos de una tabla. Concepto de tabla maestra y tabla de detalle. Ejemplo de tabla mal hecha: ^ id ^ num_factura ^ producto ^ cantidad ^ precio ^ fecha ^ cliente ^ | 1 | 150 | miproducto | 10 | 12 | 2020-01-05 |pepito | | 2 | 150 | otroproducto | 5 | 3 | 2020-01-05 | pepito | | 3 | 100 | producto1 | 3 | 1 | 2019-09-03 | pepito | Podemos ver que se repite el número de factura y el cliente. La tabla maestra debería ser: ^ id_ ^ num_factura ^ cliente ^ | 1 | 150 | 1 | | 2 | 152 | 1 | La de detalle: ^ id ^ num_factura ^ | | | ==== Segunda forma normal ==== Cada campo de la tabla debe depender de la clave principal. No podemos incluir campos que dan información de otras tablas. Por ejemplo, si tenemos una tabla de clientes, no incluiremos campos de productos. ==== Tercera forma normal ==== No puede haber datos derivados. Si tenemos una clave foránea en una tabla, no podemos incluir en esa tabla otro campo de la tabla foránea si ellos los podemos obtener a través de dicha clave foránea. Por ejemplo, si tenemos un campo llamado **id_departamento** en la tabla **clientes**, no podría incluir un campo **nombre_departamento** en esa tabla ya que es un dato que se puede obtener mediante el campo **id_departamento** cuando buscamos en la tabla de **departamentos**. Esta forma normal obliga al uso de JOINS para poder obtener los datos que necesitemos. ===== Buenas prácticas ===== ==== Más tablas, menos columnas ==== Es preferible tener todo más atomizado en diferentes tablas que no pocas tablas llenas de campos. ==== Más registros, menos columnas ==== Al separar los datos en varias tablas, cuando crucemos información tendremos más registros, pero no crecerá en campos. ==== Usar valores por defecto ==== Muy útil cuando necesitamos que aparezca un valor siempre que no se diga lo contrario. ==== Usar campos de estado ==== Con campos de tipo BIT, nos facilitará mucho las consultas a ciertas tablas. Ciertas comprobaciones, en lugar de hacer consultas o desarrollos complejos, podremos resolverlas con filtros sencillos. Es muy mala práctica borrar registros de tablas maestras, podríamos tener problemas de consistencia por otros datos que de otras tablas que estén relacionadas con ella. Por ejemplo, teniendo una tabla **productos**, podríamos tener los siguientes campos: * ''estado'': indica si el producto está habilitado para su uso en el sistema. * ''venta_suspendida'': indica si el producto se quitó para la venta * ''compra_suspendida'': indica si el producto se quitó para la compra ==== Índices en campos significativos ==== Si las búsquedas se suelen hacer por ciertos campos, es recomendable añadirles índices para acelerarlas. Si el campo es de tipo BIT, añadir un índice no aporta ninguna mejora. ==== Tablas resumen ==== Con el tiempo, se almacenará tal cantidad de datos que afectará al tiempo que tardan las consultas. Un buena recomendación es crear tablas de resumen. Normalmente se automatiza un proceso mensual para crear una tabla con totales de un determinado periodo y así en búsquedas de ese rango de fechas, se hagan a estas tablas resumen en lugar de la tabla con la información desde el origen de los tiempos. No es nada recomendable que las tablas crezcan de forma descontrolada. ===== JOIN ===== {{ :informatica:bases_de_datos:sql:sql-tipos-joins.jpg?nolink&600 |}} ==== FULL OUTER JOIN ==== En MySQL no existe este tipo de JOIN, pero se puede emular mediante UNION: Con dos tablas: SELECT * FROM t1 LEFT JOIN t2 ON t1.id = t2.id UNION SELECT * FROM t1 RIGHT JOIN t2 ON t1.id = t2.id Con 3 tablas SELECT * FROM t1 LEFT JOIN t2 ON t1.id = t2.id LEFT JOIN t3 ON t2.id = t3.id UNION SELECT * FROM t1 RIGHT JOIN t2 ON t1.id = t2.id LEFT JOIN t3 ON t2.id = t3.id UNION SELECT * FROM t1 RIGHT JOIN t2 ON t1.id = t2.id RIGHT JOIN t3 ON t2.id = t3.id * [[https://stackoverflow.com/questions/2384298/why-does-mysql-report-a-syntax-error-on-full-outer-join|Why does MySQL report a syntax error on FULL OUTER JOIN?]] (Stack Overflow) ==== Ejemplos ==== Seleccionar los registros de una tabla que no aparezcan en la otra: SELECT * FROM table1 t1 LEFT JOIN table2 t2 ON t2.id = t1.id WHERE t2.id IS NULL ===== Convenciones ===== ==== Tablas ==== Las tablas se usan para almacenar información en la base de datos. Se puede poner el nombre en singular o plural. ==== Vistas ==== Son como tablas virtuales basadas en el resultado de consultas SQL. Una vista contiene filas y columnas, como una tabla normal. Cada nombre de vista debería comenzar por ''vw_'': ''vw_ProductDetails''. ==== Claves primarias ==== Una clave primaria identifica de forma unívoca cada registro en una tabla La clave debería comenzar con ''PK_'' e ir seguido del nombre de la tabla: ''PK_Empleados''. ==== Claves foráneas ==== Una clave foránea es un campo de una tabla que es clave primaria en otra tabla. El propósito de la clave foránea es asegurar la integridad referencial de los datos. La clave foránea debería comenzar por ''FK_'' e ir seguido del nombre de la tabla que la contiene y luego el nombre de la tabla donde es clave primaria: ''FK_Employees_Projects'', ''FK_Students_ContactNumbers'', '' FK_Orders_Details''