Está en la página 1de 12

La integridad referencial declarativa y las relaciones entre tablas

La integridad referencial declarativa (DRI) y las relaciones entre tablas vienen a garantizar algo importantsimo en los sistemas relacionales, en este caso la consistencia de los datos. No es de recibo que exista en una base de datos un albarn al cliente 50, y que el cliente 50 no exista!!, y eso es lo que nos garantiza la DRI, que esas cosas no sucedan. Ahora bien, lo que la integridad referencial no garantiza es que existan registros relacionados, por ejemplo, en los trozos de cdigo que vienen justo a continuacin vamos a ver como puede existir una cabecera que no tenga lneas, aunque la DRI garantiza que si existe una lnea su cabecera si existe. Esto puede llevarnos a situaciones a veces difciles de entender, sobre todo al principio. Si se construye una sentencia select que devuelve los registros de la cabecera, aparecen X registros, si la sentencia se completa con las unin con las lneas aparecen Y, pero Y puede ser hasta menor que X, sera normal que fuese mayor, pero menor?, veamos el ejemplo. /* Siempre nos basamos en una bd que exista en el sistema y que se llame pruebas */ use pruebas go create table cabecera( id int identity (1,1) primary key not null, fecha datetime default getdate()) go create table lineas (id int not null, orden int not null, Descripcion varchar(100) not null, constraint pk_lineas primary key (id,orden), constraint fk_lineas foreign key (id) references cabecera) go /* adems metemos 100 cabeceras */ declare @i int set @i=0 while @i<100 begin insert into cabecera default values select @i=@i+1 end go /* y dos lineas *// insert into lineas values (1,1,Esto es una prueba) insert into lineas values (1,2,Esto es una prueba linea 2) go select * from cabecera 100 filas Esto es normal, el sistema nos devuelve las 100 filas de la cabecera, go select * from cabecera inner join lineas on cabecera.id=lineas.id

2 filas !!!! Sin embargo ahora devuelve solo dos, porque una sola cabecera tiene lneas y tiene dos lneas, por tanto devuelve aquellas que estn en las dos tablas, coincidiendo su id, esto da como resultado, dos lneas solamente. Pero podemos hacer que devuelva todas las cabeceras, y aquellas que no tengan lneas, pues que nos devuelva valores null, esto son los llamados joins externos y sirven para resolver la problemtica precisamente de cabeceras no relacionadas con lneas. go select * from cabecera left join lineas on cabecera.id=lineas.id 101 filas El resultado sern las 101 filas, siendo todos los valores de la tabla lneas null, en aquellas que no tienen registros relacionados. Aparece una fila ms que cabeceras por que una cabecera tiene dos lneas, por tanto esa cabecera aparecer dos veces. go select * from cabecera left join lineas on cabecera.id=lineas.id where lineas.id is null 99 filas = 101 2 filas. Tambin podemos mediante sentencias como la que tienes arriba encontrar todas las cabeceras que no tiene lneas, sabemos que si no hay lneas, el campo que relaciona lneas con cabecera ser null, no existir, as que obligamos a que esto sea as con el predicado Where lineas.id is null Otras cuestiones, tambin puede ser que las relaciones externas sean opcionales, en nuestro ejemplo, vamos a aadir una zona, que resultar opcional, se podr indicar para esta cabecera o no. Si no se indica ser un valor null en la tabla de cabecera, pero si se indica, tiene que existir, a continuacin el script para crear esta relacin. alter table cabecera add idZona int go create table Zonas (idzona int identity(1,1) not null primary key, nombre varchar(100) not null ) go alter table cabecera add constraint fk_CabZonas foreign key (idZona) references zonas(idzona) go Insertamos un registro en zonas insert into zonas values (Sur Este?) select @@identity Insertada la zona 1 Sin embargo existen ya 100 cabeceras con zona =null y eso no supone ningn problema, vamos excepto que queramos sacar el nombre de la cabecera. select * from cabecera c inner join zonas on c.idzona=zonas.idzona Tambin devolver cero registros, por lo que tendremos que usar de nuevo left join.

Como comentarios aadir que sql-server tambin admite una notacin distinta de inner join, left join y right join, a base de poner el la condicin where el smbolo * al lado del igual de una de las condiciones, pero que adems de ser menos clara en mi opinin, no es nomenclatura ANSI, por lo que Sql-server podra no soportarla en futuras versiones.

Que es un ndice?
Un ndice (o KEY, o INDEX) es un grupo de datos que MySQL asocia con una o varias columnas de la tabla. En este grupo de datos aparece la relacin entre el contenido y el nmero de fila donde est ubicado. Los ndices -como los ndices de los libros- sirven para agilizar las consultas a las tablas, evitando que mysql tenga que revisar todos los datos disponibles para devolver el resultado. Podemos crear el ndice a la vez que creamos la tabla, usando la palabra INDEX seguida del nombre del ndice a crear y columnas a indexar (que pueden ser varias): INDEX nombre_indice (columna_indexada, columna_indexada2...) La sintaxis es ligeramente distinta segun la clase de ndice: PRIMARY KEY (nombre_columna_1 [,nombre_columna2...]) UNIQUE INDEX nombre_indice (columna_indexada1 [,columna_indexada2 ...]) INDEX nombre_index (columna_indexada1 [,columna_indexada2...])

Podemos tambin aadirlos a una tabla despus de creada: ALTER TABLE nombre_tabla ADD INDEX nombre_indice (columna_indexada); Si queremos eliminar un ndice: ALTER TABLE tabla_nombre DROP INDEX nombre_indice para que sirven ? LOs index permiten mayor rpidez en la ejecucin de las consultas a la base de datos tipo SELECT ... WHERE La regla bsica es pues crear tus ndices sobre aquellas columnas que vayas a usar con una clusula WHERE, y no crearlos con aquellas columnas que vayan a ser objeto de un SELECT: SELECT texto from tabla_libros WHERE autor = Vazquez; En este ejemplo, la de autor es una columna buena candidata a un indice; la de texto, no. Otra regla bsica es que son mejores candidatas a indexar aquellas columnas que presentan muchos valores distintos, mientras que no son buenas candidatas las que tienen muchos valores idnticos, como por ejemplo sexo (masculino y femenino) porque cada consulta implicar siempre recorrer practicamente la mitad del indice. La regla de la izquierda Si necesitamos un select del tipo SELECT ... WHERE columna_1 = X AND columna_2 = Y y ya tenemos un INDEX con la columna_1, podemos crear un segundo indice con la columna 2, o mejor

todava, crear un nico indice combinado con las columnas 1 y 2. Estos son los ndices multicolumna, o compuestos. No obstante si tienes indices multicolumna y los utilizas en las clausulas WHERE, debes incluir siempre de izquierda a derecha las columnas indexadas; o el indice NO se usar: Supongamos un INDEX usuario (id, name, adress), y una clusula SELECT ... WHERE NAME = x. Este Select no aprovechar el ndice. Tampoco lo hara un SELECT ... WHERE ID =X AND ADRESS = Y. Cualquier consulta que incluya una columna parte del index sin incluir adems las columnas a su izquierda, no usar el indice. Por tanto en nuestro ejemplo solo sacarian provecho del indice las consultas SELECT ... WHERE ID = x, o WHERE ID = X AND NAME = y o WHERE ID = x AND NAME = y AND ADRESS = Z Cuando un ndice contiene mas de una columna, cada columna es leida por el orden que ocupa de izquierda a derecha, y a efectos prcticos, cada columna (por ese orden) es como si constituyera su propio ndice. Esto significa que en el ejemplo anterior, no hara falta crear otro INDEX ID (id) ya que podramos usar nuestro INDEX USUARIO simplemente con la clusula SELECT ... WHERE ID = X; Puedes ver si tu llamada sql usa o no los ndices correctos anteponiendo a select la orden explain: EXPLAIN SELECT * FROM mitable WHERE .... Y para ser sinceros, usando explain para comprobar el uso de indices en distintos selects con indices multicolumna, he obtenido resultados poco consistentes con la 'regla de la izquierda' ya que en muchos casos parece que se usaban indices que tericamente no debian estar disponibles ... posiblemente un caso de mala configuracion en mi tabla-test Tipos de indice En algunas bases de datos existen diferencias entre KEY e INDEX. No as en MySQL donde son sinnimos. Un ndice que s es especial es el llamado PRIMARY KEY. Se trata de un ndice diseado para consultas especialmente rpidas. Todos sus campos deben ser UNICOS y no admite NULL Un indice UNIQUE es aquel que no permite almacenar dos valores iguales. Los indices FULL TEXT permiten realizar bsquedas de palabras. Puedes crear indices FULLTEXT sobre columnas tipo CHAR, VARCHAR o TEXT. Una vez creado puedes hacer bsquedas del tipo: SELECT * FROM nombre_tabla WHERE MATCH(nombre_indice_fulltext) AGAINST('palabra_a_buscar'); Algunas limitaciones de los indices fulltext: solo busca por palabras completas. indice no encontrar indices. No se indexan las palabras de menos de cuatro letras. No se indexan columnas que contengan menos de tres filas, ni palabras que aparezcan en la mitad o mas de las filas. Las palabras separadas por guiones se cuentan como dos palabras.

Los indices ordinarios no tienen restricciones en cuanto a la existencia de valores idnticos o nulos. Una posibilidad interesante, si pensamos crear un ndice sobre columnas CHAR y VARCHAR es la de limitar el campo a indexar. Por ejemplo, cada entrada en la columna puede ser de hasta 40 caracteres y nosotros indexar unicamente los primeros 10 de cada una. Para crear estos ndices basta con indicar entre parntesis el numero de caracteres a indexar despues del nombre de la columna: ALTER TABLE libros ADD INDEX idx_autor(nombre(10), apellidos(10));

Desventajas de los indices Los ndices se actualizan cada vez que se modifica la columna o columnas que utiliza. Por ello no es aconsejable usar como indices columnas en las que sern frecuentes operaciones de escritura (INSERT, UPDATE, DELETE). Tampoco tendra sentido crear indices sobre columnas cuando cualquier select sobre ellos va a devolver una gran cantidad de resultados; por ejemplo una columna booleana que admita los valores Y/N. En fin, tampoco es necesario usar indices en tablas demasiado pequeas, ya que en estos casos no hay ganancia de rapidez frente a una consulta normal. Finalmente, los ndices ocupan espacio. A veces, incluso mas que la tabla de datos. Un ndice permite un acceso a los datos mucho ms rpido.

ndices
Tenemos tres tipos de ndices. El primero corresponde a las claves primarias, que como vimos, tambin se pueden crear en la parte de definicin de columnas. Claves primarias La sintaxis para definir claves primarias es:
definicin_columnas | PRIMARY KEY (index_nombre_col,...)

El ejemplo anterior que vimos para crear claves primarias, usando esta sintaxis, quedara as:
mysql> CREATE TABLE ciudad4 (nombre CHAR(20) NOT NULL, -> poblacion INT NULL DEFAULT 5000, -> PRIMARY KEY (nombre)); Query OK, 0 rows affected (0.17 sec)

Pero esta forma tiene ms opciones, por ejemplo, entre los parntesis podemos especificar varios nombres de columnas, para construir claves primarias compuestas por varias columnas:
mysql> CREATE TABLE mitabla1 ( -> id1 CHAR(2) NOT NULL,

-> id2 CHAR(2) NOT NULL, -> texto CHAR(30), -> PRIMARY KEY (id1, id2)); Query OK, 0 rows affected (0.09 sec) mysql>

ndices El segundo tipo de ndice permite definir ndices sobre una columna, sobre varias, o sobre partes de columnas. Para definir estos ndices se usan indistintamente las opciones KEY o INDEX.
mysql> CREATE TABLE mitabla2 ( -> id INT, -> nombre CHAR(19), -> INDEX (nombre)); Query OK, 0 rows affected (0.09 sec)

O su equivalente:
mysql> CREATE TABLE mitabla3 ( -> id INT, -> nombre CHAR(19), -> KEY (nombre)); Query OK, 0 rows affected (0.09 sec)

Tambin podemos crear un ndice sobre parte de una columna:


mysql> CREATE TABLE mitabla4 ( -> id INT, -> nombre CHAR(19), -> INDEX (nombre(4))); Query OK, 0 rows affected (0.09 sec)

Este ejemplo usar slo los cuatro primeros caracteres de la columna 'nombre' para crear el ndice. Claves nicas El tercero permite definir ndices con claves nicas, tambin sobre una columna, sobre varias o sobre partes de columnas. Para definir ndices con claves nicas se usa la opcin UNIQUE. La diferencia entre un ndice nico y uno normal es que en los nicos no se permite la insercin de filas con claves repetidas. La excepcin es el valor NULL, que s se puede repetir.
mysql> CREATE TABLE mitabla5 ( -> id INT, -> nombre CHAR(19),

-> UNIQUE (nombre)); Query OK, 0 rows affected (0.09 sec)

Una clave primaria equivale a un ndice de clave nica, en la que el valor de la clave no puede tomar valores NULL. Tanto los ndices normales como los de claves nicas s pueden tomar valores NULL. Por lo tanto, las definiciones siguientes son equivalentes:
mysql> CREATE TABLE mitabla6 ( -> id INT, -> nombre CHAR(19) NOT NULL, -> UNIQUE (nombre)); Query OK, 0 rows affected (0.09 sec)

Y:
mysql> CREATE TABLE mitabla7 ( -> id INT, -> nombre CHAR(19), -> PRIMARY KEY (nombre)); Query OK, 0 rows affected (0.09 sec)

Los ndices sirven para optimizar las consultas y las bsquedas de datos. Mediante su uso es mucho ms rpido localizar filas con determinados valores de columnas, o seguir un determinado orden. La alternativa es hacer bsquedas secuenciales, que en tablas grandes requieren mucho tiempo.

declarative referential integrity and relationships between tables


Declarative referential integrity (DRI) and the relationships between tables to ensure something important come in relational systems, in this case the consistency of the data. It is unacceptable that there is a database on a delivery note to the client 50, and the client 50 does not exist!, And that is what guarantees the DRI, these things happen. Now, what does not guarantee referential integrity is that there are related records, for example, pieces of code that are right then we will see how it can be a header that has no lines, although the DRI ensures that if there is a its header line if one exists. This can lead to situations sometimes difficult to understand, especially at first. If you build a select statement that returns records from the bedside, there are X records, if the sentence is completed with the union with lines are Y, but Y can be up less than X, it would be 'normal' is greater, but Are you under?, consider the example. / * We always rely on a db that exists in the system and is called tests * / use test go create table header (id int identity (1.1) not null primary key, date datetime default getdate ()) lines go create table (id int not null, order int not null, Description varchar (100) not null, pk_lineas constraint primary key (id, order) fk_lineas constraint foreign key (id) references header) go

/ * We put 100 seats in addition * / declare @ i int set @ i = 0 while @ i <100 begin default values insert into header select @ i = @ i +1 end go / * And two lines * / / lines insert into values (1.1, 'This is a test') lines insert into values (1.2, 'This is a test line 2') go select * from header - 100 rows This is normal, the system will return the 100 rows of the header, go select * from header lines on inner join cabecera.id = lineas.id - 2 rows!! But now returns only two, a single head has lines with two lines, both those that are returned in the two tables, coinciding its id, this results in two lines only. But we can return all the headers, and those who do not have lines, then we return null, this is called 'external joins' and serve to resolve the problem precisely non-header lines. go select * from left join header lines on cabecera.id = lineas.id - 101 rows The result will be 101 rows, with all values null lines of the table, those that have no related records. Appears more than one row headers that a header has two lines, so that header will appear twice. go select * from left join header lines on cabecera.id = lineas.id WHERE lineas.id is null - 99 rows = 101 -2 rows. We can also by statements like the above you have to find all the headers that has no lines, we know that if there are no lines, the field lines linking header is null, there will be, so we force this to happen with the predicate ' Where lineas.id is null ' Other issues might also be optional external relations, in our example, we add an area, which will be optional, may be indicated for this header or not. Unless stated to be a null value in the bedside table, but if indicated, must exist, then the script to create this relationship. alter table add header int idZona go create table zones (idzona int identity (1.1) not null primary key, name varchar (100) not null) go alter table add constraint fk_CabZonas header foreign key (idZona) references parts (idzona) go Insert a record in areas insert into parts values ('South East') select @ @ identity Inserted Zone 1

However there are already 100 headers with zone = null and that is no problem, except that we want to get the name of the header. select * from header c inner join on c.idzona = zonas.idzona areas Also return zero records, so again we have to use left join. As comments add to sql-server also supports a different notation of inner join, left join and right join, based on the where condition put an * next to just one of the conditions, but also less clear in my opinion, is not naming ANSI SQL-server that may not support in future versions.

What is an Index?
An index (or KEY or INDEX) is a MySQL data associated with one or more columns of the table. This data set shows the relationship between content and the row number where it is located. -Index and the indexes of books, serve to streamline the consultation to the tables, mysql avoiding having to review all data available to return the result. We can create the index while creating the table, using the word INDEX followed by the name of the index to create and columns to index (which may be several): INDEX index_name (columna_indexada, columna_indexada2 ...) The syntax is slightly different according to class index: PRIMARY KEY (nombre_columna_1 [, ...]) nombre_columna2 UNIQUE INDEX index_name (columna_indexada1 [, ...]) columna_indexada2 INDEX nombre_index (columna_indexada1 [, ...]) columna_indexada2

We can also add a table created after: ALTER TABLE tbl_name ADD INDEX index_name (columna_indexada); If you want to delete an index: ALTER TABLE DROP INDEX index_name tabla_nombre What are they? Index LOs allow faster execution of queries to the database SELECT ... WHERE The basic rule is thus create your indexes on those columns that are going to use a WHERE clause and not create them with those columns that will be a SELECT: SELECT tabla_libros text from WHERE author = Vazquez; In this example, the author is a good candidate for a column index, the text, no. Another basic rule is that they are better candidates to index those columns that have many different values, while they are not good candidates that have many identical values such as gender (male and female) for each query will always involve almost half of the tour index. The rule of the left If you need to select the type a SELECT ... WHERE AND columna_2 column_1 = X = Y and we have an INDEX with column_1, we create a second index in column 2, or better yet, create a single index combined with columns 1 and 2. These are the multi-column indexes, or compounds.

However if you have multi-column indexes and use them in the WHERE clauses, you should always include from left to right the indexed columns, or the index will not be used: Suppose a user INDEX (id, name, address), and a SELECT clause ... WHERE NAME = x. Select not take advantage of this index. Nor would a SELECT ... WHERE AND ADDRESS ID = X = Y. Any query that includes a column of the index without also include columns on your left, you will not use the index. So in our example would benefit from the index only SELECT queries ... WHERE ID = x, or X AND WHERE ID = NAME = I WHERE ID = x AND NAME AND ADDRESS = y = Z When an index contains more than one column, each column is read by the ordering of left to right, for practical purposes, each column (in that order) is as if it were its own index. This means that in the example above, would not need to create another ID INDEX (id) and we could use our USER INDEX SELECT clause simply ... WHERE ID = X; You can see if your sql call or not to use the correct indexes to select the order putting explain: EXPLAIN SELECT * FROM mytable WHERE .... And to be honest, using EXPLAIN to check the use of indices in different selects with multicolumn indexes, I have obtained inconsistent results with the 'rule of the left' because in many cases it seems that using indices that theoretically there should be available. .. possibly a case of bad settings on my board-test Types of index In some databases there are differences between KEY and INDEX. Not so in MySQL which are synonymous. An index that it is special is called the PRIMARY KEY. This is an index designed to consultations particularly fast. All fields must be unique and does not allow NULL A UNIQUE index is one that can store two values are not equal. FULL TEXT indexes allow word searches. You can create FULLTEXT indexes on columns CHAR, VARCHAR or TEXT. Once created you can search like: SELECT * FROM table_name WHERE MATCH (nombre_indice_fulltext) AGAINST ('palabra_a_buscar'); Some limitations of fulltext indexes: only looks for whole words. index not find indices. No indexing words less than four letters. Not indexed columns that contain less than three rows, or words that appear in half or more of the rows. Hyphenated words are counted as two words. The standard indicators are not restricted as to the existence of identical values or zero. An interesting possibility, if we create an index on CHAR and VARCHAR columns is to limit the field to be indexed. For example, each entry in the column can be up to 40 characters and we only indexes the first 10 of each. To create these rates simply indicate in brackets the number of characters to be indexed after the name of the column: ALTER TABLE books ADD idx_autor INDEX (name (10), surname (10));

Disadvantages of indices The indexes are updated each time you change the column or columns used. It is therefore not advisable to use as indexes columns that are frequent write operations (INSERT, UPDATE, DELETE). Neither would it make sense to create indexes on columns where any select on them to return a large number of results, for example a Boolean column that supports the values Y / N. In short, it is not necessary to use indexes in tables too small, since in these cases there is no speed gain compared to a normal query. Finally, An index allows access to data much faster but indexes take up space. Sometimes even more than the data table. Indexes We have three types of indexes. The first is the primary key, as we saw, can also be created in the column definition. Primary Keys The syntax for defining primary keys is: definicin_columnas | PRIMARY KEY (index_nombre_col ,...) The previous example we saw to create primary keys, using this syntax looks like this: mysql> CREATE TABLE ciudad4 (name CHAR (20) NOT NULL, -> INT NULL DEFAULT population 5000, -> PRIMARY KEY (name)); Query OK, 0 rows affected (0.17 sec) But this way has more options, for example, the brackets can specify multiple column names, primary keys to construct consisting of several columns: mysql> CREATE TABLE mitabla1 ( -> Id1 CHAR (2) NOT NULL, -> Id2 CHAR (2) NOT NULL, -> Text CHAR (30), -> PRIMARY KEY (id1, id2)); Query OK, 0 rows affected (0.09 sec) mysql> Indexes The second type of index used to define indexes on a column of several, or parts of columns. To define these indices are used interchangeably KEY or INDEX options. mysql> CREATE TABLE mitabla2 ( -> Id INT, -> Name CHAR (19), -> INDEX (name)); Query OK, 0 rows affected (0.09 sec)

Or the equivalent: mysql> CREATE TABLE mitabla3 ( -> Id INT, -> Name CHAR (19), -> KEY (name)); Query OK, 0 rows affected (0.09 sec) We can also create an index of a column: mysql> CREATE TABLE mitabla4 ( -> Id INT, -> Name CHAR (19), -> INDEX (name (4))); Query OK, 0 rows affected (0.09 sec) This example will use only the first four characters in the column 'name' to create the index. Unique keys The third key to define unique indexes, also on a column, or on various parts of columns. To define unique key indexes using the UNIQUE option. The difference between a unique index and a normal one is that the only not allow the inclusion of repeated rows with keys. The exception is the NULL value, which itself can be repeated. mysql> CREATE TABLE mitabla5 ( -> Id INT, -> Name CHAR (19), -> UNIQUE (name)); Query OK, 0 rows affected (0.09 sec) A primary key is equivalent to a unique key index, where the key value can not take null values. Both the normal range of unique keys as they can take null values. Therefore, the definitions are equivalent: mysql> CREATE TABLE mitabla6 ( -> Id INT, -> Name CHAR (19) NOT NULL, -> UNIQUE (name)); Query OK, 0 rows affected (0.09 sec) Y: mysql> CREATE TABLE mitabla7 ( -> Id INT, -> Name CHAR (19), -> PRIMARY KEY (name)); Query OK, 0 rows affected (0.09 sec) The indexes are used to optimize queries and data searches. Using this it is much faster to locate rows with specific column values, or follow a certain order. The alternative is to search sequentially, large tables that require a long time

También podría gustarte