Para crear una nueva tabla se emplea la sentencia CREATE TABLE.
Se necesita el permiso CREATE TABLE en la base de datos y el permiso ALTER en el esquema en que se crea la tabla. Si las columnas de la instruccin CREATE TABLE se definen como un tipo definido por el usuario CLR, se necesita la propiedad del tipo o el permiso REFERENCES. Si las columnas de la instruccin CREATE TABLE tienen una coleccin de esquemas XML asociada, se necesita la propiedad de la coleccin de esquemas XML o el permiso REFERENCES.
Empezaremos por una sintaxis reducida:
CREATE TABLE [ nbBaseDatos.[nbEsquema].| nbEsquema.]nbTabla ( { <definicion_columna> | < definicion_colCalc > } [ ,...n ] [ <restriccion_tabla> ] [ ,...n ] ) [ ; ] nbBaseDatos Es el nombre de la base de datos en la que se crea la tabla. Debe ser el nombre de una base de datos existente. Si no se especifica nbBaseDatos, se utiliza de manera predeterminada la base de datos actual. El inicio de sesin de la conexin actual debe estar asociado a un Id. de usuario existente en la base de datos especificada por nbBaseDatos, y ese Id. de usuario debe tener permisos CREATE TABLE. nbEsquema Es el nombre del esquema al que pertenece la nueva tabla. nbTabla Es el nombre de la nueva tabla. Los nombres de tablas deben seguir las reglas de los identificadores. nbTabla puede contener un mximo de 128 caracteres excepto para los nombres de tablas temporales locales (nombres precedidos por un nico signo de nmero (#)) que no pueden superar los 116 caracteres. Despus de indicar el nombre de la tabla, entre parntesis definimos, separadas por una coma, cada una de las columnas de la tabla y al final las restricciones a nivel de tabla si las hay.
Definir columnas fsicas
< definicion_columna > ::= nbCol <tipo_dato> [ COLLATE nbIntercalacion ] [ NULL | NOT NULL ] [ [ CONSTRAINT nbRestriccion ] DEFAULT exp_constante ] | [ IDENTITY [( semilla, incremento )] [NOT FOR REPLICATION] ] ] [ ROWGUIDCOL ] [ <restriccion_columna> [ ...n ] ] Como mnimo debemos indicar el nombre de la columna nbCol y su tipo de datos.
Los nombres de columnas deben seguir las reglas de los identificadores y deben ser nicos en la tabla. nbCol puede contener de 1 a 128 caracteres. nbCol se puede omitir en las columnas creadas con un tipo de datos timestamp, en tal caso, si no se especifica nbCol, el nombre de la columna timestamp ser de manera predeterminada timestamp. En cuanto al tipo de dato, esta es la sintaxis:
<tipo_dato> ::= [nbEsquema_tipo. ] nbtipo [ ( precision [ , escala ] | max | [ { CONTENT | DOCUMENT } ] xml_schema_collection ) ] [ nbEsquema_tipo. ] nbtipo nbtipo Especifica el tipo de datos de la columna y nbEsquema_tipo el esquema al que pertenece el tipo. El tipo de datos puede ser uno de los siguientes:
Un tipo de datos del sistema de SQL Server 2005 como los que ya conocemos. Un tipo de alias basado en un tipo de datos del sistema de SQL Server. Los tipos de datos de alias se crean con la instruccin CREATE TYPE para poder utilizarlos en una definicin de tabla. La asignacin NULL o NOT NULL de un tipo de datos de alias puede anularse durante la instruccin CREATE TABLE. No obstante, la especificacin de longitud no se puede cambiar; la longitud del tipo de datos de alias no se puede especificar en una instruccin CREATE TABLE. Un tipo definido por el usuario CLR. Los tipos definidos por el usuario CLR se crean con la instruccin CREATE TYPE para poder utilizarlos en una definicin de tabla. Si no se especifica el parmetro nbEsquema_tipo, el SQL Server Database Engine (Motor de base de datos de SQL Server) hace referencia a nbtipo en el siguiente orden:
El tipo de datos del sistema de SQL Server. El esquema predeterminado del usuario actual en la base de datos actual. El esquema de dbo de la base de datos actual. Precision es la precisin del tipo de datos especificado.
Escala es la escala del tipo de datos especificado.
Max slo se aplica a los tipos de datos varchar, nvarchar y varbinary para almacenar 231 bytes de datos de caracteres y binarios, y 230 bytes de datos Unicode.
INSERCIN DE DATOS
Insertar en una tabla existente INSERT INTO La insercin de nuevos datos en una tabla, se realiza aadiendo filas enteras a la tabla, la sentencia SQL que lo permite es la orden INSERT (o tambin denominada INSERT INTO.
SintaXIS NSERT INTO <Tabla>(campo1,campo2) VALUES (valor1,valor2) Ejemplo. INSERT INTO oficinas (oficina, ciudad) VALUES (26, 'Elx') INSERT INTO oficinas VALUES (27,'Mstoles','Centro',default ,null, default) inserta datos en una tabla existente insert into Empleado(cod_emppleado,nombre) select * from empleadocopia
INSERT INTO(copiar tabla) Copia una tabla existente creando una tabla con la misma estructura Sintaxis SELECT * INTO newtable FROM table1 WHERE <Criterio>
UPDATE La sentencia UPDATE modifica los valores de una o ms columnas en las filas seleccionadas de una nica tabla. Para modificar los datos de una tabla es necesario disponer del privilegio UPDATE sobre dicha tabla. UPDATE [ TOP ( expression ) [ PERCENT ] ] <destino> SET { nbcolumna = { expresion | DEFAULT | NULL } } [ ,...n ] [ FROM{ <origen> }] [ WHERE <condicion> ] [;] <destino> ::= { [nbBaseDatos.[nbEsquema.]| nbEsquema.]nbTablaVista } Con <destino> indicamos la tabla que se va a actualizar. La clusula SET especifica qu columnas van a modificarse y con qu valor, el valor se puede expresar mediante una expresin, la palabra DEFAULT que equivale al valor predeterminado de la columna, o el valor nulo NULL. Las columnas de identidad no se pueden actualizar. Expresin en cada asignacin debe generar un valor del tipo de dato apropiado para la columna indicada. La expresin debe ser calculable basada en los valores de la fila actualmente en actualizacin. Si para el clculo se utiliza una columna que tambin se modifica, el valor que se utilizar es el de antes de la modificacin, lo mismo para la condicin del WHERE. Expresin tambin puede ser una sub consulta siempre y cuanto devuelva un nico valor y cumpla las condiciones anteriormente expuestas. Ejemplo UPDATE oficinas SET ventas = DEFAULT UPDATE oficinas SET ventas = 0, objetivo = 0
Si no queremos actualizar todas las filas de la tabla sino unas cuantas, utilizaremos la clusula TOP, o unas determinadas, utilizaremos la clusula WHERE.
TOP (expresin) [ PERCENT ]
Ejemplo
UPDATE TOP (10) PERCENT oficinas SET ventas = 0;
Cuando el campo de la otra tabla se utiliza para la clusula SET, entonces debemos utilizar la clusula FROM. La clusula FROM permite definir un origen de datos basado en varias tablas, y ese origen ser el utilizado para realizar la actualizacin.
Por ejemplo queremos actualizar el importe de los pedidos con el precio de la tabla productos.
UPDATE pedidos SET importe = cant * precio FROM pedidos INNER JOIN productos ON fab = idfab AND producto = idproducto;
EJERCICIO
Subir un 5% el precio de todos los productos del fabricante QSA. (3 filas afectadas) Poner a cero las ventas y cuota del empleado Luis Garcia, si hay varios con el mismo nombre actualizarlos todos. (1 filas afectadas) Cambiar los empleados de la oficina 40 a la oficina 30
LA SENTENCIA DELETE La sentencia DELETE elimina filas de una tabla. Si se borran todas las filas, o se borra la nica fila de una tabla, la definicin de la tabla no desaparece, slo que la tabla se queda vaca.
DELETE [ TOP ( expression ) [ PERCENT ] ] [ FROM ] <destino> [ FROM <origen>] [ WHERE < condicion>] [; ] <destino> ::= { [nbBaseDatos. nbEsquema. | nbEsquema.]nbTablaVista } Con esta instruccin podemos eliminar una o varias filas de una tabla.
La palabra FROM (la primera) es opcional (originalmente era obligatorio) y no aade funcionalidad slo sirve para introducir el destino. <destino> es el nombre de la tabla de donde queremos eliminar las filas, puede ser un nombre de tabla o un nombre de vista (de momento basada en una slo tabla). La segunda clusula FROM sirve para indicar un origen que permita una condicin de WHERE sobre una tabla diferente de destino. La instruccin bsica sera pues:
Ejemplo DELETE FROM oficinas; DELETE oficinas WHERE region = Este; DELETE FROM empleados FROM empleados INNER JOIN oficinas ON empleados.oficina = oficinas.oficina WHERE region = 'Este';
BORRADO MASIVO - TRUNCATE Si queremos eliminar todas las filas de una tabla podemos utilizar tambin la instruccin TRUNCATE TABLE.
TRUNCATE TABLE [nbBaseDatos.[nbEsquema.]| nbEsquema.]nbTabla [; ] Esta sentencia quita todas las filas de una tabla sin registrar las eliminaciones individuales de filas. Desde un punto de vista funcional, TRUNCATE TABLE es equivalente a la instruccin DELETE sin una clusula WHERE; no obstante, TRUNCATE TABLE es ms rpida y utiliza menos recursos de registros de transacciones y de sistema.
En comparacin con la instruccin DELETE, TRUNCATE TABLE ofrece las siguientes ventajas:
Se utiliza menos espacio del registro de transacciones. La instruccin DELETE quita una a una las filas y graba una entrada en el registro de transacciones por cada fila eliminada. TRUNCATE TABLE quita los datos al cancelar la asignacin de las pginas de datos utilizadas para almacenar los datos de la tabla y slo graba en el registro de transacciones las cancelaciones de asignacin de pginas. Por regla general, se utilizan menos bloqueos. Si se ejecuta la instruccin DELETE con un bloqueo de fila, se bloquea cada fila de la tabla para su eliminacin. TRUNCATE TABLE siempre bloquea la tabla y la pgina, pero no cada fila. Las pginas cero se conservan en la tabla sin excepciones. Despus de ejecutar una instruccin DELETE, la tabla puede seguir conteniendo pginas vacas. Por ejemplo, no se puede cancelar la asignacin de las pginas vacas de un montn sin un bloqueo de tabla exclusivo como mnimo. Si en la operacin de eliminacin no se utiliza un bloqueo de tabla, la tabla contiene muchas pginas vacas. En el caso de los ndices, la operacin de eliminacin puede dejar pginas vacas, aunque la asignacin de estas pginas se puede cancelar rpidamente mediante un proceso de limpieza en segundo plano. Si la tabla contiene una columna de identidad, el contador para dicha columna se restablece al valor de inicializacin definido para ella. Si no se define ningn valor de inicializacin, se utiliza el valor predeterminado 1. Para conservar el contador de identidad, se utiliza DELETE.
Pero no todo son ventajas, no se puede utilizar TRUNCATE TABLE en las siguientes tablas:
Tablas a las que se hace referencia mediante una restriccin FOREIGN KEY (las tablas que entran como principales en una relacin). Tablas que participan en una vista indizada.
Definir una base de datos CREATE DATABASE Estructura interna
Como ya vimos en el primer tema, las bases de datos de SQL Server 2005 utilizan tres tipos de archivos:
Archivos de datos principales (.mdf): Archivo requerido. Archivos de datos secundarios (.ndf): Archivo opcional. Archivos de registro (.ldf): Archivo requerido. Y se deben situar en sistemas de archivos FAT o NTFS. Se recomienda NTFS.
CREATE DATABASE
CREATE DATABASE nbBasedeDatos [ ON [ PRIMARY ] [ <esp_fichero> [ ,...n ] [ , <grupo> [ ,...n ] ] [ LOG ON { < esp_fichero > [ ,...n ] } ] ] [ COLLATE nbintercalacion] [ WITH <external_access_option> ] ] [;] Como vemos la instruccin mnima es:
CREATE DATABASE nbBasedeDatos nbBasedeDatos: Es el nombre de la nueva base de datos. Los nombres de base de datos deben ser nicos en una instancia de SQL Server y cumplir las reglas de los identificadores. Puede tener 128 caracteres como mximo, excepto en un caso que veremos ms adelante.
Con la clusula ON especificamos los ficheros utilizados para almacenar los archivos de datos.
[ ON [ PRIMARY ] [ <esp_fichero> [ ,...n ] [ , <grupo> [ ,...n ] ] <esp_fichero> ::= ( NAME = nbfichero_logico , FILENAME = 'nbfichero_fisico' [ , SIZE = tamao [ KB | MB | GB | TB ] ] [ , MAXSIZE = { max_size [ KB | MB | GB | TB ] | UNLIMITED } ] [ , FILEGROWTH = incremento_crecimiento [ KB | MB | GB | TB | % ] ] ) nbfichero_logico es el nombre que se utiliza para hacer referencia al archivo en todas las instrucciones Transact-SQL. El nombre de archivo lgico tiene que cumplir las reglas de los identificadores de SQL Server y tiene que ser nico entre los nombres de archivos lgicos de la base de datos.
nbfichero_fisico es el nombre del archivo fsico que incluye la ruta de acceso al directorio. Debe seguir las reglas para nombres de archivos del sistema operativo.
Con la clusula SIZE indicamos el tamao original del archivo. Los archivos de SQL Server 2005 pueden crecer automticamente a partir del tamao originalmente especificado. Con FILEGROWTH se puede especificar un incremento de crecimiento y cada vez que se llena el archivo, el tamao aumentar en la cantidad especificada.
Cada archivo tambin puede tener un tamao mximo especificado con MAXSIZE. Si no se especifica un tamao mximo, el archivo puede crecer hasta utilizar todo el espacio disponible en el disco. Esta caracterstica es especialmente til cuando SQL Server se utiliza como una base de datos incrustada en una aplicacin para la que el usuario no dispone fcilmente de acceso a un administrador del sistema. El usuario puede dejar que los archivos crezcan automticamente cuando sea necesario y evitar as las tareas administrativas de supervisar la cantidad de espacio libre en la base de datos y asignar ms espacio manualmente.
MODIFICAR , ADICONAR Y ELIMINAR CAMPOS Aadir campos ALTER TABLE(ADD) Para aadir una nueva columna o restriccin utilizamos la clusula ADD Sintaxis Alter table <nombre tabla> ADD <campo tipo y tamao> ejemplo ALTER TABLE Clientes ADD email varchar(50);
Modificar Campos ALTER TABLE(Column) Para modificar una columna utilizamos la clusula COLUMN Sintaxis Alter table <nombre tabla> ALTER column <campo nuevo(tipo y tamao)> Ejemplo ALTER TABLE Clientes ALTER COLUMN direccion VARCHAR(40);
Eliminar campos ALTER TABLE(DROP COLUMN) Elimina un campo de la tabla Sintaxis ALTER TABLE <nombre tabla> DROP COLUMN <nombre campo a eliminar>; ejemplo ALTER TABLE Clientes DROP COLUMN email;
CREAR UNA VISTA CREATE VIEW Una vista es una tabla virtual que representa los datos de una o ms tablas de una forma alternativa. Para crear una nueva vista se emplea la sentencia CREATE VIEW, debe ser la primera instruccin en un lote de consultas.
Una vista slo se puede crear en la base de datos actual.
Para ejecutar CREATE VIEW, se necesita, como mnimo, el permiso CREATE VIEW en la base de datos y el permiso ALTER en el esquema en el que se est creando la vista.
Sintaxis:
CREATE VIEW [nbEsquema.] nbVista [ (columna [ ,...n ] ) ] AS ( sentencia_select ) [ ; ] nbEsquema Es el nombre del esquema al que pertenece la nueva tabla.
nbVista Es el nombre de la nueva vista. Los nombres de vistas deben seguir las reglas de los identificadores.
sentencia_select Es la instruccin SELECT que define la vista. Dicha instruccin puede utilizar ms de una tabla y otras vistas. Se necesitan permisos adecuados para seleccionar los objetos a los que se hace referencia en la clusula SELECT de la vista que se ha creado. Una vista no tiene por qu ser un simple subconjunto de filas y de columnas de una tabla determinada. Es posible crear una vista que utilice ms de una tabla u otras vistas mediante una clusula SELECT de cualquier complejidad. Tambin se pueden utilizar funciones y varias instrucciones SELECT separadas por UNION o UNION ALL. Una vista puede tener como mximo 1.024 columnas.
Ejemplos:
CREATE VIEW oficinas_este AS SELECT * FROM oficinas WHERE region = Este;
Crea una vista con las oficinas del este.
CREATE VIEW oficinas_empleados AS SELECT oficinas.oficina AS ofi, ciudad, dir, region, objetivo, oficinas.ventas AS ventas_ofi, empleados.* FROM oficinas INNER JOIN empleados ON oficinas.oficina = empleados.oficina; Crea una vista con los datos de todos los empleados y de sus oficinas. En este caso hemos tenido que definir alias de campo porque en el origen de la sentencia SELECT existe duplicidad de nombres.
CREATE VIEW oficinas_EO AS SELECT * FROM oficinas WHERE region = Este; UNION ALL SELECT * FROM oficinas WHERE region = Oeste; Por defecto las columnas de la vista heredan los nombres de las columnas de la sentencia SELECT asociada, pero podemos cambiar estos nombres indicando una lista de columnas despus del nombre de la vista.
CREATE VIEW oficinas_este (Eoficina, Eciudad, Eregion, Edir, Eobjetivo,Eventas) AS SELECT * FROM oficinas WHERE region = Este; Utilizando una lista de columnas ya no tenemos que definir alias de columna en la sentencia SELECT como pasaba en el caso de la vista oficinas_empleados.
Normalmente se utiliza la lista de columnas cuando una columna proviene de una expresin aritmtica, una funcin o una constante; cuando dos o ms columnas puedan tener el mismo nombre, normalmente debido a una combinacin; o cuando una columna de una vista recibe un nombre distinto al de la columna de la que proviene.
En definitiva se puede optar por utilizar la lista de columnas o definir alias de campo en la sentencia SELECT.
Cuando utilizamos una vista en una operacin de actualizacin (INSERT, UPDATE, DELETE), la vista debe ser actualizable, para ello debe seguir las siguientes reglas:
Cualquier modificacin, incluida en las instrucciones UPDATE, INSERT y DELETE, debe hacer referencia a las columnas de una nica tabla base.
Las columnas que se vayan a modificar en la vista deben hacer referencia directa a los datos subyacentes de las columnas de la tabla, es decir que las columnas no se pueden obtener de otra forma, como con una funcin de agregado: AVG, COUNT, SUM, MIN, MAX, GROUPING, STDEV, STDEVP, VAR y VARP, o un clculo.
Las columnas formadas mediante los operadores de conjunto UNION, UNION ALL, CROSSJOIN, EXCEPT e INTERSECT equivalen a un clculo y tampoco son actualizables.
Las columnas que se van a modificar no se ven afectadas por las clusulas GROUP BY, HAVING o DISTINCT.
Las restricciones anteriores se aplican a cualquier subconsulta de la clusula FROM de la vista, al igual que a la propia vista. Normalmente, el Database Engine (Motor de base de datos) debe poder realizar un seguimiento sin ambigedades de las modificaciones de la definicin de la vista a una tabla base.
ELIMINAR UNA VISTA DROP VIEW Para eliminar una vista de una base de datos tenemos la sentencia DROP TABLE. Sintaxis:
DROP VIEW [nbEsquema.]nbVista[ ,...n ] [ ; ] Se eliminan las vista de la base de datos actual. Cuando eliminamos una vista eliminamos su definicin y los permisos asociados a ella.
Se pueden quitar varias vistas en una misma sentencia DROP VIEW escribiendo los nombres de las vistas a eliminar separados por comas.
Para ejecutar DROP VIEW, como mnimo, se necesita el permiso ALTER en SCHEMA o el permiso CONTROL en OBJECT.
Ejemplo:
DROP VIEW oficinas_este, oficinas_EO;
Elimina las vistas oficinas_este y oficinas_EO.
Si eliminamos una tabla mediante DROP TABLE, se deben quitar explcitamente, con DROP VIEW, las vistas basadas en esta tabla ya que no se quitarn por s solas.
DEFINICIN DE NDICE Un ndice es una estructura de datos definida sobre una columna de tabla (o varias) y que permite localizar de forma rpida las filas de la tabla en base a su contenido en la columna indexada adems de permitir recuperar las filas de la tabla ordenadas por esa misma columna. Funciona de forma parecida al ndice de un libro donde tenemos el ttulo del captulo y la pgina donde empieza dicho captulo, en un ndice definido sobre una determinada columna tenemos el contenido de la columna y la posicin de la fila que contiene dicho valor dentro de la tabla.
La definicin de los ndices de la base de datos es tarea del administrador de la base de datos, los administradores ms experimentados pueden disear un buen conjunto de ndices, pero esta tarea es muy compleja, consume mucho tiempo y est sujeta a errores, incluso con cargas de trabajo y bases de datos con un grado de complejidad no excesivo.
TIPOS DE NDICES
NDICE SIMPLE Y COMPUESTO.
Un ndice simple est definido sobre una sla columna de la tabla mientras que un ndice compuesto est formado por varias columnas de la misma tabla (tabla sobre la cual est definido el ndice. Cuando se define un ndice sobre una columna, los registros que se recuperen utilizando el ndice aparecern ordenados por el campo indexado. Si se define un ndice compuesto por las columnas col1 y col2, las filas que se recuperen utilizando dicho ndice aparecern ordenadas por los valores de col1 y todas las filas que tengan el mismo valor de col1 se ordenarn a su vez por los valores contenidos en col2, funcin igual que la clusula ORDER BY vista en el tema de consultas simples. Por ejemplo si definimos un ndice compuesto basado en las columnas (provincia, localidad), las filas que se recuperen utilizando este ndice aparecern ordenadas por provincia y dentro de la misma provincia por localidad.
ndice agrupado y no agrupado,
El trmino ndice agrupado no se debe confundir con ndice compuesto, el significado es totalmente diferente. Un ndice agrupado (CLUSTERED) es un ndice en el que el orden lgico de los valores de clave determina el orden fsico de las filas correspondientes de la tabla. El nivel inferior, u hoja, de un ndice agrupado contiene las filas de datos en s de la tabla. Una tabla o vista permite un solo ndice agrupado al mismo tiempo. Los ndices no agrupados existentes en las tablas se vuelven a generar al crear un ndice agrupado, por lo que es conveniente crear el ndice agrupado antes de crear los ndices no agrupados. Un ndice no agrupado especifica la ordenacin lgica de la tabla. Con un ndice no agrupado, el orden fsico de las filas de datos es independiente del orden indizado.
ndice nico
ndice nico es aquel en el que no se permite que dos filas tengan el mismo valor en la columna de clave del ndice. Es decir que no permite valores duplicados.
VENTAJAS E INCONVENIENTES DE LOS NDICES VENTAJAS La utilizacin de ndices puede mejorar el rendimiento de las consultas, ya que los datos necesarios para satisfacer las necesidades de la consulta existen en el propio ndice. Es decir, slo se necesitan las pginas de ndice y no las pginas de datos de la tabla o el ndice agrupado para recuperar los datos solicitados; por tanto, se reduce la E/S global en el disco. Por ejemplo, una consulta de las columnas a y b de una tabla que dispone de un ndice compuesto creado en las columnas a, b y c puede recuperar los datos especificados del propio ndice.
Los ndices en vistas pueden mejorar de forma significativa el rendimiento si la vista contiene agregaciones, combinaciones de tabla o una mezcla de agregaciones y combinaciones.
INCONVENIENTES
Las tablas utilizadas para almacenar los ndices ocupan espacio. Los ndices consumen recursos ya que cada vez que se realiza una operacin de actualizacin, insercin o borrado en la tabla indexada, se tienen que actualizar todas las tablas de ndice definidas sobre ella (en la actualizacin slo es necesaria la actualizacin de los ndices definidos sobre las columnas que se actualizan). Por estos motivos no es buena idea definir ndices indiscriminadamente.
Consideraciones a tener en cuenta
A la hora de definir ndices se deben de tener en cuenta estas consideraciones:
Hay que evitar crear demasiados ndices en tablas que se actualizan con mucha frecuencia y procurar definirlos con el menor nmero de columnas posible. Es conveniente utilizar un nmero mayor de ndices para mejorar el rendimiento de consultas en tablas con pocas necesidades de actualizacin, pero con grandes volmenes de datos. Un gran nmero de ndices contribuye a mejorar el rendimiento de las consultas que no modifican datos, como las instrucciones SELECT, ya que el optimizador de consultas dispone de ms ndices entre los que elegir para determinar el mtodo de acceso ms rpido. La indizacin de tablas pequeas puede no ser una solucin ptima, porque puede provocar que el optimizador de consultas tarde ms tiempo en realizar la bsqueda de los datos a travs del ndice que en realizar un simple recorrido de la tabla. De este modo, es posible que los ndices de tablas pequeas no se utilicen nunca; sin embargo, sigue siendo necesario su mantenimiento a medida que cambian los datos de la tabla. Se recomienda utilizar una longitud corta en la clave de los ndices agrupados. Los ndices agrupados tambin mejoran si se crean en columnas nicas o que no admitan valores NULL. Un ndice nico en lugar de un ndice no nico con la misma combinacin de columnas proporciona informacin adicional al optimizador de consultas y, por tanto, resulta ms til. Hay que tener en cuenta el orden de las columnas si el ndice va a contener varias columnas. La columna que se utiliza en la clusula WHERE en una condicin de bsqueda igual a (=), mayor que (>), menor que (<) o BETWEEN, o que participa en una combinacin, debe situarse en primer lugar. Las dems columnas deben ordenarse basndose en su nivel de diferenciacin, es decir, de ms distintas a menos distintas.
DEFINIR UN NDICE CREATE INDEX CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX nombre_indice ON <objeto> (columna [ ASC | DESC ] [ ,...n ] ) [ ; ] <objeto> ::= { [nbBaseDatos.[nbEsquema].| nbEsquema.]nbTablaVista } Esta es la sintaxis simplicada de la instruccin CREATE INDEX que permite crear un ndice en una tabla sobre una o varias columnas.
nbBaseDatos Es el nombre de la base de datos. nbEsquema Es el nombre del esquema al que pertenece la tabla/vista. nbTablaVista Es el nombre de la tabla o vista sobre la que se quiere crear el ndice. nombre_indice Es el nombre del ndice que estamos creando. Columna Es el nombre de la columna que forma parte del ndice. Se pueden definir ndices compuestos escribiendo entre parntesis los nombres de las columnas separados por comas. ASC los valores de la columna se ordenarn de forma ASCendente o DESCendente. Por defecto se asume ASC. UNIQUE permite definir un ndice nico (no admite valores repetidos). CLUSTERED el ndice ser agrupado. NONCLUSTERED (valor por defecto) el ndice ser no agrupado.
Ejemplos:
CREATE INDEX I_clientes_nombre ON Clientes (nombre) Crea un ndice no agrupado sobre la columna nombre de la tabla Clientes en la base de datos actual, las filas se ordenarn de forma ascendente.
CREATE INDEX I_clientes_ApeNom ON Clientes (apellidos, nombre) Crea un ndice no agrupado sobre las columnas apellidos y nombre de la tabla Clientes en la base de datos actual, las filas se ordenarn de forma ascendente por apellido y dentro del mismo apellido por nombre.
CREATE INDEX I_clientes_EdadApe ON Clientes (edad DESC,apellidos) Crea un ndice no agrupado sobre las columnas edad y apellidos de la tabla Clientes en la base de datos actual, las filas se ordenarn de forma descendente por edad y ascendente por apellido. Aparecern los clientes de mayor a menor edad y los clientes de la misma edad se ordenarn por apellido (por orden alfabtico).
CREATE CLUSTERED INDEX I_clientes_cod ON Clientes (codigo) Crea un ndice agrupado sobre la columna codigo de la tabla Clientes en la base de datos actual, las filas se ordenarn y almacenarn por orden de cdigo.
CREATE UNIQUE INDEX U_clientes_col ON Clientes (col) Crea un ndice nico sobre la columna col de la tabla Clientes en la base de datos actual, la columna col no podr contener valores duplicados.
ELIMINAR UN NDICE DROP INDEX Para eliminar un ndice tenemos la sentencia DROP INDEX. La instruccin DROP INDEX no es aplicable a los ndices creados mediante la definicin de restricciones PRIMARY KEY y UNIQUE. Para quitar la restriccin y el ndice correspondiente, se tiene que ejecutar un ALTER TABLE con la clusula DROP CONSTRAINT.
Sintaxis simplificada:
DROP INDEX <indice> [ ,...n ] [ ; ] <indice>::= { nbindice ON [nbBaseDatos.[nbEsquema].|nbEsquema.]nbTablaVista } nbBaseDatos Es el nombre de la base de datos. nbEsquema Es el nombre del esquema al que pertenece la tabla/vista. nbTablaVista Es el nombre de la tabla o vista de la que se quiere eliminar el ndice. nbindice Es el nombre del ndice a eliminar.
Ejemplo:
DROP INDEX U_clientes_col ON Clientes; Elimina el ndice U_clientes_col definido sobre la tabla Clientes.
PROGRAMACIN EN TRANSACT SQL (I)
Introduccin Hasta ahora hemos estudiado sentencias SQL orientadas a realizar una determinada tarea sobre la base de datos como definir tablas, obtener informacin de las tablas, actualizarlas; estas sentencias las hemos ejecutado desde el editor de consultas del MSSMS de una en una o a lo sumo una a continuacin de la otra dentro de la misma consulta formando un lote de instrucciones. Las sentencias que ya conocemos son las que en principio forman parte de cualquier lenguaje SQL. Ahora veremos que TRANSACT-SQL va ms all de un lenguaje SQL cualquiera ya que aunque no permita:
Crear interfaces de usuario. Crear aplicaciones ejecutables, sino elementos que en algn momento llegarn al servidor de datos y sern ejecutados. Incluye caractersticas propias de cualquier lenguaje de programacin, caractersticas que nos permiten definir la lgica necesaria para el tratamiento de la informacin:
Tipos de datos. Definicin de variables. Estructuras de control de flujo. Gestin de excepciones. Funciones predefinidas. Elementos para la visualizacin, que permiten mostrar mensajes definidos por el usuario gracias a la clusula PRINT. Estas caractersticas nos van a permitir crear bloques de cdigo orientados a realizar operaciones ms complejas. Estos bloques no son programas sino procedimientos o funciones que podrn ser llamados en cualquier momento. En SQL Server 2005 podemos definir tres tipos de bloques de cdigo, los procedimientos almacenados, los desencadenadores (o triggers) y funciones definidas por el usuario. Nosotros estudiaremos los dos primeros. Empezaremos por los procedimientos almacenados, veremos primero las sentencias para crear y eliminar procedimientos almacenados, luego estudiaremos las instrucciones Transact-SQL ms propias de un lenguaje de programacin nombradas en el tema de Introduccin al Transact-SQL como son por ejemplo los bucles y estructuras condicionales. Estas instrucciones las utilizaremos dentro de procedimientos almacenados pero veremos que tambin nos servirn para definir otros bloques de cdigo. Terminaremos esta unidad de programacin estudiando los disparadores o Triggers muy similares a los procedimientos almacenados que difieren bsicamente en la forma en que entran en funcionamiento.
PROCEDIMIENTOS ALMACENADOS STORE PROCEDURE Un procedimiento almacenado (STORE PROCEDURE) est formado por un conjunto de instrucciones Transact-SQL que definen un determinado proceso, puede aceptar parmetros de entrada y devolver un valor o conjunto de resultados. Este procedimiento se guarda en el servidor y puede ser ejecutado en cualquier momento.
Los procedimientos almacenados se diferencian de las instrucciones SQL ordinarias y de los lotes de instrucciones SQL en que estn precompilados. La primera vez que se ejecuta un procedimiento, el procesador de consultas de SQL Server lo analiza y prepara un plan de ejecucin que se almacena en una tabla del sistema. Posteriormente, el procedimiento se ejecuta segn el plan almacenado. Puesto que ya se ha realizado la mayor parte del trabajo de procesamiento de consultas, los procedimientos almacenados se ejecutan casi de forma instantnea por lo que el uso de procedimientos almacenados mejora notablemente la potencia y eficacia del SQL.
SQL Server incorpora procedimientos almacenados del sistema, se encuentran en la base de datos master y se reconocen por su nombre, todos tienen un nombre que empieza por sp_. Permiten recuperar informacin de las tablas del sistema y pueden ejecutarse en cualquier base de datos del servidor.
Tambin estn los procedimientos de usuario, los crea cualquier usuario que tenga los permisos oportunos.
Se pueden crear tambin procedimiento temporales locales y globales. Un procedimiento temporal local se crea por un usuario en una conexin determinada y slo se puede utilizar en esa sesin, un procedimiento temporal global lo pueden utilizar todos los usuarios, cualquier conexin puede ejecutar un procedimiento almacenado temporal global. ste existe hasta que se cierra la conexin que el usuario utiliz para crearlo, y hasta que se completan todas las versiones del procedimiento que se estuvieran ejecutando mediante otras conexiones. Una vez cerrada la conexin que se utiliz para crear el procedimiento, ste ya no se puede volver a ejecutar, slo podrn finalizar las conexiones que hayan empezado a ejecutar el procedimiento.
Tanto los procedimientos temporales como los no temporales se crean y ejecutan de la misma forma, el nombre que le pongamos indicar de qu tipo es el procedimiento.
Los procedimientos almacenados se crean mediante la sentencia CREATE PROCEDURE y se ejecutan con EXEC (o EXECUTE). Para ejecutarlo tambin se puede utilizar el nombre del procedimiento almacenado slo, siempre que sea la primera palabra del lote. Para eliminar un procedimiento almacenado utilizamos la sentencia DROP PROCEDURE.
ELIMINAR PROCEDIMIENTOS ALMACENADOS Aunque no sabemos todava crear un procedimiento comentaremos aqu la instruccin para eliminar procedimientos y as podremos utilizarla en los dems ejercicios.
DROP {PROC|PROCEDURE} [nombreEsquema.]nombreProcedimiento [,...n ]. Transact-SQL permite abreviar la palabra reservada PROCEDURE por PROC sin que ello afecte a la funcionalidad de la instruccin. Ejemplos:
DROP PROCEDURE Dice_Hola; Elimina el procedimiento llamado Dice_Hola.
DROP PROC Dice_Hola; Es equivalente, PROC y PROCEDURE indican lo mismo.
Para eliminar varios procedimientos de golpe, indicamos sus nombres separados por comas:
DROP PROCEDURE Dice_Hola, Ventas_anuales; Elimina los procedimientos Dice_Hola y Ventas_anuales.
TRANSACT SQL (II) CREAR Y EJECUTAR UN PROCEDIMIENTO CREATE PROCEDURE
Para crear un procedimiento almacenado como hemos dicho se emplea la instruccin CREATE PROCEDURE:
CREATE {PROC|PROCEDURE} [NombreEsquema.]NombreProcedimiento [{@parametro tipo} [VARYING] [= valorPredet] [OUT|OUTPUT] ] [,...n] AS { <bloque_instrucciones> [ ...n] }[;] <bloque_instrucciones> ::= {[BEGIN] instrucciones [END] } Las instrucciones CREATE PROCEDURE no se pueden combinar con otras instrucciones SQL en el mismo lote. Despus del verbo CREATE PROCEDURE indicamos el nombre del procedimiento, opcionalmente podemos incluir el nombre del esquema donde queremos que se cree el procedimiento, por defecto se crear en dbo. Ya que Sqlserver utiliza el prefijo sp_ para nombrar los procedimientos del sistema se recomienda no utilizar nombres que empiecen por sp_. Como se puede deducir de la sintaxis (no podemos indicar un nombre de base de datos asociado al nombre del procedimiento) slo se puede crear el procedimiento almacenado en la base de datos actual, no se puede crear en otra base de datos. Si queremos definir un procedimiento temporal local el nombre deber empezar por una almohadilla (#) y si el procedimiento es temporal global el nombre debe de empezar por ##. El nombre completo de un procedimiento almacenado o un procedimiento almacenado temporal global, incluidas ##, no puede superar los 128 caracteres. El nombre completo de un procedimiento almacenado temporal local, incluidas #, no puede superar los 116 caracteres.
Transact-SQL permite abreviar la palabra reservada PROCEDURE por PROC sin que ello afecte a la funcionalidad de la instruccin.
CREATE PROC Calcula_comision AS Es equivalente a
CREATE PROCEDURE calcula_comision AS @parametro: representa el nombre de un parmetro. Se pueden declarar uno o ms parmetros indicando para cada uno su nombre (debe de empezar por arroba) y su tipo de datos, y opcionalmente un valor por defecto (=valorPredet) este valor ser el asumido si en la llamada el usuario no pasa ningn valor para el parmetro. Un procedimiento almacenado puede tener un mximo de 2.100 parmetros. Los parmetros son locales para el procedimiento; los mismos nombres de parmetro se pueden utilizar en otros procedimientos. De manera predeterminada, los parmetros slo pueden ocupar el lugar de expresiones constantes; no se pueden utilizar en lugar de nombres de tabla, nombres de columna o nombres de otros objetos de base de datos.
VARYING Slo se aplica a los parmetros de tipo cursor por lo que se explicar cuando se expliquen los cursores. OUTPUT | OUT (son equivalentes) Indica que se trata de un parmetro de salida. El valor de esta opcin puede devolverse a la instruccin EXECUTE que realiza la llamada. El parmetro variable OUTPUT debe definirse al crear el procedimiento y tambin se indicar en la llamada junto a la variable que recoger el valor devuelto del parmetro. El nombre del parmetro y de la variable no tienen por qu coincidir; sin embargo, el tipo de datos y la posicin de los parmetros deben coincidir a menos que se indique el nombre del parmetro en la llamada de la forma @parametro=valor.
Procedimiento bsico
CREATE PROCEDURE Dice_Hola AS PRINT Hola; GO - Indicamos GO para cerrar el lote que crea el procedimiento y empezar otro lote. EXEC Dice_Hola; -- De esta forma llamamos al procedimiento (se ejecuta). En este caso, como la llamada es la primera del lote (va detrs del GO) podamos haber obviado la palabra EXEC y haber escrito directamente.
PROGRAMACIN EN TRANSACT SQL (III)
Con un parmetro de entrada (la palabra que queremos que escriba)
CREATE PROCEDURE Dice_Palabra @palabra CHAR(30) AS PRINT @palabra; GO EXEC Dice_Palabra Lo que quiera; EXEC Dice_Palabra Otra cosa; Aqu hemos hecho dos llamadas, una con el valor Lo que quiera y otra con el valor Otra cosa.
Con varios parmetros
Si queremos indicar varios parmetros los separamos por comas.
USE Biblio; --DROP PROC VerUsuariosPoblacion; --La comentamos la primera vez GO CREATE PROCEDURE VerUsuariosPoblacion @pob CHAR(30),@pro CHAR(30) AS SELECT * FROM usuarios WHERE poblacion=@pob AND provincia = @pro; GO EXEC VerUsuariosPoblacion Madrid, Valencia En la llamada podemos indicar los valores de los parmetros de varias formas, indicando slo el valor de los parmetros (en este caso los tenemos que indicar en el mismo orden en que estn definidos) como en el ejemplo anterior, o bien indicando el nombre del parmetro:
EXEC VerUsuariosPoblacion @pob=Madrid, @pro=Valencia Indicar el nombre del parmetro en la llamada tambin nos permite indicar los valores en cualquier orden, la siguiente llamada es equivalente a la anterior, hemos invertido el orden y se ejecuta igual:
EXEC VerUsuariosPoblacion @pro=Valencia, @pob=Madrid En este procedimiento todos los parmetros son obligatorios, no deja llamar con un solo parmetro.
EXEC VerUsuariosPoblacion Madrid Da error.
Con parmetros opcionales
Para definir un parmetro opcional tenemos que asignarle un valor por defecto en la definicin del procedimiento.
DROP PROC VerUsuariosPoblacion2; GO CREATE PROCEDURE VerUsuariosPoblacion2 @pob CHAR(30),@pro CHAR(30)='Madrid' AS SELECT * FROM usuarios WHERE poblacion=@pob AND provincia = @pro; GO EXEC VerUsuariosPoblacion2 Madrid En este caso, en la llamada slo hemos indicado un valor, para el primer parmetro, el paramtro opcional no lo hemos indicado y se rellenar con el valor por defecto que indicamos en la definicin. Lo podemos hacer as porque el parmetro opcional es el ltimo de la lista de parmetros. Cuando el parmetro opcional no es el ltimo la llamada tiene que ser diferente, tenemos que nombrar los parmetros en la llamada, al menos a partir del parmetro opcional.
DROP PROC VerUsuariosPoblacion3; GO CREATE PROCEDURE VerUsuariosPoblacion3 @a CHAR(2),@pob CHAR(30)='Madrid',@pro CHAR(30) AS SELECT * FROM usuarios WHERE poblacion=@pob AND provincia = @pro; GO EXEC VerUsuariosPoblacion3 a,@pro='Madrid' En este caso el parmetro opcional es el segundo de la lista de parmetros, cuando hacemos la llamada no podemos hacer como en otros lenguajes de dejar un hueco:
EXEC VerUsuariosPoblacion3 a, ,'Madrid' Da error. Esta forma da error, debemos utilizar la palabra DEFAULT o indicar el nombre de todos los parmetros que van detrs del opcional.
EXEC VerUsuariosPoblacion3 a,DEFAULT,'Madrid'
PROGRAMACIN EN TRANSACT SQL (IV)
Con parmetros de salida
Un procedimiento almacenado puede tambin devolver resultados, definiendo el paramtro como OUTPUT o bien utilizando la instruccin RETURN que veremos en el siguiente apartado. Para poder recoger el valor devuelto por el procedimiento, en la llamada se tiene que indicar una variable donde guardar ese valor. Ejemplo: Definimos el procedimiento ultimo_contrato que nos devuelte la fecha en que se firm el ltimo contrato en una determinada oficina. El procedimiento tendr pues dos parmetros, uno de entrada para indicar el nmero de la oficina a considerar y uno de salida que devolver la fecha del contrato ms reciente de entre los empleados de esa oficina.
USE Gestion GO CREATE PROC ultimo_contrato @ofi INT, @fecha DATETIME OUTPUT AS SELECT @fecha=(SELECT MAX(contrato) FROM empleados WHERE oficina=@ofi) GO Con @fecha DATETIME OUTPUT indicamos que el parmetro @fecha es de salida, el proceso que realice la llamada podr recoger su valor despus de ejecutar el procedimiento.
En la llamada, para los parmetros de salida, en vez de indicar un valor de entrada se indica un nombre de variable, variable que recoger el valor devuelto por el procedimiento sin olvidar la palabra OUTPUT:
RETURN ordena salir incondicionalmente de una consulta o procedimiento, se puede utilizar en cualquier punto para salir del procedimiento y las instrucciones que siguen a RETURN no se ejecutan. Adems los procedimientos almacenados pueden devolver un valor entero mediante esta orden.
RETURN [expresion_entera]
Expresion_entera es el valor entero que se devuelve. A menos que se especifique lo contrario, todos los procedimientos almacenados del sistema devuelven el valor 0. Esto indica que son correctos y un valor distinto de cero indica que se ha producido un error. Cuando se utiliza con un procedimiento almacenado, RETURN no puede devolver un valor NULL. Si un procedimiento intenta devolver un valor NULL (por ejemplo, al utilizar RETURN @var si @var es NULL), se genera un mensaje de advertencia y se devuelve el valor 0. Si queremos recoger el valor de estado devuelto por el procedimiento la llamada debe ser distinta, y seguir el siguiente modelo:
EXECUTE @variable_donde_recogemos_estado = nombre_procedimiento @par, ... Con el procedimiento del punto anterior no se puede utilizar esta forma de devolver un resultado porque lo que se devuelve es una fecha, no es un valor entero, pero si quisiramos definir un procedimiento que nos devuelva el nmero de empleados de una oficina podramos hacerlo de dos formas:
De la forma normal con un parmetro de salida:
USE Gestion GO CREATE PROC trabajadores @ofi INT, @num INT OUTPUT AS SELECT @num=(SELECT COUNT(*) FROM empleados WHERE oficina=@ofi) GO Para obtener en la variable @var el resultado devuelto por el procedimiento la llamada sera:
DECLARE @var INT; EXEC trabajadores 12, @var OUTPUT Utilizando return en vez de un parmetro de salida:
CREATE PROC trabajadores2 @ofi INT AS RETURN (SELECT COUNT(*) FROM empleados WHERE oficina=@ofi) GO Para obtener en la variable @var el resultado devuelto por el procedimiento la llamada sera:
DECLARE @var INT; EXEC @var= trabajadores2 12 PRINT @var Nos visualiza el nmero de trabajadores de la oficina nmero 12.