Вы находитесь на странице: 1из 226

Unidad 1.

El entorno grfico SSMS


1.1. Introduccin
SQL Server 2005 es un sistema gestor de bases de datos relacionales de Microsoft Corporation orientado a
sistemas medianos y grandes aunque tambin puede rodar en ordenadores personales. SQL Server Management Studio
(SSMS) es la herramienta de SQL Server que permite definir y gestionar todas las bases de datos almacenadas en el
servidor SQL Server 2005.
En este tema veremos cmo utilizar el SQL Server Management Studio para manejar las bases de datos del servidor y
organizaremos el texto en los siguientes puntos:

Instalar SQL Server 2005.

Entrada al SQL Server Management Studio

Las bases de datos: Estructura interna, crear, adjuntar, conectar y desconectar.

Las tablas: crear tablas, definirlas, modificar su contenido, etc.

Relacionar tablas

Las Consultas

Las Vistas

Si no sabes lo que es una base de datos relacional o no tienes conocimientos previos acerca de las bases de datos, puedes
leer una introduccin a las bases de datos en el siguiente bsico

Unidad 1. Bsico: Introduccin a las bases de datos (I)


Objetivos de un SGBD
Un sistema gestor de bases de datos por definicin debe cumplir los siguientes objetivos:

Independencia de los datos.


Recordando uno de los problemas que plantean los ficheros convencionales. La independencia de los datos consiste en
hacer que los programas no sean tan dependientes de la estructura de los datos.
Se han definido dos tipos de independencia:
1. La independencia fsica: consiste en poder modificar la definicin interna de los datos (el esquema interno) sin que
ello suponga una modificacin de los programas existentes.
Por ejemplo, se puede cambiar la ubicacin de la base de datos, o se puede aadir un ndice sobre una tabla para
que las consultas se ejecuten ms rpidamente, sin que eso suponga una variacin en los esquemas externos y
conceptual, por lo que los programas (que utilizan el esquema externo) no se vern afectados.
2. La independencia lgica: consiste en poder cambiar el esquema conceptual sin que ello suponga una modificacin
de los programas existentes.

Por ejemplo podemos aadir un nuevo dato en la tabla de clientes como la direccin de email sin que los esquemas
externos se vean afectados.

Seguridad e integridad.
La seguridad consiste en que los usuarios no puedan acceder a datos sin autorizacin.
Si juntamos toda la informacin de la empresa en un mismo sitio, el SGBD debe tener mecanismos para que cualquier
usuario pueda tener acceso a nicamente la informacin que necesita para las tareas que tiene encomendadas.
Esta seguridad se consigue por medio de los esquemas externos, ya que el usuario slo tiene acceso a su esquema externo
que le proporciona los datos que el administrador ha considerado incluir en ese esquema. Para el usuario no habr ms
datos que estos.
Adems los SGBD tienen mecanismos para definir autorizaciones que pueden ser de distinto tipo: autorizacin de lectura, de
insercin, de actualizacin, autorizaciones especiales para poder variar el esquema conceptual etc.
La integridad se refiere a que la informacin almacenada en la base de datos est libre de errores. Esto no siempre es
posible ya que existen distintos tipos de errores que tienen diferentes soluciones:
* Fallos de hardware. Estos errores no los puede evitar el SGBD pero se pueden subsanar facilitando copias de seguridad y
procesos de recuperacin.
* Fallos del programador. Puede que aparezcan datos errneos en la base de datos como consecuencia de errores en el
programa que genera estos datos. Para evitar al mximo este tipo de errores el sistema debe ser fcil de programar, cuantos
ms controles realice el sistema de forma automtica, menos controles habr que incluir a nivel de programacin por lo que
limitaremos la probabilidad de fallo y los programas deben ser probados con juegos de ensayos bien definidos.
* Fallos del usuario final. El usuario que introduce datos en la base de datos tambin puede cometer errores, el sistema debe
permitir controlar al mximo la informacin que se introduce para limitar el nmero de estos errores, para ello los SGBD
incluyen clusulas de validacin de los datos, validaciones de diferentes tipos que veremos con ms detalle ms adelante.
* Fallos derivados de la concurrencia. Ya que toda la informacin est centralizada y los distintos usuarios acceden a ella de
forma simultnea, pueden ocurrir problemas cuando dos usuarios quieren acceder al mismo dato a la vez. Por ello el SGBD
debe tener establecidos mecanismos para evitar este tipo de problema, bloquear registros, abortar automticamente
transacciones etc.

Redundancia mnima
La redundancia consiste en que exista algn dato repetido en varios lugares.
Por ejemplo si tenemos la direccin del cliente en la factura, en la cuenta contable, en los datos generales del cliente; esto
como ya vimos anteriormente nos producir varios problemas:

la informacin repetida ocupa espacio innecesario.

la variacin de un domicilio supone el variar ese domicilio en todos los lugares donde est almacenado.
o

mayor tiempo de proceso

posibilidad de inconsistencia

Por todo ello hay que evitar al mximo esa redundancia, esto se consigue utilizando herramientas de diseo y obteniendo un
diseo ptimo de la base de datos.

Facilidad de recuperacin de la informacin


Otro objetivo muy importante de un SGBD es el proporcionar al usuario (o programador) unas herramientas potentes de
manejo de datos para que pueda de manera sencilla y rpida, obtener toda la informacin que desea sin que, por ello se
tenga que hacer un programa complejo.
Veremos que el SQL, lenguaje empleado para recuperar informacin de la base de datos, es un lenguaje muy potente y
cercano al lenguaje hablado, y adems los SGBD incluyen entornos grficos sencillos de utilizar.

El administrador de la base de datos


El administrador es el encargado de gestionar y controlar todo el sistema con la ayuda que le proporciona el SGBD. Tiene
una gran responsabilidad ya que de l depende que el sistema funcione correctamente y como tiene el mximo nivel de
privilegios, sus errores pueden ser desastrosos.
Entre sus responsabilidades se incluye:

Instalar el SGBD en el sistema informtico (a veces).

Realizar el diseo de la base de datos.

Crear las bases de datos que se vayan a gestionar.

Crear y mantener los esquemas de las bases de datos.

Crear y mantener las cuentas de los usuarios de las bases de datos.

Colaborar con el administrador del sistema en las tareas de ubicacin, dimensionado y control de los archivos y
espacios de disco ocupados por el SGBD.

Establecer estndares de uso, polticas de acceso y protocolos de trabajo diario para los usuarios de las bases de
datos.

Efectuar tareas de explotacin como:


o

Vigilar el trabajo diario colaborando en la resolucin de las dudas de los usuarios.

Controlar los tiempos de acceso, tasas de uso, cargas en los servidores, anomalas, etc.

Llegado el caso, reorganizar las bases de datos.

Disear y efectuar el planning de copias de seguridad peridicas.

Restaurar la base de datos despus de un incidente.

Estudiar las auditoras mediante el ajuste de parmetros y con ayuda de las herramientas de monitorizacin
del sistema y de las estadsticas.

El diccionario de datos
Dentro del SGBD, hay una parte que son datos sobre los datos, es una base de datos en la que se almacena toda la
informacin necesaria para que el sistema funcione. Esta base de datos es el diccionario de datos y contiene:

La estructura lgica y fsica de la base de datos.

Las definiciones de todos los objetos de la base de datos: tablas, vistas, ndices, disparadores (triggers) funciones,
procedimientos almacenados, etc.

El espacio asignado y utilizado por los objetos.

Los valores por defecto de las columnas de las tablas.

Los privilegios otorgados a los usuarios.

Informacin que permita obtener estadsticas y evaluaciones del rendimiento del sistema.

Tipos de bases de datos


Podemos realizar distintas clasificaciones de las bases de datos:

Segn su ubicacin

Segn la organizacin lgica de la informacin.

Tipos de bases de datos segn su ubicacin


1. Bases de datos locales.
En modo local tenemos la base de datos y el usuario ubicados en el mismo ordenador. Un ejemplo de base de datos que
funciona en modo local es Microsoft Access, MS Access es una base de datos fcil de manejar por usuarios poco expertos
que funciona bien en modo local y mientras no tenga que albergar grandes cantidades de informacin.

Ventajas

Economa
Es la ms barata.

Simplicidad
No se necesita llevar controles de accesos concurrentes, de
transmisin de datos, etc.

Desventajas
Monousuario
En un instante determinado slo la puede utilizar una
persona.

Capacidad
Suele tener una capacidad de almacenamiento limitado.

2. Bases de datos centralizadas


En los sistemas centralizados tenemos la base de datos completa en un mismo servidor, y todos los usuarios acceden a ese
servidor. Que la base de datos est en un mismo servidor no implica que est en un solo archivo o en el mismo disco, puede
estar repartida.

En modo Cliente/Servidor, la base de datos se encuentra en un ordenador (el Servidor) y los usuarios acceden
simultneamente a esa base de datos a travs de la red (sea una red local o Internet) desde sus ordenadores a travs de un
programa Cliente.
A nivel de empresas es el sistema que ms se utiliza en la actualidad.
Ventajas

Desventajas

Multiusuario

Complejidad

Permite que varios usuarios accedan a la vez a la misma

Tiene que incluir y gestionar un sistema de usuario y

informacin.

subesquemas.

No redundancia

Seguridad

Al estar todos los datos en el mismo servidor, la informacin Se tienen que realizar controles para garantizar la seguridad
no se duplica y es ms facil evitar fallos debidos a

de los datos, tanto a nivel interno como a nivel de

redundancias.

comunicaciones.

3. Bases de datos distribuidas


Tenemos la informacin repartida en distintas localizaciones unidas todas ellas mediante red y un sistema gestor de bases
de datos distribuidas.
Las distintas localizaciones suelen ser distintas geogrficamente.

Ventajas

Desventajas

Rendimiento

Complejidad en el diseo de datos

Una clara ventaja es que es posible ubicar los datos en

Adems de las dificultades que generalmente se encuentran

lugares donde se necesitan con ms frecuencia, aunque

al disear una base de datos, el diseo de una base de datos

tambin se permita a usuarios no locales acceder a los datos distribuida debe considerar la fragmentacin, replicacin y
segn sus necesidades. Esto hace que la informacin se

ubicacin de los fragmentos en sitios especficos, se tiene

recupere de forma ms rpida y gil en las ubicaciones

que trabajar tomando en cuenta su naturaleza distribuida, por

locales. Adems los sistemas trabajan en paralelo, lo cual

lo cual no podemos pensar en hacer joins que afecten a

permite balancear la carga en los servidores.

tablas de varios sistemas, etc.

Disponibilidad

Complejidad tcnica

En caso de que falle la base de datos de alguna localidad, el Se debe asegurar que la base de datos sea transparente, se
sistema no se colapsa, puede seguir funcionando excluyendo debe lidiar con varios sistemas diferentes que pueden
los datos de la localidad que haya fallado.

presentar dificultades nicas.

Autonoma local

Economa en el mantenimiento

Un departamento puede controlar los datos que le

La complejidad y la infraestructura necesaria implica que se

pertenecen.

necesitar mayor mano de obra.

Economa en la implantacin

Seguridad

Es ms barato crear una red de muchas mquinas pequeas, Se debe trabajar en la seguridad de la infraestructura as
que tener una sola mquina muy poderosa.

Modularidad
Se pueden modificar, agregar o quitar sistemas de la base de
datos distribuida sin afectar a los dems sistemas (mdulos).

como cada uno de los sistemas.


Integridad
Se vuelve difcil mantener la integridad, aplicar las reglas de
integridad a travs de la red puede ser muy caro en trminos
de transmisin de datos.
Falta de experiencia
Las bases de datos distribuidas son un campo relativamente
nuevo y poco comn por lo cual no existe mucho personal
con experiencia o conocimientos adecuados.
Carencia de estndares
An no existen herramientas o metodologas que ayuden a
los usuarios a convertir un DBMS centralizado en un DBMS
distribuido.

Tipos de bases de datos segn la organizacin lgica de los datos


En un principio existan tres tipos de bases de datos segn su estructura interna (la manera de organizar la informacin):
Bases de datos jerrquicas
Bases de datos en red
Bases de datos relacionales.
Ms recientes son las bases de datos orientadas a objetos y las bases de datos multidimensionales.

1. Las bases de datos jerrquicas


En una base de datos jerrquica se organizan los datos utilizando estructuras arborescentes (en rbol).
Un RBOL es una estructura jerrquica en la que los elementos se suelen denominar NODOS y existen dependencias entre
los nodos.
La dependencia es de 1:M del tipo padre/hijo. Un hijo no puede tener ms de un padre, pero un padre varios hijos.

Un ejemplo de base de datos jerrquica es el sistema IMS.

2. Las bases de datos en red


Tambin en desuso, en una base de datos en red se utiliza la estructura de grafo/red, como en el caso anterior los distintos
objetos estn relacionados entre s mediante relaciones del tipo 1:M pero en este caso un objeto puede estar relacionado
como hijo con varios elementos que sern sus padres. Un este caso las relaciones que se crean se denominan SET y el
equivalente al padre se denomina PROPIETARIO (OWNER) y el equivalente al hijo se denomina MIEMBRO (MEMBER).
Un ejemplo de sistema en red es el CODASYL. Tambin existen modelos para realizar el diseo de datos orientado a bases
de datos en red.
En red podramos representar lo mismo que la estructura anterior y adems lo siguiente:

Los sistemas jerrquico y en red constituyen la primera generacin de los SGBD. Pero estos sistemas presentan algunos
inconvenientes:

Es necesario escribir complejos programas de aplicacin para responder a cualquier tipo de consulta de datos, por
simple que sta sea.

La independencia de datos es mnima.

No incluyen controles de integridad.

Por lo que pronto fueron sustituidos por los sistemas relacionales.

3. Las bases de datos relacionales


Esta es la estructura que se ha impuesto para aplicaciones de gestin, consiste en organizar los datos en forma de tablas,
las relaciones entre los objetos se consiguen incluyendo en la tabla del hijo, la clave del objeto padre. Como son las que
utilizaremos durante todo el mdulo hemos reservado un apartado especial para ellas.

4. Las bases de datos orientadas a objetos


Es un modelo ms reciente, trata de almacenar en la base de datos los objetos completos (estado y comportamiento). La
informacin que contienen se organiza en atributos y el comportamiento en operaciones.

5. Las bases de datos mutidimensionales


En una base de datos multidimensional los datos se almacenan en tablas de mltiples dimensiones en vez de tablas
bidimensionales como las del modelo relacional. Se utilizan para grandes volmenes de informacin.

La base de datos relacional


Elementos de una base de datos relacional

Los datos se organizan en relaciones compuestas por tuplas de atributos. Si convertimos esta definicin a tablas
tenemos que los datos se organizan en tablas compuestas por filas (registros) y columnas (campos).

A cada tabla se le asigna un nombre nico.

Una tabla tiene 0 o ms filas, y cada fila contiene la informacin de un determinado sujeto de la relacin.

Las filas en un principio estn desordenadas.

La lista de los atributos dispuestos en un orden especfico de izquierda a derecha y que forman la definicin de una
tabla se denomina esquema de la tabla, mientras que los valores concretos de los datos que estn almacenados en
la tabla se llaman ocurrencias.

Por ejemplo, tenemos estas dos tablas:

El esquema de la tabla Piezas est compuesto por las columnas (Codigo, Denominacin, Precio, Fabricante,
Codigo_segn_fab).
Codigo es el cdigo de la pieza, Denominacion el nombre de la pieza, Fabricante el cdigo del fabricante que nos suministra
la pieza y Cdigo_segn_fab el cdigo que utiliza ese fabricante para identificar la pieza en su sistema de gestin.
Una ocurrencia de fila de la tabla Piezas sera:1, Taburete 3 patas, 25, Fab1, T123-34.

Todos los valores de una columna determinada tienen el mismo tipo de datos, y stos estn extrados de un
conjunto de valores legales llamado dominio de la columna. Muchas veces el dominio se corresponder con un tipo
de datos estndar del sistema.
Por ejemplo en la tabla Piezas la columna Codigo est definida sobre el dominio de los enteros.

A parte de los valores del dominio, la columna puede contener un valor especial, el valor nulo. El valor nulo (NULL)
es importante porque representa la ausencia de valor en el campo y no es lo mismo que el valor cero 0 o la cadena
vaca o espacios en blanco. De hecho es un valor tan especial que no funciona como los dems valores, por ejemplo
no podemos comparar (con el operador de comparacin =) un campo con el valor nulo, tenemos que utilizar un
operador especial (IS NULL). Incluso se han tenido que redefinir los operadores lgicos para tener en cuenta el valor
nulo.
Ej. En la tabla Fabricantes el campo direccin de la primera fila contiene el valor nulo (null) esto significa que este
fabricante no tiene direccin (al menos conocida).

En una tabla cada columna tiene un nico nombre y ste no se puede utilizar para nombrar otra columna de la
misma tabla pero s de otra tabla.
Por ejemplo en la tabla Piezas no se pueden definir dos columnas llamadas Codigo, por eso el segundo cdigo lo
hemos llamado Codigo_segun_fab. Pero en la tabla Fabricantes la columna IdFab se poda haber llamado Codigo
sin problema.

En una tabla no se admiten dos filas con los valores coincidentes en todos sus campos. Esta restriccin no se suele
cumplir.
Esta regla nos dice que por ejemplo en la tabla Fabricantes no pueden haber dos filas con los valores Fab1,
Muebles la Madera, null.
Realmente sera informacin redundante, por eso la existencia de esta regla, no obstante en algunos casos muy
concretos s es necesario poder almacenar dos ocurrencias de fila idnticas, por esta razn muchos SGBD no
cumplen esta regla.

Toda tabla debe tener una clave principal (clave primaria).


Una clave primaria es cualquier una columna (o combinacin de columnas) que permite identificar de forma unvoca
cada una de las filas de la tabla. Para que pueda cumplir su cometido, la clave primaria no puede contener
valores nulos ni valores duplicados (no podr haber dos filas con el mismo valor en este campo). Hay SGBD que
incluyen el concepto de clave primaria pero no la hacen obligatoria, por lo que en estos sistemas se pueden definir
tablas sin clave primaria.

En una tabla pueden existir ms de una columna que permita identificar las filas de la tabla, si queremos utilizar tales
columnas como identificadores las definiremos como claves secundarias (alternativas). Una clave secundaria tiene
las mismas restricciones que una clave primaria, pero como no podemos definir dos claves primarias, definimos la
que se vaya a utilizar ms frecuentemente como clave primaria y la otra (u otras) como secundarias.
Por ejemplo en la tabla Piezas la clave primaria es el campo Codigo ya que no hay ni puede haber dos piezas con el
mismo cdigo. Este campo realmente sirve para identificar las filas de la tabla, sabiendo un valor de cdigo (por
ejemplo el 2) sabremos que nos referimos a la fila de la mesa ovalada.
En esta misma tabla tenemos una posible clave alternativa, la formada por los campos Fabricante y
Codigo_segun_fab ya que en la tabla Piezas es imposible tener dos filas con la misma combinacin de valores en
estos campos (el cdigo_segun_fab es el cdigo que utiliza el fabricante para identificar sus piezas).

Otro concepto muy importante, fundamental en las bases de datos relacionales, es la clave ajena (externa o
fornea).
Una clave ajena es un campo (o combinacin de campos) que contiene la referencia a una fila de otra tabla, tambin
puede referirse a la misma tabla. En otras palabras, es un campo que seala a un registro de otra tabla, contiene un
valor que identifica un registro de la otra tabla. Son los campos que se utilizan para relacionar las tablas entre s.
Una tabla puede tener 0, una o varias claves ajenas (externas, forneas).

Una clave ajena puede contener valores duplicados y valores nulos.


Siguiendo el ejemplo anterior, en la tabla Piezas tenemos la clave ajena Fabricante ya que en este campo nos
guardamos un valor que seala a una fila de la tabla Fabricantes, en este campo tenemos el cdigo del fabricante
que nos suministra la pieza y este cdigo nos lleva al fabricante correspondiente en la tabla Fabricantes.
Por ejemplo la pieza 3 es servida por el fabricante Fab2, valor que seala al fabricante Maderas Asociados.

El SGBD deber velar por la integridad de los datos, para ello incluye varias reglas de integridad que se
comprobarn de forma automtica sin necesidad de la intervencin externa de los usuarios o de los programas de
aplicacin.
Existen distintos tipos de reglas de integridad:

10

La integridad de entidades (integridad de claves): Toda tabla debe tener una clave primaria que permite
identificar unvocamente los registros que contiene, por lo tanto no puede contener el valor nulo ni valores
duplicados.
En el ejemplo anterior si intentamos insertar una nueva pieza con el cdigo 2, el sistema no nos dejar
porque ya hay una pieza con este mismo cdigo en la tabla.

La integridad referencial: En una clave ajena no puede haber un valor no nulo que no exista en la tabla de
referencia. Para que no existan errores de integridad referencial en la base de datos, el sistema comprueba
automticamente que los valores introducidos en las claves ajenas existan en el campo de referencia en la
otra tabla, si no existe, no nos dejar insertar el registro.
Volviendo al ejemplo anterior, si intentamos insertar una pieza con un cdigo de fabricante que no existe en
la tabla de fabricantes, el sistema no nos dejar.

A nivel de control sobre los datos, el SGBD debe de proporcionar herramientas para poder definir restricciones de
dominio que se comprobarn de forma automtica (se comprueba que el valor introducido en una columna
pertenece al dominio de la columna, al tipo de datos), y reglas de negocio, que son reglas especficas sobre los
datos, en este tipo de reglas entran las reglas de validacin y reglas definidas a nivel superior que veremos ms
adelante.
Una regla de validacin sera por ejemplo que el precio no pueda ser inferior a 10 euros, y una regla de negocio, que
no pueda haber ms de 20 fabricantes.

Un SGBD relacional sigue la arquitectura de tres niveles en la que tenemos en el nivel externo las vistas, en nivel
conceptual el esquema conceptual con la definicin de todas las tablas, columnas que las componen y relaciones
entre ellas, en el nivel interno tenemos la definicin fsica de la base de datos.

Finalmente tenemos para poder manejar la informacin almacenada en la base de datos un lenguaje que cumple las
reglas de Codd, el lenguaje SQL que veremos en prximos temas.

1.2. Instalar SQL Server 2005


Existen diferentes versiones (ediciones) del producto, por lo que es un producto muy verstil, que puede cumplir con las
exigencias de cualquier empresa, puede ser utilizado para gestionar bases de datos en un PC en modo local a gestionar
todo el sistema de informacin de grandes empresas pasando por sistemas que requieran menos potencia y por sistemas
mviles.
Actualmente se utiliza ms en entornos Cliente/servidor con equipos medianos y grandes.
Para realizar este curso te recomendamos instalar la versin gratuita: Express. Puedes descargarla desde la pgina web de
Microsoft, desde el enlace para iniciar descarga. Si quieres ver las diferentes ediciones y sus caractersticas principales visita
el siguiente avanzado
Si la instalacin se realiza a partir del archivo descargado de Internet, la descarga se empaqueta como un nico ejecutable
mediante una tecnologa de instalacin de Microsoft llamada SFXCab. Al hacer doble clic en el .exe se inicia
automticamente el proceso de instalacin.
Tan slo deberemos seguir el asistente. Los puntos ms importantes a tener en cuenta son:

11

Habilitar el SQL Server Management Studio en la instalacin (si no lo est por defecto) cuando nos pregunte qu
componentes deseamos instalar.

Indicar que se trata de una Instancia predeterminada.

1.3. Entrada al SQL Server Management Studio


Aunque trabajemos en modo local, la entrada a la herramienta es la misma. Para empezar entramos a travs del acceso

directo

o a travs de Inicio, Programas, Microsoft SQL Server 2005, SQL Server Management Studio.

Lo primero que deberemos hacer es establecer la conexin con el servidor:

Seleccionamos el nombre del servidor y pulsamos el botn Conectar. Se abrir la ventana inicial del SQL Server
Management Studio (en adelante SSMS):

12

En la parte izquierda tenemos abierto el panel Explorador de Objetos en el que aparece debajo del nombre del servidor con
el

que

estamos

conectados

una

serie

de

carpetas

objetos

que

forman

parte

del

servidor.

En el panel de la derecha se muestra la zona de trabajo, que vara segn lo que tengamos seleccionado en el Explorador de
objetos, en este caso vemos el contenido de la carpeta que representa el servidor ord01.
En la parte superior tenemos el men de opciones y la barra de herramientas Estndar.

Con las siguientes opciones:


1. Nueva consulta

6. Consulta de SQL Server Mobile 11. Resumen

2. Consulta de motor de Base de datos 7. Abrir archivo

12. Explorador de Objetos

3. Consulta MDX de Analysis Services 8. Guardar

13. Explorador de Plantillas

4. Consulta DMX de Analysis Services 9. Guardar todo

14. Ventana de Propiedades

5. Consulta MXLA de Analysis Services 10. Servidores registrados


En caso de que utilices la versin Express, es posible que no dispongas de algunos de stos botones.

1.4. Estructura interna de una base de datos


Antes de empezar tenemos que tener claro cmo se organiza la informacin en una base de datos SQL Server 2005.
Las bases de datos de SQL Server 2005 utilizan tres tipos de archivos:

Archivos de datos principales


En una base de datos SQLServer los datos se pueden repartir en varios archivos para mejorar el rendimiento de la
base de datos.
El archivo de datos principal es el punto de partida de la base de datos y apunta a los otros archivos de datos de la
base de datos. Cada base de datos tiene obligatoriamente un archivo de datos principal. La extensin recomendada
para los nombres de archivos de datos principales es .mdf.

Archivos de datos secundarios


Los archivos de datos secundarios son todos los archivos de datos menos el archivo de datos principal. Puede que
algunas bases de datos no tengan archivos de datos secundarios, mientras que otras pueden tener varios archivos
de datos secundarios. La extensin de nombre de archivo recomendada para los archivos de datos secundarios es
.ndf.
Adems los archivos de datos se pueden agrupar en grupos de archivos. Para cada base de datos pueden
especificarse hasta 32.767 archivos y 32.767 grupos de archivos.

13

Archivos de registro
Los archivos de registro (archivos de log) almacenan toda la informacin de registro que se utiliza para recuperar la
base de datos, el tambin denominado registro de transacciones. Como mnimo, tiene que haber un archivo de
registro por cada base de datos, aunque puede haber varios. La extensin recomendada para los nombres de
archivos de registro es .ldf.

SQL Server 2005 no exige las extensiones de nombre de archivo .mdf, .ndf y .ldf, pero estas extensiones ayudan a
identificar las distintas clases de archivos y su uso.
Cada base de datos tiene al menos 2 archivos (un archivo de datos principal y un archivo de registro) y opcionalmente un
grupo de archivos.
Los archivos de datos y de registro de SQL Server se pueden colocar en sistemas de archivos FAT o NTFS. Se recomienda
utilizar NTFS por los aspectos de seguridad que ofrece. No se pueden colocar grupos de archivos de datos de lectura y
escritura, y archivos de registro, en un sistema de archivos NTFS comprimido. Slo las bases de datos de slo lectura y los
grupos de archivos secundarios de slo lectura se pueden colocar en un sistema de archivos NTFS comprimido.

1.5. Crear una base de datos en SSMS


En el Explorador de objetos, si desplegamos la carpeta Bases de datos nos aparecen Bases de datos del sistema y las
bases de datos de usuario despus de la carpeta Instantneas...

Despus de la instalacin, en la carpeta Bases de datos del sistema se habr creado una especial denominada master se
utiliza como base de datos de usuario por defecto.
Las dems bases de datos forman tambin parte del diccionario de datos y las utiliza el sistema para llevar a cabo su
gestin.

14

Las bases de datos de los usuarios se deben crear preferentemente fuera de la carpeta Bases de datos del sistema.
Para crear una nueva base de datos de usuario nos posicionamos sobre la carpeta Bases de datos y con el botn derecho
del ratn desplegamos el men contextual del que elegimos la opcin Nueva base de datos

Se abre a continuacin el cuadro de dilogo donde definiremos la base de datos que queremos crear:

15

Lo mnimo a introducir ser el campo Nombre de la base de datos, ste es el nombre de la base de datos lgica, la base de
datos a la que nos referiremos dentro del SSMS, a nivel conceptual (en la imagen Mibase).
Esta base de datos est asociada a dos archivos fsicos, en la parte inferior aparecen esos archivos. Para facilitarnos la
tarea, al teclear el nombre de la bd lgica, se rellenan automticamente los nombres de los archivos fsicos, el de datos con
el mismo nombre y el del archivo de registro con el mismo nombre seguido de _log. Estos nombres son los nombres que se
asumen por defecto pero los podemos cambiar, posicionando el cursor en el nombre y cambindolo.
Para cada archivo fsico podemos definir una serie de parmetros como el tipo de archivo (si es de datos o de transacciones
Registro) y su ocupacin inicial (Tamao inicial).
Si no indicamos ninguna ubicacin podemos ver que los guarda en la carpeta del SQL Server/MSSQL.n/MSSQL/DATA.
n representa un nmero que puede variar de una instalacin a otra.

Estos son los archivos mnimos en los que se almacenar la base de datos, pero como ya vimos anteriormente se puede
almacenar en ms archivos, los tenemos que definir todos en esta ventana a continuacin de los dos obligatorios.
Para aadir ms archivos fsicos disponemos del botn Agregar.
Al pulsar el botn Agregar se crea una nueva fila en la tabla de archivos fsicos donde deberemos escribir el nombre del
archivo, su tipo (desplegando la lista podemos elegir entre de datos o de registro) y dems parmetros.

16

Al agregar un nuevo archivo se activa el botn Quitar, siempre que estemos posicionados encima de un archivo secundario
para poder as eliminarlo si lo queremos.
No podemos eliminar ni el de datos primario, ni el de registro inicial.
Si nos fijamos en la zona de la izquierda, vemos que nos encontramos en la pestaa General, podemos cambiar otros
parmetros de la base de datos pulsando en Grupos de archivos o en Opciones:

17

Al final pulsamos en Aceptar y se crear la base de datos.

Aparecer dentro de la carpeta Bases de datos. Si no se ve pulsa en el icono Actualizar

Desde el Explorador de Windows podemos ver que en la carpeta indicada se han creado los archivos fsicos con los
nombres que le hemos indicado.

18

1.6. Adjuntar una base de datos


En ocasiones no necesitaremos crear la base de datos desde cero, porque sta ya estar creada. ste es el caso de los
ejercicios del curso. Para realizarlos, debers adjuntar una base de datos ya existente a tu servidor. Para ello, lo que
tenemos que hacer es pegar los archivos en la ubicacin que queramos, y luego indicar al SQL Server que vamos a utilizar
esta base de datos, de la siguiente manera:
En el Explorador de objetos, sobre la carpeta Bases de datos desplegar el men contextual y elegir Adjuntar...

En la siguiente ventana elegimos la base de datos:

19

Pulsando en Agregar indicamos el archivo de datos primario en su ubicacin y automticamente se adjuntar la base de
datos lgica asociada a este archivo.

Finalmente pulsamos en Aceptar y aparece la base de datos en nuestro servidor.

La opcin Adjuntar slo se utiliza la primera vez, cuando todava no tenemos la base de datos en el disco.

Unidad 1. Ejercicio paso a paso: Adjuntar base de datos


Objetivo
Importar bases de datos al servidor de SQL Server que has instalado.

Ejercicio paso a paso


1. En la carpeta Ejercicios del curso, busca U3_Consultas_simples.zip y GestionA.zip y extrae su contenido en una carpeta
que llamars Bases de datos.
2. Abre el SQL Server Management Studio Express.

20

3. Haz clic con el botn secundario del ratn sobre la carpeta Bases de datos que se encuentra en el Explorador de objetos
del SSMS.
4. En el men contextual, elige Adjuntar...
5. Pulsa el botn Agregar y busca el directorio Bases de datos que contiene las dos bases que has descargado.
6. Selecciona la primera base (Gestion.mdf) y pulsa Aceptar.
7. Pulsa el botn Agregar de nuevo y esta vez selecciona GestionA.mdf. Cambia su nombre lgico (el campo Adjuntar como)
a Gestion. As es como nos referiremos a ella.
8. Si todo va bien, te indicar que se han adjuntado correctamente y las vers en el Explorador de objetos (GestionA y
GestionSimples). Si no las ves, pulsa el botn Actualizar

1.7. Conectar y Desconectar la base de datos


Una vez hemos creado la base de datos o la hemos adjuntado a nuestro servidor, nos daremos cuenta de que no podremos
manipular los archivos de la base desde fuera del gestor SSMS, por ejemplo, desde el Explorador de Windows. Es decir, no
podremos copiar, cortar, mover o eliminar los archivos fuente mdf, ndf y ldf. Si lo intentamos se mostrar un aviso de que la
base de datos est en uso.
sto es as porque SQL Server sigue en marcha, a pesar de que se cierre el gestor. Ten en cuenta que el servidor de base
de datos normalmente se crea para que sirva informacin a diferentes programas, por eso sera absurdo que dejara de
funcionar cuando cerramos el programa gestor, que slo se utiliza para realizar modificaciones sobre la base.
Para poder realizar acciones sobre la base de datos, sta debe estar desconectada. Para ello, desde el SSMS,
desplegamos el men contextual de la base de datos que nos interese manipular y seleccionaremos la opcin Poner fuera
de conexin:

Aparecer un smbolo a la izquierda de la base de datos

indicndonos que la base de datos est desconectada, a partir

de este momento Windows nos dejar manipular los archivos.


Para volver a conectar la base de datos y seguir trabajando con ella, accederemos al mismo men contextual pero
elegiremos la opcin Poner en conexin:

21

El caso ms inmediato en el que puedes necesitar conectar y desconectar la base de datos es copiar a un pendrive los
archivos de las bases que utilizars en los ejercicios para poder trabajar en diferentes ordenadores con ellos. Para aprender
cmo hacerlo, visita el siguiente Ejercicio Trasladar una base de datos a otro equipo.

Unidad 1. Ejercicio paso a paso: Trasladar una base de datos a otro equipo
Objetivo
Copiar una base de datos que est en uso en un servidor, y adjuntarla o actualizarla en otro.

Ejercicio paso a paso


Vamos a suponer que tenemos una base de datos en el servidor de clase y queremos llevarnos la base de datos a
nuestra casa para seguir trabajando con ella.
1. Sabemos que la base de datos est en los archivos fsicos que definimos cuando definimos la base de datos, estos
archivos se localizan en una determina ruta. Esta informacin se encuentra en las propiedades de la base de datos, para
acceder a la ventana de propiedades de la base de datos (parecida la que se abri cuando creamos la base de datos)
utilizamos como siempre el men contextual que nos llevar a la ventana Propiedades de la base de datos:

2. Una vez sabemos la ruta, utilizamos el Explorador de Windows para abrir a la carpeta donde se encuentran los archivos.
3. Volvemos al SSMS y desconectamos la base de datos, como ya hemos visto: Desde el men contextual y eligiendo
Tareas > Poner fuera de conexin.

22

4. Ahora que ya est desconectada, copiamos los archivos desde el Explorador de Windows, por ejemplo, a nuestro
pendrive.
Ya tenemos una copia de la base de datos de clase. Ahora vamos a ver cmo incluirla en el otro ordenador, es decir, en
casa.
- En caso de que la base de datos no exista, debers adjuntarla como ya hemos visto: Desde el men contextual de bases
de datos y eligiendo la Adjuntar...
- En caso de que la base de datos ya exista y lo que quieras sea actualizarla, debers:
1. Desconectar la base existente desde SSMS.
2. Sobreescribir los archivos fsicos por los nuevos que llevas en el pendrive, desde el Explorador de Windows.
3. Volver a conectar la base de datos desde SSMS.
En caso de que tu versin de SQL Server no tenga las opciones Poner en conexin y Poner fuera de conexin, debers
utilizar la opcin Separar... y luego volver a adjuntarla.
Para crear una nueva tabla primero nos tenemos que posicionar en la base de datos donde queremos que se almacene la
tabla, desplegar el men contextual y seleccionar la opcin Nueva tabla.

En la ventana que se abre debemos definir las columnas de la tabla:

A cada columna se le asigna un nombre, un tipo de datos, y opcionalmente una serie de propiedades, en este tema veremos
las bsicas y las dems las veremos con ms detalle cuando veamos la instruccin SQL CREATE TABLE.
De momento no tenemos definida ninguna columna, al teclear un nombre se crea una primera entrada en esta tabla con la
definicin de la primera columna. En la columna Tipo de datos elegimos qu tipo de valores se podrn almacenar en la
columna.

23

1.8. Crear una nueva tabla


Para crear una nueva tabla primero nos tenemos que posicionar en la base de datos donde queremos que se almacene la
tabla, desplegar el men contextual y seleccionar la opcin Nueva tabla.

En la ventana que se abre debemos definir las columnas de la tabla:

A cada columna se le asigna un nombre, un tipo de datos, y opcionalmente una serie de propiedades, en este tema veremos
las bsicas y las dems las veremos con ms detalle cuando veamos la instruccin SQL CREATE TABLE.
De momento no tenemos definida ninguna columna, al teclear un nombre se crea una primera entrada en esta tabla con la
definicin de la primera columna. En la columna Tipo de datos elegimos qu tipo de valores se podrn almacenar en la
columna.

1.9. Tipos de datos

Podemos elegir entre todos los tipos que aparecen arriba.


Algunos tipos no necesitan ms, como por ejemplo el tipo entero (int), y otros se pueden completar con una longitud, como
los tipos alfanumricos:

24

En este ejemplo hemos definido una columna (Codigo) de tipo Entero corto (Smallint), y una columna (Nombre) que
almacenar hasta 20 caracteres alfanumricos (nchar(20)), en este caso la longitud la indicamos en la pestaa Propiedades
de columna en la propiedad Longitud.
Las propiedades de la columna pueden variar dependiendo del tipo de datos de la columna seleccionada, por ejemplo los
campos enteros no tienen la propiedad longitud, ya que el propio tipo define la longitud del campo, en cambio los campos de
tipo numeric o decimal no tiene la propiedad longitud pero s las propiedades escala y precisin, los valores que permiten
definir el tamao del campo.

1.10. Valores nulos


Tambin podemos indicar si la columna permitir valores nulos o no, o bien cambiando la propiedad Permitir valores nulos
que aparece debajo de la propiedad Longitud, o bien simplemente marcando o desmarcando la casilla de la columna
Permitir valores nulos que se encuentra al lado de la columna Tipo de datos. Si la casilla est marcada, el usuario podr no
rellenar el campo cuando inserte una fila de datos en la tabla.
1.11. Columna con contador

25

En la mayora de los sistemas gestores de bases de datos tenemos un tipo de datos de tipo contador, autonumrico,
autoincremental, etc. Este tipo hace que el propio sistema es el encargado de rellenar el campo con un valor que va
incrementando conforme se crean ms filas de datos en la tabla.
Las columnas de este tipo se utilizan normalmente para numerar las filas de la tabla, como no habrn dos filas con el mismo
valor (el sistema se encarga de incrementar el valor cada vez que se crea una nueva fila), estos campos se suelen utilizar
como claves primarias.
En SQL Server 2005 no existe el tipo de datos Contador pero se consigue el mismo funcionamiento asignando a la columna
un tipo de datos numrico y definiendo la columna como columna de identidad.
En las propiedades de la columna marcamos S en la propiedad (Identidad) y a continuacin podemos indicar en qu valor
queremos que empiece el contador (Inicializacin de identidad) y en cunto incrementar cada vez que se cree un nuevo
registro (Incremento de identidad).
Aunque este tipo de columnas se utiliza frecuentemente como clave primaria, SQL Server no le asigna automticamente
esta funcin, la tenemos que definir nosotros mismos, pero s fuerza a que sea una columna sin valores nulos. No se puede
definir ms de una columna de identidad por tabla.

1.12. Clave primaria


Para definir una columna como clave primaria, posicionamos el puntero del ratn sobre la columna, desplegamos el men
contextual y seleccionamos la opcin Establecer Clave principal:

26

Aparecer una llave a la izquierda del nombre, smbolo de las claves principales:

Para definir una clave primaria compuesta por varias columnas, seleccionamos las columnas manteniendo pulsada la tecla
Ctrl y luego seleccionamos la opcin.
Para quitar una clave principal, hacemos lo mismo pero en esta ocasin seleccionamos la opcin Quitar clave principal.

Tambin podemos utilizar el icono de la barra de herramientas.

1.13. Aadir o eliminar columnas


Una vez definidas algunas columnas, si queremos aadir una nueva columna entre dos, nos posicionamos en la segunda y
seleccionamos la opcin Insertar columna del men contextual.

La nueva columna se colocar delante:

Del mismo modo si queremos eliminar la definicin de una columna, nos posicionamos en la columna a eliminar y
seleccionamos la opcin Eliminar columna:

27

O simplemente hacemos clic en la zona a la izquierda del nombre y pulsamos la tecla Supr.
Finalmente guardamos la tabla, nos pedir el nombre de la tabla:

La nueva tabla aparecer en la lista de tablas de la base de datos:

1.14. Modificar la definicin de una tabla


Para entrar a la ventana de definicin de la tabla utilizamos la opcin Modificar de su men contextual (Tambin es posible
que se llame Diseo):

Se abrir la ventana que ya conocemos para definir las columnas de la tabla.

1.15. Insertar datos en la tabla


Ahora que tenemos la tabla creada podemos rellenarla con datos. Para eso debemos abrir la tabla:

28

Se abrir una ventana parecida a esta:

La primera columna sirve para indicarnos el estado de una fila, por ejemplo el * nos
indica que es una nueva fila, esta fila realmente no est en la tabla, nos sirve de contenedor para los nuevos datos que
queremos insertar.
Para insertar una nueva fila de datos slo tenemos que rellenar los campos que aparecen en esa fila (la del *), al cambiar de
fila los datos se guardarn automticamente en la tabla a no ser que alguno infrinja alguna regla de integridad, en ese caso
SQL Server nos devuelve un mensaje de error para que corrijamos el dato errneo, si no lo podemos corregir entonces slo
podemos deshacer los cambios.

1.16. Modificar datos


Para modificar un valor que ya est en una fila de la tabla slo tenemos que posicionarnos en el campo y rectificar el valor.
En cuanto modificamos un valor, la fila aparece con un lpiz escribiendo (ver imagen), este lpiz nos indica que la fila se ha
modificado y tiene nuevos datos por guardar. Al salir de la fila sta se guardar automticamente a no ser que el nuevo valor
infrinja alguna regla de integridad. Si queremos salir de la fila sin guardar los cambios, tenemos que cancelar la actualizacin
pulsando la tecla ESC.

1.17. Eliminar filas


Para eliminar una fila completa, la seleccionamos y pulsamos la tecla Supr o bien desplegamos su men contextual y

seleccionamos la opcin Eliminar.


En cualquiera de los dos casos nos aparece un mensaje de confirmacin.

29

1.18. Relacionar tablas


Como ya hemos visto, en una base de datos relacional, las relaciones entre las tablas se implementan mediante la definicin
de claves ajenas, que son campos que contienen valores que sealan a un registro en otra tabla, en esta relacin as
creada, la tabla referenciada se considera principal y la que contiene la clave ajena es la subordinada.
Desde el entorno grfico del SSMS podemos definir claves ajenas entrando en el diseo de la tabla y desplegando el men
contextual del campo que va a ser clave ajena:

Seleccionamos la opcin Relaciones y se abre la ventana:

Al pulsar el botn que se encuentra en la fila Especificacin de tablas y columnas se abre el dilogo donde definiremos la
relacin:

30

En la parte derecha tenemos la tabla en la que estamos y el campo que va a actuar como clave ajena, slo nos queda elegir
en el desplegable de la izquierda la tabla a la que hace referencia la clave y al seleccionar una tabla, a la izquierda del
campo clave ajena podremos elegir el campo de la otra tabla por el que se relacionarn las tablas. En nuestro caso ser:

De esta forma hemos definido una relacin entre las tablas Facturas y Clientes. Para ver las relaciones existentes entre las
diferentes tablas tenemos los diagramas.
Primero debemos definir el diagrama, para ello seleccionamos la opcin correspondiente:

Si no tenemos todava ningn diagrama creado, nos aparece un mensaje:

Elegimos S y se crea digamos el soporte donde se pintar el diagrama.

31

A continuacin nos aparece el nuevo diagrama ahora si elegimos crear un nuevo diagrama nos preguntar las tablas a
incluir en el diagrama:

Seleccionamos cada una y pulsamos Agregar, cuando hayamos agregado al diagrama todas las que queremos pulsamos en
Cerrar y aparecern en el diagrama las tablas con las relaciones que tengan definidas en ese momento:

La llave indica la tabla principal (padre) y el smbolo infinito seala la tabla que contiene la clave ajena.
En el examinador de objetos en la carpeta Diagramas de base de datos aparecen todos los diagramas definidos hasta el
momento:

Hemos aprendido hasta ahora lo bsico para poder crear una base de datos y rellenarla con tablas relacionadas entre s y
con datos, ahora veamos cmo recuperar esos datos.

32

1.19. Abrir una nueva consulta


Vamos a ver ahora cmo crear consultas SQL y ejecutarlas desde el entorno del SSMS.
Para ello debemos abrir la zona de trabajo de tipo Query, abriendo una nueva consulta, seleccionando previamente el
servidor y pulsando el botn

de la barra de botones o si queremos realizar la consulta sobre un servidor

con el cual todava no hemos establecido conexin, seleccionando de la barra de mens la opcin Nuevo > Consulta de
motor de base de datos:

.
En este ltimo caso nos aparecer el cuadro de dilogo para establecer la conexin (el mismo que vimos al principio del
tema).
A continuacin se abrir una nueva pestaa donde podremos teclear las sentencias SQL:

Adems aparece una nueva barra de botones que nos permitir ejecutar los comandos ms tiles del modo query.

1.20. Escribir y ejecutar cdigo TRANSACT-SQL


Slo tenemos que teclear la sentencia a ejecutar, por ejemplo empezaremos por crear la base de datos.
Utilizaremos la sentencia CREATE DATABASE mnima:

33

CREATE DATABASE ventas;


Al pulsar el botn Ejecutar se ejecuta la sentencia y aparece en la parte inferior el resultado de la ejecucin, en la pestaa
Mensajes:

Si ahora desplegamos la carpeta Bases de Datos del Explorador de Objetos, observaremos la base de datos que hemos
creado:

Si la ejecucin de la sentencia produce un error, el sistema nos devolver el mensaje de error escrito en rojo en la pestaa
Mensajes.
Podemos incluir en una misma consulta varias sentencias SQL, cuando pulsamos Ejecutar se ejecutarn todas una detrs
de otra. Si tenemos varias consultas y slo queremos ejecutar una, la seleccionaremos antes de ejecutarla.

34

1.21. La base de datos predeterminada


Cuando ejecutamos consultas desde el editor, nos tenemos que fijar sobre qu base de datos se va a actuar.
Fijndonos en la pestaa de la consulta, en el nombre aparece el nombre del servidor seguido de un punto y el nombre de la
base de datos sobre la que se va a actuar y luego un guin y el nombre de la consulta.
En la imagen anterior tenemos ord01.master SQLQuery1.sql, lo que nos indica que la consulta se llama SQLQuery1.sql, y
que se va a ejecutar sobre la base de datos master que se encuentra en el servidor ord01.
Cuando creamos una nueva consulta, sta actuar sobre la base de datos activa en ese momento. Por defecto la base de
datos activa es la predeterminada (master). Si queremos que la base de datos activa sea por ejemplo la base de datos
ventas, hacemos clic sobre su nombre en el Explorador de objetos, y sta pasar a ser la base de datos activa. Si ahora
creamos una nueva consulta, sta actuar sobre la base de datos ventas.
Si queremos crear una consulta que siempre acte sobre una determinada base de datos y no nos queremos preocupar de
qu base de datos tenemos activa podemos aadir al principio de la consulta la instruccin USE nombreBaseDatos; esto
har que todas las instrucciones que aparezcan despus, se ejecuten sobre la base de datos indicada.
Por ejemplo:
USE ventas;

SELECT * FROM pedidos;


Obtiene todos los datos de la tabla pedidos que se encuentra en la base de datos ventas.
Si no utilizamos USE y almacenamos la consulta, al abrirla otra vez, coger como base de datos la predeterminada (no la
activa) y se volver a ejecutar sobre la base de datos master.
Normalmente utilizaremos como base de datos la nuestra y no la base de datos master, por lo que nos ser til cambiar el
nombre de la base de datos por defecto, esto lo podemos hacer cambiando la base de datos por defecto en el id de sesin.
Para ello, cuando vamos a conectar con el servidor:

Pulsamos en el botn Opciones >>

35

En la pestaa Propiedades de conexin, en el cuadro Conectar con base de datos: Seleccionamos <Examinar servidor >
para elegir la base de datos.

La elegimos y aceptamos. A partir de ese momento la base de datos elegida ser la que SQL Server coja por defecto en
todas las sesiones de ese usuario.
1.22. El editor de texto
Para facilitarnos la redaccin y correccin de las sentencias, el editor de SQL presenta las palabras de distintos colores
segn su categora y podemos utilizar el panel Explorador de Objetos para arrastrar desde l los objetos sobre la zona de

36

trabajo y as asegurarnos de que los nombres de los objetos (por ejemplo nombre de tabla, de columna, etc.) sean los
correctos.
Como hemos dicho el texto que se escribe en este editor de cdigo se colorea por categora. Los colores son los mismos
que se utilizan en todo el entorno SQL Server. En esta tabla aparecen los colores ms comunes.
Color

Categora

Rojo

Cadena de caracteres

Verde oscuro

Comentario

Negro sobre fondo plateado Comando SQLCMD


Fucsia

Funcin del sistema

Verde

Tabla del sistema

Azul

Palabra clave

Verde azulado

Nmeros de lnea o parmetro de plantilla

Rojo oscuro

Procedimiento almacenado de SQL Server

Gris oscuro

Operadores

1.23. Configurar un esquema de colores personalizado


En el men Herramientas > Opciones, desplegando la opcin Entorno, Fuentes y colores, se puede ver la lista completa de
colores y sus categoras, as como configurar un esquema de colores personalizado:

37

En la lista Mostrar valores para, seleccionamos el entorno que se ver afectado.


El botn Usar predeterminados nos permite volver a la configuracin predeterminada.
Ahora slo nos queda aprender a redactar sentencias SQL, cosa que se ver en otro momento, mientras tanto podemos
utilizar el Generador de Consulta que incluye SSMS y que veremos a continuacin en el apartado sobre vistas.

1.24. Las Vistas


Las consultas que hemos visto hasta ahora son trozos de cdigo SQL que podemos guardar en un archivo de texto y abrir y
ejecutar cuando queramos, pero si queremos que nuestra consulta de recuperacin de datos se guarde en la propia base de
datos y se comporte como una tabla (algo parecido a una consulta almacenada de Access), la tenemos que definir como
una vista. Esta vista tiene la ventaja entre otras de poder ser utilizada como si fuese una tabla en otras consultas. Realmente
al ejecutarla obtenemos una tabla lgica almacenada en memoria y lo que se guarda en la base de datos es su definicin, la
instruccin SQL que permite recuperar los datos.

38

Para definir una vista en el Explorador de Objetos desplegamos la base de datos donde la guardaremos y elegimos la
opcin Nueva vista del men contextual de la carpeta Vistas, se pondr en funcionamiento el generador de consultas
pidindonos las tablas en las que se basar la vista. Pulsamos sobre la tabla a aadir al diseo de la vista y pulsamos el
botn Agregar, podemos aadir as cuntas tablas queramos.
Despus de Cerrar, vemos a la derecha del Explorador de Objetos la pestaa con la definicin de la vista que puede incluir
varios paneles:

39

La aparicin de estos paneles es configurable, en la barra de herramientas Diseador de vistas los iconos remarcados en
azul

son

los

correspondientes

cada

panel:

40

1.25. El panel de diagrama


Es el primero que aparece, incluye una representacin grfica de las tablas con sus campos y de la forma en que se juntan
en la vista. En este caso, como las tablas tienen relaciones definidas (claves ajenas), esta relacin ha aparecido
automticamente al aadir la segunda tabla. Pero se puede cambiar el tipo de relacin eligiendo la opcin correspondiente
en el men contextual que aparece con el clic derecho sobre la relacin:

Desde el panel diagrama podemos aadir cmodamente campos de las tablas a la consulta marcando la casilla
correspondiente. En la imagen anterior la nica casilla seleccionada es la del * en la tabla Libros por lo que se visualizarn
todas las columnas de la tabla Libros y ninguna de la tabla Prstamos.
Conforme vamos marcando casillas de las tablas del panel diagrama, los cambios se ven reflejados en los dems paneles
excepto en el panel de resultados que se actualiza ejecutando la consulta.

1.26. El panel de criterios


Es una rejilla en la que podemos definir las columnas del resultado de la consulta (las columnas de la vista).

En cada fila de la rejilla se define una columna del resultado o una columna que se utiliza para obtener el resultado.

En Columna tenemos el nombre de la columna de la se obtienen los datos o la expresin cuando se trata de una
columna calculada.

En Alias escribimos el nombre que tendr la columna en la vista, tambin corresponde con el encabezado de la
columna en la rejilla de resultado. Si se deja el campo en blanco, por defecto se asume el mismo nombre que hay en
Columna.

En Tabla tenemos el nombre de la tabla del origen de la consulta a la que pertenece la Columna, por ejemplo la
primera columna del resultado se saca de la columna Codigo de la tabla LIBROS y se llamar CodLibro. La cuarta
columna de la vista coger sus datos de la columna Usuario de la tabla Prestamos y se llamar Usuario (Alias se ha
dejado en blanco por lo que asume el nombre que hay en Columna.

41

En la columna Resultados indicamos si queremos que la columna se visualice o no, las columnas con la casilla
marcada se visualizan.

Las columnas Criterio de ordenacin y Tipo de orden permiten ordenar las filas del resultado segn una o ms
columnas. Se ordena por las columnas que tienen algo en Tipo de orden y cuando se ordena por varias columnas
Criterio de ordenacin indica que primero se ordena por la columna que lleva el n 1 y despus por la columna que
lleva el n 2 y as sucesivamente. En el ejemplo las filas del resultado se ordenarn primero por cdigo de libro y
despus por cdigo de prstamo, todas las filas dentro del mismo libro se ordenarn por cdigo de prstamo.

Si queremos aadir unos criterios de seleccin tenemos las columnas Filtro y O

En cada celda indicamos una condicin que debe cumplir la columna correspondiente y se puede combinar varias
condiciones mediante O (OR) e Y (AND) segn coloquemos las condiciones en la misma columna o en columnas diferentes.
En el ejemplo anterior tenemos la condicin compuesta: ((usuario=1) AND (Dias>5)) OR (Usuario=2).
Podemos variar el orden de aparicin de las columnas arrastrando la fila correspondiente de la rejilla hasta el lugar deseado.
Tambin podemos Elimnar filas de la rejilla para eliminar columnas del resultado, lo conseguimos seleccionando la fila
haciendo clic sobre su extremo izquierda y cuando aparece toda la fila remarcada pulsamos Supr o desde el men
contextual de la fila.
Podemos definir consultas ms complejas como por ejemplo consultas de resumen, pulsando sobre el botn Agrupar por de
la barra de herramientas, se aade a la rejilla una nueva columna Agrupar por con las siguientes opciones:

1.27. El panel SQL

42

En l vemos la instruccin SQL generada, tambin podemos redactar directamente la sentencia SQL en el panel y ver los
cambios equivalentes en los distintos paneles. Para ver estos cambios debemos de ejecutar o Comprobar la sintaxis para
que se actualicen los dems paneles.
Por defecto el generador aade a la consulta una clusula TOP (100) PERCENT que indica que se visualizarn el 100% de
las filas. Esta clusula no la hemos definido nosotros sino que la aade automticamente el generador.

Una vez tenemos la vista definida la guardamos y podremos hacer con ella casi todo lo que podemos hacer con una tabla.
De hecho si nos fijamos en el Explorador de objetos, en la carpeta Vistas:

Vemos que la estructura es muy similar a la estrutura de una tabla. Y que podemos modificar su definicin y ejecutarla, igual
que con las tablas:

Modificar para modificar la definicin de la vista

Abrir vista para ejecutarla y ver los datos como si fuese una tabla real.

43

Unidad 2. Introduccin al SQL. Transact-SQL (I)


2.1. Conceptos bsicos de SQL
SQL (Structured Query Language), Lenguaje Estructurado de Consulta es el lenguaje utilizado para definir, controlar y
acceder a los datos almacenados en una base de datos relacional.
Como ejemplos de sistemas gestores de bases de datos que utilizan SQL podemos citar DB2, SQL Server, Oracle, MySql,
Sybase, PostgreSQL o Access.
El SQL es un lenguaje universal que se emplea en cualquier sistema gestor de bases de datos relacional. Tiene un estndar
definido, a partir del cual cada sistema gestor ha desarrollado su versin propia.
En SQL Server la versin de SQL que se utiliza se llama TRANSACT-SQL.
EL SQL en principio es un lenguaje orientado nicamente a la definicin y al acceso a los datos por lo que no se puede
considerar como un lenguaje de programacin como tal ya que no incluye funcionalidades como son estructuras
condicionales, bucles, formateo de la salida, etc. (aunque veremos que esto est evolucionando).
Se puede ejecutar directamente en modo interactivo, pero tambin se suele emplear embebido en programas escritos en
lenguajes de programacin convencionales. En estos programas se mezclan las instrucciones del propio lenguaje
(denominado anfitrin) con llamadas a procedimientos de acceso a la base de datos que utilizan el SQL como lenguaje de
acceso. Como por ejemplo en Visual Basic, Java, C#, PHP .NET, etc.
Las instrucciones SQL se clasifican segn su propsito en tres grupos:

El DDL (Data Description Language) Lenguaje de Descripcin de Datos.

El DCL (Data Control Language) Lenguaje de Control de Datos.

El DML (Data Manipulation Language) Lenguaje de Manipulacin de Datos.

El DDL, es la parte del SQL dedicada a la definicin de la base de datos, consta de sentencias para definir la estructura
de la base de datos, permiten crear la base de datos, crear, modificar o eliminar la estructura de las tablas, crear ndices,
definir reglas de validacin de datos, relaciones entre las tablas, etc. Permite definir gran parte del nivel interno de la base de
datos. Por este motivo estas sentencias sern utilizadas normalmente por el administrador de la base de datos.
El DCL (Data Control Language) se compone de instrucciones que permiten:

Ejercer un control sobre los datos tal como la asignacin de privilegios de acceso a los datos (GRANT/REVOKE).

La gestin de transacciones (COMMIT/ROLLBACK).

Una transaccin se puede definir como un conjunto de acciones que se tienen que realizar todas o ninguna para preservar la
integridad de la base de datos.
Por ejemplo supongamos que tenemos una base de datos para las reservas de avin. Cuando un usuario pide reservar una
plaza en un determinado vuelo, el sistema tiene que comprobar que queden plazas libres, si quedan plazas reservar la que

44

quiera el usuario generando un nuevo billete y marcando la plaza como ocupada. Aqu tenemos un proceso que consta de
dos operaciones de actualizacin de la base de datos (crear una nueva fila en la tabla de billetes y actualizar la plaza
reservada en el vuelo, ponindola como ocupada) estas dos operaciones se tienen que ejecutar o todas o ninguna, si
despus de crear el billete no se actualiza la plaza porque se cae el sistema, por ejemplo, la base de datos quedara en un
estado inconsistente ya que la plaza constara como libre cuando realmente habra un billete emitido para esta plaza. En
este caso el sistema tiene el mecanismo de transacciones para evitar este error. Las operaciones se incluyen las dos en una
misma transaccin y as el sistema sabe que las tiene que ejecutar las dos, si por lo que sea no se pueden ejecutar las dos,
se encarga de deshacer los cambios que se hubiesen producido para no ejecutar ninguna.
Las instrucciones que gestionan las autorizaciones sern utilizadas normalmente por el administrador mientras que las otras,
referentes a proceso de transacciones sern utilizadas tambin por los programadores.
No todos los sistemas disponen de ellas.
El DML se compone de las instrucciones para el manejo de los datos, para insertar nuevos datos, modificar datos
existentes, para eliminar datos y la ms utilizada, para recuperar datos de la base de datos. Veremos que una sola
instruccin de recuperacin de datos es tan potente que permite recuperar datos de varias tablas a la vez, realizar clculos
sobre estos datos y obtener resmenes.
El DML interacta con el nivel externo de la base de datos por lo que sus instrucciones son muy parecidas, por no decir casi
idnticas, de un sistema a otro, el usuario slo indica lo que quiere recuperar no cmo se tiene que recuperar, no influye el
cmo estn almacenados los datos.
Es el lenguaje que utilizan los programadores y los usuarios de la base de datos.
A lo largo del curso se explicarn cada una de las formas de explotacin de la base de datos. Dependiendo de tu perfil
profesional (programador o administrador) o de tu inters personal te resultar ms til un bloque u otro.

2.2. Introduccin al TRANSACT-SQL


Como hemos dicho, el sistema gestor de base de datos SQL-Server 2005 utiliza su propia versin del lenguaje SQL, el
TRANSACT-SQL.
TRANSACT-SQL es un lenguaje muy potente que nos permite definir casi cualquier tarea que queramos efectuar sobre la
base de datos. En este tema veremos que TRANSACT-SQL va ms all de un lenguaje SQL cualquiera ya que 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.

45

Sin embargo no permite:

Crear interfaces de usuario.

Crear aplicaciones ejecutables, sino elementos que en algn momento llegarn al servidor de datos y sern
ejecutados.

Debido a estas restricciones se emplea generalmente para crear procedimientos almacenados, triggers y funciones de
usuario.
Puede ser utilizado como cualquier SQL como lenguaje embebido en aplicaciones desarrolladas en otros lenguajes de
programacin como Visual Basic, C, Java, etc. Y por supuesto los lenguajes incluidos en la plataforma .NET.
Tambin lo podremos ejecutar directamente de manera interactiva, por ejemplo desde el editor de consultas de SSMS (SQL
Server Management Studio) el entorno de gestin que ya conocemos. Esta es la forma en que lo utilizaremos nosotros.

2.3. Caractersticas generales del lenguaje Transact-SQL


El lenguaje SQL se cre con la finalidad de ser un lenguaje muy potente y a la vez muy fcil de utilizar, se ha conseguido en
gran medida ya que con una sola frase (instruccin) podemos recuperar datos complejos (por ejemplo datos que se
encuentran en varias tablas, combinndolos, calculando resmenes), y utilizando un lenguaje muy cercano al lenguaje
hablado (suponiendo que hablamos ingls, claro!).
Por ejemplo:
SELECT codigo, nombre FROM Clientes WHERE localidad=Valencia;
Esta instruccin nos permite SELECCIONAR el cdigo y nombre DE los Clientes CUYA localidad sea Valencia.
La sencillez tambin radica en que lo que indicamos es lo que queremos obtener, no el cmo lo tenemos que obtener, de
eso se encargar el sistema automticamente.
Las sentencias SQL adems siguen todas el mismo patrn:

Empiezan por un verbo que indica la accin a realizar,

completado por el objeto sobre el cual queremos realizar la accin,

seguido de una serie de clusulas (unas obligatorias, otras opcionales) que completan la frase, y proporcionan ms
detalles acerca de lo que se quiere hacer.

Si sabemos algo de ingls nos ser ms fcil interpretar a la primera lo que quiere decir la instruccin, y de lo contrario,
como el nmero de palabras que se emplean es muy reducido, enseguida nos las aprenderemos.
Por ejemplo en el DDL (acciones sobre la definicin de la base de datos), tenemos 3 verbos bsicos:
CREATE (Crear)
DROP (Eliminar)
ALTER (Modificar)

46

Completados por el tipo de objeto sobre el que actan y el objeto concreto:


CREATE DATABASE mibase .......;
Permite crear una base de datos llamada mibase, a continuacin escribiremos las dems clusulas que completarn la
accin, en este caso dnde se almacenar la base de datos, cunto ocupar, etc...
CREATE TABLE mitabla (.....);
Permite crear una nueva tabla llamada mitabla, entre parntesis completaremos la accin indicando la definicin de las
columnas de la tabla.
CREATE INDEX miindex...;
Lo mismo para crear un ndice (a que lo habais adivinado?).
DROP DATABASE mibase;
Permite borrar, eliminar la base de datos mibase.
DROP TABLE mitabla;
Elimina la tabla mitabla.
ALTER TABLE mitabla.....;
Permite modificar la definicin de la tabla mitabla.
En el DML (acciones sobre los datos almacenados) utilizaremos los verbos:
INSERT (Crear, es decir, insertar una nueva fila de datos)
DELETE (Eliminar filas de datos)
UPDATE (Modificar filas de datos)
SELECT (Seleccionar, obtener)
Por ejemplo:
INSERT INTO mitabla ..... Inserta nuevas filas en mitabla
DELETE FROM mitabla Eliminar filas de mitabla
UPDATE mitabla ....... Actualiza filas de mitabla
Como ejemplo de clusula dentro de una instruccin tenemos:
SELECT codigo, nombre
FROM Clientes
WHERE localidad=Valencia;
En esta sentencia nos aparecen dos clusulas, la clusula FROM que nos permite indicar de dnde hay que coger los datos
y la clusula WHERE que permite indicar una condicin de seleccin.
Otra caracterstica de una sentencia SQL es que acaba con un punto y coma (;) originalmente ste era obligatorio y serva
para indicar el fin de la instruccin, pero ahora se puede omitir, aunque se recomienda su uso.

47

En una sentencia utilizaremos palabras reservadas (las fijas del lenguaje), y nombres de objetos y variables
(identificadores).
Las palabras reservadas no se pueden utilizar para otro propsito, por ejemplo una tabla no se puede llamar FROM, y los
nombres (los identificadores) siguen las reglas detalladas en el punto siguiente.
Nombres cualificados. En ocasiones deberemos utilizar nombres cualificados, por ejemplo cuando se escribe un nombre
de tabla, SQL presupone que se est refiriendo a una de las tablas de la base de datos activa, si queremos hacer referencia
a una tabla de otra base de datos utilizamos su nombre cualificado nombrebasedatos.nombredeesquema.nombretabla,
utilizamos el punto para separar el nombre del objeto y el nombre de su contenedor.
O por ejemplo si en una consulta cuyo origen son dos tablas, queremos hacer referencia a un campo y ese nombre de
campo es un nombre de campo en las dos tablas, pues utilizaremos su nombre cualificado nombretabla.nombrecampo.
El valor NULL.
Puesto que una base de datos es un modelo de una situacin del mundo real, ciertos datos pueden inevitablemente faltar,
ser desconocidos o no ser aplicables, esto se debe de indicar de alguna manera especial para no confundirlo con un valor
conocido pero que sea cero por ejemplo, SQL tiene para tal efecto el valor NULL que indica precisamente la ausencia de
valor.
Por ejemplo: no es lo mismo que el alumno no tenga nota a que tenga la nota cero, esto afectara tambin a todos los
clculos que se pueden realizar sobre la columna nota.

2.4. Reglas de formato de los identificadores


Los identificadores son los nombres de los objetos de la base de datos. Cualquier elemento de Microsoft SQL Server 2005
puede tener un identificador: servidores, bases de datos, tablas, vistas, columnas, ndices, desencadenadores,
procedimientos, restricciones, reglas, etc.
Las reglas de formato de los identificadores normales dependen del nivel de compatibilidad de la base de datos, que se
estableca con el parmetro sp_dbcmptlevel pero que ahora Microsoft aconseja no utilizar ya que desaparecer en versiones
posteriores en vez de eso se tiene que utilizar la clusula SET COMPATIBILITY_LEVEL de la instruccin ALTER TABLE.
Cuando el nivel de compatibilidad es 90, (el asignado por defecto) se aplican las reglas siguientes para los nombres de los
identificadores:

No puede ser una palabra reservada.

El nombre debe tener entre 1 y 128 caracteres, excepto para algunos tipos de objetos en los que el nmero es ms
limitado.

El nombre debe empezar por:


o

Una letra, como aparece definida por el estndar Unicode 3.2. La definicin Unicode de letras incluye los
caracteres latinos de la "a" a la "z" y de la "A" a la "Z".

El carcter de subrayado ( _ ), arroba ( @ ) o nmero ( # ).

Ciertos smbolos al principio de un identificador tienen un significado especial en SQL Server. Un identificador que
empieza con el signo de arroba indica un parmetro o una variable local. Un identificador que empieza con el signo

48

de nmero indica una tabla o procedimiento temporal. Un identificador que empieza con un signo de nmero doble
(##) indica un objeto temporal global.

Algunas funciones de Transact-SQL tienen nombres que empiezan con un doble signo de arroba (@@). Para evitar
confusiones con estas funciones, se recomienda no utilizar nombres que empiecen con @@.

No se permiten los caracteres especiales o los espacios incrustados.

Si queremos utilizar un nombre que no siga estas reglas, normalmente para poder incluir espacios en blanco, lo tenemos
que escribir encerrado entre corchetes [ ] (tambin se pueden utilizar las comillas pero recomendamos utilizar los corchetes).

2.5. Tipos de datos


En SQL Server 2005, cada columna, expresin, variable y parmetro est asociado a un tipo de datos.
Un tipo de datos, realmente define el conjunto de valores vlidos para los campos definidos de ese tipo. Indica si el campo
puede contener: datos numricos, de caracteres, moneda, fecha y hora, etc.
SQL Server proporciona un conjunto de tipos de datos del sistema que define todos los tipos de datos que pueden utilizarse.
Tambin podemos definir nuestros propios tipos de datos en Transact-SQL o Microsoft .NET Framework.
Los tipos de datos ms utilizados son:

Los numricos: int, decimal, money

Los de fecha y hora: datetime

Y las cadenas de caracteres: varchar

Si quieres conocer todos los tipos de datos disponibles en SQLServer 2005, visita el siguiente avanzado .

2.6. Las constantes


Una constante es un valor especfico o un smbolo que representa un valor de dato especfico. El formato de las constantes
depende del tipo de datos del valor que representan. En este apartado veremos las ms utilizadas.

Las constantes numricas se escriben mediante una cadena de nmeros, con la consideracin de que el separador
decimal es un punto, no una coma, y que si se trata de un valor monetario deberemos incluir la moneda al inicio de
la constante. Por ejemplo: 85.90 y 85.90, el primero sera un valor decimal y el segundo un valor money. De forma
predeterminada, los valores sern positivos. Para indicar lo contrario escribimos el signo - al principio.

Las constantes de fecha y hora van entre comillas simples y con un formato de fecha y hora adecuado. Por ejemplo:
'03/10/90'.

Y las constantes en cadenas de caracteres van entre comillas simples. Por ejemplo: 'Juan Garca Lpez'.

Para indicar valores negativos y positivos aadimos el prefijo + o - segn sea el valor positivo o negativo. Sin prefijo se
entiende que el valor es positivo.
Si quieres ver cmo definir constantes para otros tipos de datos, visita el siguiente avanzado .

49

2.7. Las expresiones


Una expresin es una combinacin de smbolos y operadores que el motor de base de datos de SQL Server evala para
obtener un nico valor. Una expresin simple puede ser una sola constante, variable, columna o funcin escalar. Los
operadores se pueden usar para combinar dos o ms expresiones simples y formar una expresin compleja.

Dos expresiones pueden combinarse mediante un operador si ambas tienen tipos de datos admitidos por el operador y se
cumple al menos una de estas condiciones:

Las expresiones tienen el mismo tipo de datos.

El tipo de datos de menor prioridad se puede convertir implcitamente al tipo de datos de mayor prioridad.

La funcin CAST puede convertir explcitamente el tipo de datos con menor prioridad al tipo de datos con mayor
prioridad o a un tipo de datos intermedio que pueda convertirse implcitamente al tipo de datos con la mayor
prioridad.

Tipos de operadores:
- Operadores numricos:
suma

resta

multiplicacin

divisin

mdulo

(resto de una divisin)

- Operadores bit a bit: realizan manipulaciones de bits entre dos expresiones de cualquiera de los tipos de datos de la
categora del tipo de datos entero.
AND

&

OR

OR exclusivo

50

- Operadores de comparacin:
Igual a

Mayor que

>

Menor que

<

Mayor o igual que

>=

Menor o igual que

<=

Distinto de

<>

No es igual a

!=

No menor que

!<

No mayor que

!>

- Operadores lgicos:
Aqu slo los nombraremos ya que en el tema de consultas simples los veremos en detalle.
ALL

IN

AND

LIKE

ANY

NOT

BETWEEN

OR

EXISTS

SOME

- Operadores de cadenas:
Concatenacin

Resultados de la expresin
- Si se combinan dos expresiones mediante operadores de comparacin o lgicos, el tipo de datos resultante es booleano y
el valor es uno de los siguientes: TRUE, FALSE o UNKNOWN.

51

- Cuando dos expresiones se combinan mediante operadores aritmticos, bit a bit o de cadena, el operador determina el tipo
de datos resultante.
Las expresiones complejas formadas por varios smbolos y operadores se evalan como un resultado formado por un solo
valor. El tipo de datos, intercalacin, precisin y valor de la expresin resultante se determina al combinar las expresiones
componentes de dos en dos, hasta que se alcanza un resultado final. La prioridad de los operadores de la expresin define
la secuencia en que se combinan las expresiones.

2.8. Funciones
SQL Server 2005 proporciona numerosas funciones integradas y permite crear funciones definidas por el usuario.
Existen diferentes tipos de funciones:

Funciones de conjuntos de filas: devuelven un objeto que se puede utilizar, en instrucciones Transact-SQL, en lugar
de una referencia a una tabla.

Funciones de agregado (tambin llamadas funciones de columna): Operan sobre una coleccin de valores y
devuelven un solo valor de resumen. Por ejemplo, la funcin de suma sobre la columna importe para conocer el
importe total: SUM(importe)

Funciones de categora: Devuelven un valor de categora para cada fila de un conjunto de filas, por ejemplo
devuelve el nmero de la fila, el ranking de la fila en una determinada ordenacin, etc.

Funciones escalares: Operan sobre un valor y despus devuelven otro valor. Son las funciones que estamos
acostumbrados a utilizar. Las funciones escalares se clasifican segn el tipo de datos de sus operandos

Las variables
En Transact-SQL podemos definir variables, que sern de un tipo de datos determinado, como tipos de datos podemos
utilizar los propios de la base de datos SQL-SERVER, pero tambin podemos utilizar tipos propios del lenguaje que no
pueden ser utilizados en DDL. El tipo Cursor y el tipo Table son dos de estos tipos.
Las variables se definen utilizando la instruccin DECLARE con el siguiente formato:
DECLARE @nbvariable tipo
El nombre de la variable debe empezar por el smbolo @, este smbolo hace que SQL interprete el nombre como un nombre
de variable y no un nombre de objeto de la base de datos.
Por ejemplo: DECLARE @empleados INT
Con esto hemos definido la variable @empleados de tipo entero.
Para asignar un valor a una variable, la asignacin se realiza con la palabra SELECT y el signo igual con el formato:
SELECT @nbvariable = valor
El valor puede ser cualquier valor constante, otro nombre de variable, una expresin vlida o algo ms potente, parte de una
sentencia SELECT de SQL.

52

Por ejemplo:
SELECT @empleados = 0;
SELECT @empleados = @otra * 100;
SELECT @EMPLEADOS = COUNT(numemp) FROM empleados;
El valor almacenado en la variable se puede visualizar mediante la orden PRINT. o SELECT
PRINT @nbvariable o SELECT @nbvariable
El valor almacenado en la variable se visualizar en la pestaa de resultados. Tambin se puede usar para escribir
mensajes:
PRINT 'Este es el mensaje'
Otros elementos del lenguaje
Comentarios. Como en cualquier otro lenguaje de programacin, debemos utilizar comentarios destinados a facilitar la
legibilidad del cdigo. En SQL se insertan comentarios con los signos:

/* */

Varias lneas

--

Una nica lnea

/*

Esto

es

un

comentario

en varias lneas */
-- Esto es un comentario en una nica lnea.

USE. Cambia el contexto de la base de datos al de la base de datos especificada.


USE nbBaseDeDatos
Hace que la base de datos activa pase a ser la base de datos indicada en la instruccin, las consultas que se ejecuten a
continuacin se harn sobre tablas de esa base de datos si no se indica lo contrario. Es una instruccin til para
asegurarnos de que la consulta se ejecuta sobre la base de datos correcta.
GO
GO no es una instruccin Transact-SQL, sino un comando reconocido por las utilidades sqlcmd y osql, as como por el
Editor de cdigo de SQL Server Management Studio.
Las utilidades de SQL Server interpretan GO como una seal de que deben enviar el lote actual de instrucciones TransactSQL a una instancia de SQL Server. El lote actual de instrucciones est formado por todas las instrucciones especficadas
desde el ltimo comando GO o desde el comienzo de la sesin o script si se trata del primer comando GO.
Por ejemplo si queremos crear una consulta para crear una base de datos y sus tablas, despus del CREATE
DATABASE; tenemos que poner GO antes del primer CREATE TABLE para que el sistema efecte la primera operacin y
la base de datos est creada antes de ejecutar el primer CREATE TABLE.
BEGIN...END
Encierra un conjunto de instrucciones Transact-SQL de forma que estas instrucciones formen un bloque de instrucciones.

53

Unidad 3. Consultas simples (I)


3.1. Introduccin
Vamos a empezar por la instruccin que ms se utiliza en SQL, la sentencia SELECT. La sentencia SELECT es, con
diferencia, la ms compleja y potente de las sentencias SQL, con ella podemos recuperar datos de una o ms tablas,
seleccionar ciertos registros e incluso obtener resmenes de los datos almacenados en la base de datos. Es tan compleja
que la estudiaremos a lo largo de varias unidades didcticas incorporando poco a poco nuevas funcionalidades.
El resultado de una SELECT es una tabla lgica que alberga las filas resultantes de la ejecucin de la sentencia.
La sintaxis completa es la siguiente:
SELECT sentencia::=[WITH <expresion_tabla_comun> [,...n]]
<expresion_consulta>
[ORDER BY {expression_columna|posicion_columna [ASC|DESC] }
[ ,...n ]]
[COMPUTE
{{AVG|COUNT|MAX|MIN|SUM} (expression)}[ ,...n ] [BY expression[ ,...n ]]
]
[<FOR clausula_for>]
[OPTION (<query_hint>[ ,...n ])]
<expresion_consulta> ::=
{<especificacion_consulta> | ( < expresion_consulta > ) }
[ {UNION [ALL]|EXCEPT|INTERSECT}
<especificacion_consulta> | (<expresion_consulta>) [...n ]
]
<especificacion_consulta> ::=
SELECT [ALL|DISTINCT]
[TOP expresion [PERCENT] [WITH TIES] ]
<lista_seleccion>
[INTO nueva_tabla]
[FROM { <origen> } [ ,...n ] ]
[WHERE <condicion_busqueda> ]
[GROUP BY [ ALL ] expresion_agrupacion [ ,...n ]
[WITH { CUBE | ROLLUP } ]
]
[HAVING < condicion_busqueda > ]

54

Debido a la complejidad de la sentencia (en la sintaxis anterior no se han detallado algunos elementos), la iremos viendo
poco a poco, empezaremos por ver consultas bsicas para luego ir aadiendo ms clusulas.
Empezaremos por ver las consultas ms simples, basadas en una sola tabla y nos limitaremos a la siguiente sintaxis:

SELECT [ALL|DISTINCT]
[TOP expresion [PERCENT] [WITH TIES]]
<lista_seleccion>
FROM <origen>
[WHERE <condicion_busqueda> ]
[ORDER BY {expression_columna|posicion_columna [ASC|DESC]} [ ,...n ]]
3.2. Origen de datos FROM
De la sintaxis anterior, el elemento <origen> indica de dnde se va a extraer la informacin y se indica en la clusula FROM,
es la nica clusula obligatoria. En este tema veremos un origen de datos basado en una sola tabla.
La sintaxis ser la siguiente:
<origen>::=
nb_tabla | nb_vista [[ AS ] alias_tabla ]
nb_tabla representa un nombre de tabla.
nb_vista un nombre de vista.
Tanto para las tablas como para las vistas, podemos hacer referencia a tablas que estn en otras bases de datos (siempre
que tengamos los permisos adecuados), en este caso tenemos que cualificar el nombre de la tabla, indicando delante el
nombre de la base de datos (Lgica) y el nombre del esquema al que pertenece la tabla dentro de la base de datos.
Por ejemplo: MiBase.dbo.MiTabla se refiere a la tabla MiTabla que se encuentra en el esquema dbo de la base de datos
MiBase.
Cuando no se definen esquemas, SQL-Server crea uno por defecto en cada base de datos denominado dbo.
Opcionalmente podemos definir un nombre de alias.
Un nombre de alias (alias_tabla) es un nombre alternativo que se le da a la tabla dentro de la consulta.
Si se define un nombre de alias, dentro de la consulta, ser el nombre a utilizar para referirnos a la tabla, el nombre original
de la tabla ya no tendr validez.
Se utilizan los nombres de alias para simplificar los nombres de tablas a veces largos y tambin cuando queremos combinar
una tabla consigo misma; ya volveremos sobre los alias de tabla cuando veamos consultas multitabla.
La palabra AS no aade ninguna operatividad, est ms por esttica.
Podemos escribir:

55

SELECT ...
FROM tabla1

Sacamos los datos de la tabla tabla1

SELECT ...
FROM tabla1 t1

Sacamos los datos de la tabla tabla1 y le asignamos un alias de tabla: t1

SELECT ...
FROM tabla1 AS t1 Es equivalente a la sentencia anterior.
Si la tabla o la vista estn en otra base de datos del mismo equipo que est ejecutando la instancia de SQL Server, se utiliza
el nombre cualificado con el formato nbBaseDatos.nbEsquema.nbTabla.
Si la tabla o la vista estn fuera del servidor local en un servidor vinculado, se utiliza un nombre de cuatro partes con el
formato nbservidor.catalogo.nbEsquema.nbTabla. Volveremos ms adelante sobre las conexiones remotas.

3.3. La lista de seleccin


En la lista de seleccin <lista_seleccion> indicamos las columnas que se tienen que visualizar en el resultado de la consulta.
<lista_seleccion> ::=
{ *
| {nombre_tabla|nombre_vista|alias_tabla}.*
| { [{nombre_tabla|nombre_vista|alias_tabla}.]
{nb_columna|$IDENTITY|$ROWGUID}
|<expresion>
}[[AS] alias_columna]
| alias_columna = <expresion>
} [ ,...n ]
Separamos la definicin de cada columna por una coma y las columnas del resultado aparecern en el mismo orden que en
la lista de seleccin.
Para cada columna del resultado su tipo de datos, tamao, precisin y escala son los mismos que los de la expresin que da
origen a esa columna.
Podemos definir las columnas del resultado de varias formas, mediante:

Una expresin simple:


o

una referencia a una funcin.

una variable local

una constante

una columna del origen de datos,

56

Una subconsulta escalar, que es otra instruccin SELECT que devuelve un nico valor y se evala para cada fila del
origen de datos (esto no lo veremos de momento).

Una expresin compleja generada al usar operadores en una o ms expresiones simples.

La palabra clave *.

La asignacin de variables con el formato @variable_local = expresin.

La palabra clave $IDENTITY.

La palabra clave $ROWGUID.

3.4. Columnas del origen de datos


Cuando queremos indicar en la lista de seleccin una columna del origen de datos, la especificamos mediante su nombre
simple o nombre cualificado. El nombre cualificado consiste en el nombre de la columna precedido del nombre de la tabla
donde se encuentra la columna.
Si en el origen de datos hemos utilizado una vista o un nombre de alias, deberemos utilizar ese nombre. Es obligatorio
utilizar el nombre cualificado cuando el nombre de la columna aparece en ms de una tabla del origen de datos.
Ejemplos de consulta simple.
Listar nombres, oficinas, y fechas de contrato de todos los empleados:
SELECT nombre, oficina, contrato
FROM empleados;
El resultado sera:
nombre

oficina

contrato

Antonio Viguer

12

1986-10-20

Alvaro Jaumes

21

1986-12-10

Juan Rovira

12

1987-03-01

Jos Gonzlez

12

1987-05-19

Vicente Pantalla

13

1988-02-12

Luis Antonio

11

1988-06-14

Jorge Gutirrez

22

1988-11-14

57

Ana Bustamante

21

1989-10-12

Mara Sunta

11

1999-10-12

Juan Victor

NULL

1990-01-13

Listar una tarifa de productos:


SELECT idfab, idproducto, descripcion, productos.precio
FROM productos;
Hemos cualificado la columna precio aunque no es necesario en este caso.
El resultado sera:
Idfab

idproducto

descripcion

precio

aci

41001

arandela

0,58

aci

41002

bisagra

0,80

aci

41003

art t3

1,12

aci

41004

art t4

1,23

aci

4100x

junta

0,26

aci

4100y

extractor

28,88

aci

4100z

mont

26,25

bic

41003

manivela

6,52

bic

41089

rodamiento

2,25

3.5. Alias de columna


Por defecto, en el encabezado de cada columna del resultado, aparece el nombre de la columna origen, pero esto se puede
cambiar definiendo un alias de columna, el alias de columna es un nombre alternativo que se le da a esa columna.
El alias de columna se indica mediante la clusula AS. Se escribe el nuevo texto tal cual sin comillas siguiendo las reglas de
los identificadores.

58

Ejemplo:
SELECT numclie,nombre AS nombrecliente
FROM clientes;
El resultado ser :
Numclie

nombrecliente

2101

Luis Garca Antn

2102

Alvaro Rodrguez

2103

Jaime Llorens

en vez de:
Numclie

nombre

2101

Luis Garca Antn

2102

Alvaro Rodrguez

2103

Jaime Llorens

La palabra AS es opcional.
SELECT numclie,nombre nombrecliente
FROM clientes;
Sera equivalente a la consulta anterior
Si queremos incluir espacios en blanco en el nombre lo debemos encerrar entre corchetes.
SELECT numclie,nombre AS [nombre cliente]
FROM clientes;
Nota importante: Este nombre de alias se podr utilizar en la lista de seleccin y en la clusula ORDER BY pero no en la
clusula WHERE.

3.6. Funciones
Existen funciones que podemos utilizar en la lista de seleccin, e incluso en otras clusulas que veremos ms adelante,
como el WHERE. Las principales funciones son las siguientes:
Funciones de fecha:

59

Funcin

Descripcin

GETDATE

Devuelve la fecha actual.

GETUTCDATE

Devuelve la hora UTC.

DATEPART

Devuelve un entero que corresponde a la parte de la fecha solicitada.

DAY

Devuelve el da de la fecha indicada.

MONTH

Devuelve el mes de la fecha indicada.

YEAR

Devuelve el ao de la fecha indicada.

DATENAME

DATEADD

DATEDIFF

Devuelve una cadena de caracteres que representa el valor de la unidad especificada de


una fecha especificada.
Devuelve un valor datetime nuevo que resulta de sumar un intervalo de tiempo a una fecha
especificada.>
Devuelve el n de intervalos que hay entre dos fechas.

@@DATEFIRST Devuelve el primer da de la semana establecido con SET DATEFIRST.


SET
DATEFIRST

Establece el primer da de la semana en un nmero del 1 al 7.

Las funciones que ms se van a utilizar durante el curso estarn marcadas de la siguiente forma. Prstales especial
atencin.

Funciones de fecha
GETDATE
La funcin GETDATE devuelve la fecha actual en formato datetime.
GETDATE()
Ejemplo:
SELECT GETDATE() AS Ahora;
Una variante es la funcin GETUTCDATE()

60

GETUTCDATE
Devuelve la hora UTC (hora universal coordinada u hora del meridiano de Greenwich) actual. La hora UTC actual se deriva
de la hora local actual y la configuracin de zona horaria del sistema operativo del equipo en el que se ejecuta la instancia
de Microsoft SQL Server.

DATEPART
Devuelve un entero que representa la parte de la fecha especificada expresada en la unidad indicada.
DATEPART (unidad,fecha)
unidad

Abreviaturas Significado

year

yy, yyyy

ao

quarter

qq, q

cuatrimestre

month

mm, m

mes

dayofyear dy, y

n da del ao

day

dd, d

da

week

wk, ww

semana

weekday

dw, w

da de la semana

hour

hh

hora

minute

mi, n

minuto

second

ss, s

segundo

millisecond ms

milisegundo

Week (wk, ww) indica el nmero de semana del ao, refleja los cambios realizados en SET DATEFIRST (que indica el
primer da de la semana). El 1 de enero de cualquier ao define el nmero de inicio para week, por ejemplo: DATEPART(wk,
'1 Ene 2009') = 1.
Weekday (dw) devuelve un nmero que corresponde al da de la semana, por ejemplo: Lunes = 1, Sbado = 6. El nmero
generado con la unidad weekday depende del valor establecido por SET DATEFIRST.

61

Fecha
Es una expresin que devuelve un valor datetime o smalldatetime, o una cadena de caracteres con formato de fecha. El tipo
de datos datetime slo sirve para fechas a partir del 1 de enero de 1753.
Ejemplos
SELECT DATEPART(dw, '20/10/2008') devuelve 1 (es lunes).
SELECT 'dd',DATEPART(dd, '20/10/2008') devuelve 20
SELECT 'dy',DATEPART(dy, '20/10/2008') devuelve 294

DAY
Devuelve un entero que representa el da de la fecha especificada.
DAY(fecha)
Esta funcin es equivalente a DATEPART(dd, fecha).

MONTH
Devuelve un entero que representa el mes de la fecha especificada.
MONTH(fecha)
Esta funcin es equivalente a DATEPART(mm, fecha).

YEAR
Devuelve un entero que representa el ao de la fecha especificada.
YEAR(fecha)
Esta funcin es equivalente a DATEPART(yy, fecha).

DATENAME
Devuelve una cadena de caracteres que representa el valor de la unidad especificada de una fecha especificada.
DATENAME(unidad, fecha)
Unidad puede tomar los mismos valores que en la funcin DATEPART
Cuando la unidad corresponde a mes o da de la semana, devuelve el valor en letras.
Ejemplos:
SELECT 'dd',DATENAME(dd, '20/10/2008')

devuelve 20

SELECT 'mm',DATENAME(mm, '20/10/2008')

devuelve Octubre

SELECT 'yy',DATENAME(yy, '20/10/2008')

devuelve 2008

SELECT 'dw',DATENAME(dw, '20/10/2008')

devuelve Lunes

DATEADD
Devuelve un valor datetime nuevo que resulta de sumar un intervalo de tiempo a una fecha especificada.

62

DATEADD(intervalo, nmero, fecha)


Aade a la fecha nmero intervalos.
Valores vlidos para intervalo:
Intervalo

Abreviaturas Significado

year

yy, yyyy

ao

quarter

qq, q

cuatrimestre

month

mm, m

mes

dayofyear dy, y

n da del ao

day

dd, d

da

week

wk, ww

semana

weekday

dw, w

da de la semana

hour

hh

hora

minute

mi, n

minuto

second

ss, s

segundo

millisecond ms

milisegundo

Si nmero no es entero, se descarta la parte decimal.


Cuando intervalo es month, el nmero de das del mes afecta al resultado.
Por ejemplo,
SELECT DATEADD(month, 1, '08/30/2006')
SELECT DATEADD(month, 1, '08/31/2006')
Las dos instrucciones siguientes devuelven 2006-09-30 00:00:00.000.
Agosto tiene 31 das y septiembre tiene 30 das, al agregar un mes al final de agosto, se devuelve el ltimo da de
septiembre.

DATEDIFF
Devuelve el nmero de intervalos que hay entre las dos fechas especificadas.

63

DATEDIFF( intervalo , fechainicial , fechafinal )


Se resta fechainicial de fechafinal. Para expresar el tipo de intervalo se utilizan los mismos valores que en la funcin
DATEADD.
El valor devuelto es de tipo entero por lo que si el resultado es un nmero mayor que el mximo entero, la funcin da
error. Para los milisegundos, el nmero mximo es de 24 das, 20 horas, 31 minutos y 23.647 segundos. Para los
segundos, el nmero mximo es 68 aos.
Por ejemplo:
SELECT DATEDIFF(year, contrato, getdate()) AS [Aos trabajados]
FROM empleados;
Nos devuelve la diferencia de aos existentes entre la fecha de hoy (GETDATE()) y la fecha de contrato del empleado.

@@DATEFIRST
Devuelve el primer da de la semana establecido con SET DATEFIRST.

SET DATEFIRST
Establece el primer da de la semana en un nmero del 1 al 7.
SET DATEFIRST nmero
Se puede utilizar la funcin @@DATEFIRST para ver el valor actual de SET DATEFIRST.
La opcin SET DATEFIRST se establece en tiempo de ejecucin.
Nmero es un entero que indica el primer da de la semana. Puede ser uno de los siguientes valores.
nmero Primer da de la semana
1

Lunes

Martes

Mircoles

Jueves

Viernes

Sbado

Domingo

64

Funciones de cadena:
Funcin

ASCII

Descripcin
Devuelve el valor de cdigo ASCII del carcter situado ms a la izquierda de una expresin de
caracteres.

CHAR

Devuelve el carcter ASCII del entero indicado.

NCHAR

Devuelve el carcter Unicode del entero indicado.

UNICODE

Devuelve el entero que se corresponde al carcter Unicode indicado.

LEN

Devuelve el total de caracteres de una cadena, excluidos los espacios en blanco finales.

LTRIM

Devuelve una cadena tras quitarle los espacios en blanco iniciales.

RTRIM

Devuelve una cadena tras quitarle los espacios en blanco finales.

LEFT

Devuelve los N ltimos caracteres de una cadena.

RIGHT

Devuelve los N primeros caracteres de una cadena.

SUBSTRING

Devuelve parte de una expresin.

LOWER

Devuelve la cadena convertida a minsculas.

UPPER

Devuelve la cadena convertida a maysculas.

REPLACE

Reemplaza una determinada cadena.

STUFF

QUOTENAME

Elimina el nmero de caracteres especificado e inserta otro conjunto de caracteres en el punto


de inicio indicado.
Devuelve una cadena Unicode con los delimitadores agregados para convertirla en un
identificador delimitado vlido de Microsoft SQL Server 2005.

SPACE

Devuelve una cadena de espacios repetidos.

STR

Devuelve una cadena de caracteres a partir de datos numricos.

65

REPLICATE

Repite una cadena N veces.

REVERSE

Devuelve una cadena invertida.

CHARINDEX Devuelve la posicin inicial de la expresin especificada en una cadena de caracteres.

PATINDEX

Devuelve la posicin inicial de la primera repeticin de un patrn en la expresin especificada, o


ceros si el patrn no se encuentra, en todos los tipos de datos de texto y caracteres.

Otras funciones:
Funcin

Descripcin

ROUND

Redondea un valor a la longitud y precisin indicadas.

CAST y CONVERT

Convierten de un tipo de datos a otro de forma explcita.

CASE

Evala una lista de condiciones.

ISNULL

Reemplaza el valor NULL por otro especificado.

COALESCE

Devuelve la primera expresin distinta de NULL entre sus argumentos.

Funciones de cadena

ASCII
Devuelve el valor de cdigo ASCII del carcter situado ms a la izquierda de una expresin de caracteres.
ASCII(expresion_cadena)
expresion_cadena Es una expresin de tipo char o varchar.
La funcin devuelve un valor int.
Ejemplo:
ASCII('abc') devuelve 97, lo mismo que ASCII('a').

CHAR
Devuelve el carcter segn el cdigo ASCII correspondiente a un nmero entero.
CHAR(numero)
Numero es un nmero entero entre 0 y 255 de lo contrario la funcin devuelve NULL.
Se suele utilizar para insertar caracteres de control en cadenas alfanumricas.

66

Carcter de control Valor


Tabulacin

char(9)

Avance de lnea

char(10)

Retorno de carro

char(13)

Ejemplo:
ASCII('abc') devuelve a.

NCHAR
Devuelve el carcter Unicode correspondiente al cdigo entero dado, tal como se define en el estndar Unicode.
NCHAR(numero)
Numero es un nmero entero entre 0 y 65535 de lo contrario la funcin devuelve NULL.
Ejemplo:
NCHAR(400) devuelve

UNICODE
Devuelve el valor entero, segn la definicin del estndar Unicode, del primer carcter de la expresin de entrada.
UNICODE(expresion_cadena)
expresion_cadena Es una expresin de tipo Nchar o Nvarchar.
La funcin devuelve un valor int.
Ejemplo:
UNICODE(N'') devuelve

LEN
Devuelve el nmero de caracteres de la expresin de cadena especificada, excluidos los espacios en blanco finales.
LEN(Expresion_cadena)
Expresion_cadena es una expresin de cadena
El valor devuelto es de tipo bigint si Expresion_cadena tiene el tipo de datos varchar(max), nvarchar(max) o varbinary(max);
en caso contrario, int.
Ejemplo:
LEN('abcdef ') devuelve 7

LTRIM
Devuelve una cadena tras quitar todos los espacios iniciales en blanco.

67

LTRIM(Expresion_cadena)
Expresion_cadena es una expresin de cadena, debe ser un tipo de datos implcitamente convertible a varchar excepto
text, ntext e image.
El valor devuelto es de tipo varchar o nvarchar.
Ejemplo:
LTRIM('

ab cdef ') devuelve ab cdef .

RTRIM
Devuelve una cadena tras quitar todos los espacios finales en blanco.
RTRIM(Expresion_cadena)
Expresion_cadena es una expresin de cadena, debe ser un tipo de datos implcitamente convertible a varchar excepto
text, ntext e image.
El valor devuelto es de tipo varchar o nvarchar.
Ejemplo:
RTRIM('

ab cdef

') devuelve

ab cdef.

LEFT
Devuelve la parte izquierda de una cadena de caracteres con el nmero de caracteres especificado.
LEFT(Expresion_cadena, longitud)
Expresion_cadena es una expresin de cadena
Longitud: es el nmero de caracteres a devolver. Puede ser de tipo bigint, si es negativo la funcin devuelve un error.
El valor devuelto es de tipo varchar o nvarchar.
Ejemplo:
LEFT('abcdef ', 3) devuelve abc

RIGHT
Devuelve la parte derecha de una cadena de caracteres con el nmero de caracteres especificado.
RIGHT(Expresion_cadena, longitud)
Expresion_cadena es una expresin de cadena
Longitud: es el nmero de caracteres a devolver. Puede ser de tipo bigint, si es negativo la funcin devuelve un error.
El valor devuelto es de tipo varchar o nvarchar.
Ejemplo:
RIGHT('abcdef ', 3) devuelve def

68

SUBSTRING
Devuelve parte de una expresin de caracteres, binaria, de texto o de imagen.
SUBSTRING ( expresion ,inicio , longitud )
expresion
Es una cadena de caracteres, una cadena binaria, texto, imagen, una columna o una expresin que incluye una columna. No
se puede utilizar expresiones que incluyan funciones de agregado.
inicio
Es un entero que especifica dnde comienza la subcadena. start puede ser de tipo bigint.
longitud
Es un entero positivo (puede ser de tipo bigint ) que especifica cuntos caracteres o bytes de la expression se van a
devolver. Si longitud es negativo, se devuelve un error.
Segn el tipo de datos de Expresion los datos devueltos son de tipo:
Expresion

Valor devuelto

char/varchar/text

varchar

nchar/nvarchar/ntext

nvarchar

binary/varbinary/image varbinary
Los valores (inicio y longitud) que utilizan los tipos de datos ntext, char o varchar deben especificarse en nmero de
caracteres. Los desplazamientos que utilizan los tipos de datos text, image, binary o varbinary deben especificarse en
nmero de bytes.
Ejemplo:
SUBSTRING('abcdef',3,2) devuelve cd

LOWER
Devuelve una cadena despus de convertir en minsculas los caracteres en maysculas.
LOWER(Expresion_cadena)
Expresion_cadena es una expresin de cadena, debe ser un tipo de datos implcitamente convertible a varchar.
El valor devuelto es de tipo varchar o nvarchar.
Ejemplo:
LOWER('aBcdEf ', 3) devuelve abcdef

UPPER
Devuelve una cadena despus de convertir en maysculas los datos de caracteres en minsculas.

69

UPPER(Expresion_cadena)
Expresion_cadena es una expresin de cadena, debe ser un tipo de datos implcitamente convertible a varchar.
El valor devuelto es de tipo varchar o nvarchar.
Ejemplo:
UPPER('aBcdEf ', 3) devuelve ABCDEF

REPLACE
Reemplaza todas las apariciones de un valor de cadena especificado por otro valor de cadena.
REPLACE(cadena_original, cadena_a_quitar, cadena_a_poner)
Las cadenas pueden ser de tipo carcter o binario. Se pueden combinar con COLLATE.
Devuelve nvarchar si una de las cadenas es de tipo nvarchar, en caso contrario devuelve varchar.
Ejemplo:
REPLACE('Esto es una cuestin','es','xx') devuelve xxto xx una cuxxtin

STUFF
Elimina el nmero de caracteres especificado e inserta otro conjunto de caracteres en el punto de inicio indicado.
STUFF (expresin_origen, inicio , longitud , expresin_sustituta)

expresin_origen indica la cadena que se va a modificar.

inicio: la posicin de inicio de la subcadena a eliminar, puede ser de tipo bigint.

longitud: la longitud de la subtira a eliminar, puede ser de tipo bigint.

Si inicio o longitud es negativo, se devuelve una cadena nula.

Si inicio es mayor que la longitud de expresin_origen, se devuelve una cadena nula.

Si longitud es mayor que la longitud de expresin_origen, se elimina hasta el ltimo carcter de expresin_origen.

expresin_sustituta es la cadena a insertar en el lugar de la que se elimina.

Si la longitud de la cadena resultante es mayor que el mximo admitido, se genera un error.

Tanto expresin_origen como expresin_sustituta pueden ser tanto de caracteres como binarios.

Ejemplo:
STUFF('abcdef', 2, 3, 'ijklmn') devuelve aijklmnef

QUOTENAME
Devuelve una cadena Unicode con los delimitadores agregados para convertirla en un identificador delimitado vlido de
Microsoft SQL Server 2005.
QUOTENAME ( 'cadena' [ , 'caracter' ] )

70

Cadena es una cadena de caracteres.


Carcter es el carcter delimitador. Puede ser una comilla simple ('), un corchete izquierdo o derecho ([ ]) o una comilla
doble ("). Si no se especifica, se utilizarn corchetes.
Ejemplo:
QUOTENAME('nombre de campo') devuelve [nombre de campo]
QUOTENAME('nombre de campo','"') devuelve "nombre de campo"

SPACE
Devuelve una cadena de espacios repetidos.
SPACE(nmero)
Nmero es un entero positivo que indica el nmero de espacios en blanco a devolver, si es negativo la funcin devuelve una
Cadena null.
Para incluir espacios en datos Unicode o para devolver ms de 8.000 espacios en blanco, utilice REPLICATE en lugar de
SPACE.
Ejemplo:
PRINT RTRIM('Ana

') + SPACE(1) + LTRIM('

Garca') devuelve Ana Garca.

STR
Devuelve una cadena de caracteres a partir de datos numricos.
STR ( nmero [ , longitud [ , decimales ] ] )
Nmero es el nmero a convertir debe ser de tipo numrico.
Longitud es la longitud de la cadena devuelta incluye todos los caracteres, dgitos, punto decimal, signo y espacios. EL valor
predeterminado es 10.
Decimales es el nmero de cifras a la derecha del separador decimal. El valor de decimales debe ser menor o igual que 16.
Si es mayor que 16, el resultado se trunca en el decimosexto lugar a la derecha del separador decimal. El valor
predeterminado es cero.
La funcin redondea automticamente los valores.
Cuando la el valor excede de la longitud especificada la funcin devuelve **.
DECLARE @n numeric(5,3);
DECLARE @x float;
SELECT @n=3.67;
SELECT @x=3.45;
PRINT 'A'+STR(@n,8,2)+'B'

71

PRINT 'F'+STR(@x,8,2)+'G'
PRINT 'a'+STR(@n,8)+'b'
PRINT 'f'+STR(@x,8)+'g'
Da como salida:
A

3.67B

3.45G

4b
3g

REPLICATE
Repite una expresin de caracteres un nmero especificado de veces.
REPLICATE(expresion_cadena, longitud)
expresion_cadena Es una expresin de un tipo de datos que puede convertirse implcitamente a varchar. Tambin puede
ser una constante, una variable o una columna de datos binarios.
Longitud es un nmero entero positivo (puede ser de tipo bigint). Si es negativo, se devuelve una cadena NULL.
Ejemplo:
REPLICATE('abc',5) devuelve abcabcabcabcabc

REVERSE
Devuelve una expresin de caracteres invertida.
REVERSE(expresion_cadena)
expresion_cadena Es una expresin de un tipo de datos que puede convertirse implcitamente a varchar. Tambin puede
ser una constante, una variable o una columna de datos binarios.
Ejemplo:
REVERSE('abcdef') devuelve fedcba

CHARINDEX
Devuelve la posicin inicial de la expresin especificada en una cadena de caracteres.
CHARINDEX( cadena_a_buscar , cadena_origen [ , inicio ] )
cadena_a_buscar y cadena_origen son de tipo de datos carcter.
Inicio indica pa posicin a partir de la cual se empieza a buscar. Puede ser de tipo bigint. Si no se especifica o si es cero o
negativo, la bsqueda empieza en el primer carcter de cadena_origen.
Ejemplo:
CHARINDEX('fg', 'abcdefghyfg') devuelve 6

72

PATINDEX
Devuelve la posicin inicial de la primera repeticin de un patrn en la expresin especificada, o ceros si el patrn no se
encuentra, en todos los tipos de datos de texto y caracteres.
PATINDEX ( '%patrn%' , expresion )
Patrn es una cadena literal. Se pueden incluir caracteres comodn, aunque el carcter % debe preceder y seguir a patrn
(excepto cuando se busca el primer o el ltimo carcter). Es una expresin de la categora de tipo de datos de cadena de
caracteres.
Expression es de la categora de tipo de datos de cadena de caracteres. Se puede combinar con COLLATE.
La funcin devuelve bigint si expresion es de los tipos de datos varchar o nvarchar, en caso contrario, int.
Si expresin es una columna, la consulta devolver todas las filas del origen de la consulta (despus de ejecutar el WHERE)
e indicar valores distintos de cero para las filas en las que se haya encontrado el patrn y cero para el resto.
Ejemplo:
PRINT PATINDEX('%cd%','aasecdgtcd') devuelve 5
PRINT PATINDEX('cd%','aasecdgtcd')

devuelve 0 (lo busca al principio).

PRINT PATINDEX('%cd','aasecdgtcd')

devuelve 9 (lo busca al final).

ROUND
Devuelve un valor numrico, redondeado a la longitud o precisin especificadas y del mismo tipo.
ROUND ( expresion_numerica , longitud [ ,funcion ] )
expresion_numerica
Es una expresin de la categora de tipo de datos numrico exacto o numrico aproximado, excepto el tipo de datos bit.
longitud
Es la precisin con la que se redondea expresion_numerica. Debe ser una expresin de tipo tinyint, smallint o int. Si
longitud es un nmero positivo, se redondea al nmero de posiciones decimales que especifica longitud. Si longitud es un
nmero

negativo,

se

redondea

la

izquierda

del

separador

decimal,

segn

se

especifica

en

longitud.

funcion
Es el tipo de operacin que se realiza. function debe ser de tipo tinyint, smallint o int. Si function se omite o tiene el valor 0
(predeterminado), se redondea. Si se especifica un valor distinto de 0, se trunca.
Ejemplos:
ROUND(1265.45627, 2)

devuelve

1265.46000

ROUND(1265.45627, 3)

devuelve

1265.45600

ROUND(1265.45627, 2,1)

devuelve

1265.45000 trunca

ROUND(1265.45627, -3)

devuelve

1000.00000

ROUND(1265.45627, -2)

devuelve

1300.00000

73

CAST y CONVERT
Convierten una expresin de un tipo de datos en otro de forma explcita. CAST y CONVERT proporcionan funciones
similares.
CAST ( expresion AS tipo_dato [ (longitud) ])

CONVERT (tipo_dato [ (longitud) ] , expresion [ , estilo ] )


expresion Es cualquier expresin vlida.
tipo_dato Es el tipo de datos de destino proporcionado por el sistema. Incluye xml, bigint y sql_variant. No se pueden
utilizar tipos de datos de alias.
Longitud Es un parmetro opcional de los tipos de datos nchar, nvarchar, char, varchar, binary o varbinary. Para
CONVERT,

si

no

se

ha

especificado

el

parmetro

longitud,

el

valor

predeterminado

es

30

caracteres.

estilo
Es el estilo del formato de fecha usado para convertir datos de tipo datetime o smalldatetime en datos de caracteres (con
tipo de datos nchar, nvarchar, char, varchar, nchar o nvarchar), o para convertir datos de caracteres de formatos de fecha
y hora conocidos en datos de tipo datetime o smalldatetime; o bien, el formato de cadena usado para convertir datos de
tipo float, real, money o smallmoney en datos de caracteres (con tipo de datos nchar, nvarchar, char, varchar, nchar o
nvarchar). Cuando estilo es NULL, el resultado devuelto tambin es NULL.
En las conversiones money a carcter los estilos utilizados son:
Valor

Resultado

Sin separadores de millar cada tres dgitos a la izquierda del separador decimal y dos dgitos a la

(predeterminado) derecha del separador decimal; por ejemplo, 4235,98.


1

Separadores de millar cada tres dgitos a la izquierda del separador decimal y dos dgitos a la derecha
del separador decimal; por ejemplo, 3.510,92.

Sin separadores de millar cada tres dgitos a la izquierda del separador decimal y cuatro dgitos a la
derecha del separador decimal; por ejemplo, 4235,9819.

En las conversiones de tipo fecha a tipo alfanumrico, por ejemplo los estilos 3 y 103 permiten convertir la fecha con el estilo
dd/mm/aa y dd/mm/aaaa respectivamente.
Ejemplo:
DECLARE @fecha AS datetime;
SELECT @fecha= GETDATE();
PRINT @fecha;

devuelve Oct 27 2008 7:20PM

PRINT CONVERT (CHAR(8),@fecha,3)

devuelve 27/10/08

74

PRINT CONVERT (CHAR(10),@fecha,103) devuelve 27/10/2008

CASE
Evala una lista de condiciones y devuelve una de las varias expresiones de resultado posibles.

La funcin CASE sencilla compara una expresin con un conjunto de expresiones sencillas para determinar el
resultado.

La funcin CASE buscada evala un conjunto de expresiones booleanas para determinar el resultado.

Ambos formatos son compatibles con un argumento ELSE opcional.


Funcin CASE simple:
CASE expresion_entrada

WHEN valor THEN resultado


[ ...n ]
[
ELSE resultado_sino
]
END
Expresion_entrada es la expresin que calcula el valor a evaluar.
Valor es cualquier expresin que devuelva un valor del mismo tipo que expresion_entrada (o por lo menos de conversin
implcita).
Resultado es el valor devuelto por la funcin si expresin_entrada es igual a valor.
Resultado_sino Es el valor devuelto por la funcin si ninguna comparacin se evala como TRUE. Si se omite este
argumento y ninguna comparacin se evala como TRUE, CASE devuelve NULL.
Resultado_sino y todos los Resultado deben tener el mismo tipo de datos o deben ser de conversin implcita.
Cmo funciona:

Evala expresion_entrada y, en el orden especificado, la expresin expresion_entrada = valor para cada clusula
WHEN.

Devuelve resultado de la primera expresion_entrada = valor que se evala como TRUE.

Si expresion_entrada = valor no se evala como TRUE, SQL Server 2005 Database Engine (Motor de base de datos
de SQL Server 2005) devuelve resultado_sino si se especifica una clusula ELSE, o bien un valor NULL si no se
especifica ninguna clusula ELSE.

75

Ejemplo:
CASE estado_civil
WHEN c THEN casado/a

WHEN s THEN soltero/o


WHEN v THEN viudo/a

ELSE otro
END
Si queremos evaluar si el campo es nulo no podemos aadir un WHEN NULL THEN nulo porque la condicin estado_civil =
NULL no es TRUE cuando el campo es nulo, en este caso habra que utilizar la segunda forma de la funcin CASE y utilizar
el operador is null.
Funcin CASE buscada:
CASE
WHEN condicion THEN resultado
[ ...n ]
[
ELSE resultado_sino
]
END
Condicion

es

la

condicin

que

se

evala

si

el

resultado

es

TRUE

la

funcin

devuelve

resultado.

Devuelve resultado de la primera condicion que se evala como TRUE. SI ninguna condicin se evala como TRUE la
funcin devuelve NULL.
Ejemplo:
CASE
WHEN estado_civil IS NULL THEN nulo
WHEN estado_civil = c THEN casado/a
WHEN estado_civil = s THEN soltero/o
WHEN estado_civil = v THEN viudo/a
ELSE otro
END

ISNULL
Reemplaza el valor NULL con el valor de reemplazo especificado.
ISNULL ( expresion_entrada , valor )
expresion_entrada es la expresin que indica donde se va a comprobar la existencia de NULL.
Valor es el valor por el cual se reemplaza NULL.

76

Ejemplo:
ISNULL(precio, 0)
Si en precio hay un valor no nulo la funcin devuelve ese valor, si precio contiene NULL entonces la funcin devuelve 0.

COALESCE
Devuelve la primera expresin distinta de NULL entre sus argumentos.
COALESCE ( expresion [ ,...n ] )
Si todos los argumentos son NULL, la funcin devuelve NULL.
Por ejemplo, tenemos dos campos fijo y movil, en uno tenemos el telfono fijo del cliente y en el otro tenemos el telfono
mvil y queremos obtener el telfono fijo si tiene y sino el mvil, lo pondramos as:
COALESCE(fijo, movil)
3.7. Columnas calculadas
Adems de las columnas que provienen directamente de la tabla origen, una consulta SQL puede incluir columnas
calculadas cuyos valores se evalan a partir de una expresin.
La expresin puede contener cualquier operador vlido (+, -, *, /, &), cualquier funcin vlida, nombres de columnas del
origen de datos, nombres de parmetros o constantes y para combinar varias operaciones se pueden utilizar los parntesis.
Ejemplos de columnas calculadas:
Listar la ciudad, regin y el supervit de cada oficina. Consideraremos el supervit como el volumen de ventas que se
encuentran por encima o por debajo del objetivo de la oficina.
SELECT ciudad, region, (ventas-objetivo) AS superavit
FROM oficinas;
El resultado ser:
ciudad

region

superavit

Valencia

este

11800,00

Alicante

este

-6500,00

Castellon

este

1800,00

Badajoz

oeste

11100,00

A Corua

oeste

-11400,00

Madrid

centro

NULL

77

Madrid

centro

-10000,00

Pamplona

norte

NULL

Valencia

este

-90000,00

De cada producto queremos saber el id de fabricante, id de producto, su descripcin y el valor de sus existencias.
SELECT idfab,idproducto,descripcion,(existencias*precio) AS valoracion
FROM productos;
El resultado sera:
Idfab

idproducto

descripcion

valoracion

aci

41001

arandela

160,66

aci

41002

bisagra

133,60

aci

41003

art t3

231,84

aci

41004

art t4

170,97

aci

4100x

junta

9,62

aci

4100y

extractor

722,00

aci

4100z

mont

735,00

bic

41003

manivela

19,56

bic

41089

rodamiento

175,50

Listar el nombre, mes y ao del contrato de cada vendedor.

78

SELECT nombre, MONTH(contrato) AS [Mes de contrato], YEAR(contrato) AS [Ao de contrato]


FROM empleados;
El resultado ser:
Nombre

Mes de contrato

Ao de contrato

Antonio Viguer

10

1986

Alvaro Jaumes

12

1986

Juan Rovira

1987

Listar las ventas en cada oficina con el formato: 22 tiene ventas de 186,042.00
SELECT oficina, 'tiene ventas de ' AS [ ], ventas
FROM oficinas;
El resultado sera:
oficina

ventas

11

tiene ventas de

69300,00

12

tiene ventas de

73500,00

13

tiene ventas de

36800,00

21

tiene ventas de

83600,00

22

tiene ventas de

18600,00

23

tiene ventas de

NULL

24

tiene ventas de

15000,00

26

tiene ventas de

NULL

28

tiene ventas de

0,00

El incluir una constante como columna en la lista de seleccin puede parecer intil (se repetir el mismo valor en todas las
filas) pero veremos ms adelante que tiene utilidad en ciertos casos.
Tambin podemos utilizar la sintaxis:

79

alias_columna = <expresion>
Ejemplo:
SELECT oficina, superavit = ventas-objetivo
Esto tiene el mismo efecto que
SELECT oficina, ventas-objetivo AS superavit
3.8. Utilizacin del asterisco *
Si queremos visualizar todas las columnas del origen de datos, en lugar de indicar todas las columnas una a una se puede
utilizar el carcter de sustitucin *.
Mostrar todos los datos de la tabla oficinas.
SELECT *
FROM oficinas;
Obtener todos los datos y el supervit de cada oficina.
SELECT *, (ventas-objetivo) AS superavit
FROM oficinas;
Tambin podemos cualificar el * con un nombre de tabla, de vista o un alias de tabla:
SELECT oficinas.*
FROM oficinas;
oficinas.* se interpreta como: todas las columnas de la tabla oficinas.
Esta forma se utiliza normalmente cuando el origen est basado en varias tablas y queremos indicar todas las columnas no
del origen completo sino de una tabla concreta.

3.9. Las palabras clave $IDENTITY y $ROWGUID


La palabra clave $IDENTITY se interpreta como la columna de la tabla que tiene la propiedad IDENTITY (la columna de
identidad que vimos en un tema anterior).
Por ejemplo, si en la columna codigo de la tabla usuarios (BD Biblio) se ha definido la propiedad IDENTITY.
SELECT $IDENTITY, nombre, apellidos
FROM usuarios;
Es equivalente a:
SELECT codigo, nombre, apellidos
FROM usuarios;
La palabra clave $ROWGUID se interpreta como la columna de la tabla que tiene la propiedad ROWGUIDCOL y se puede
utilizar de la misma forma que $IDENTITY.

80

3.10. Ordenacin de las filas del resultado ORDER BY


Si queremos que las filas del resultado de la consulta aparezcan ordenadas, lo podemos indicar mediante la clusula
ORDER BY.
ORDER BY {expression_columna|posicion_columna [ASC|DESC]}[ ,...n ]
Podemos indicar una columna o varias separadas por una coma, la columna de ordenacin se especifica mediante el
nombre de columna en el origen de datos o su posicin dentro de la lista de seleccin. Si utilizamos el nombre de columna,
no hace falta que la columna aparezca en la lista de seleccin. Si utilizamos la posicin es la posicin de la columna dentro
de la lista de seleccin empezando en 1.
Por defecto la filas se ordenarn en modo ascendente (ASC), de menor a mayor; si queremos invertir ese orden aadimos
detrs de la columna la palabra DESC.

Si la columna de ordenacin es alfanumrica, las filas se ordenarn por orden alfabtico.

Si la columna de ordenacin es numrica, las filas se ordenarn de menor a mayor.

Si la columna de ordenacin es de tipo fecha, las filas se ordenarn de ms antigua a ms reciente o futura.

Ejemplos:
Mostrar las ventas de cada oficina, ordenadas por orden alfabtico de regin y dentro de cada regin por ciudad.
SELECT oficina, region, ciudad, ventas
FROM oficinas
ORDER BY region, ciudad;
Da como resultado:
Oficina

region

ciudad

ventas

24

centro

Aranjuez

15000,00

23

centro

Madrid

NULL

12

este

Alicante

73500,00

13

este

Castelln

36800,00

11

este

Valencia

69300,00

28

este

Valencia

0,00

26

norte

Pamplona

NULL

81

22

oeste

A Corua

18600,00

21

oeste

Badajoz

83600,00

Listar las oficinas de manera que las oficinas de mayores ventas aparezcan en primer lugar.
SELECT ciudad, region, ventas
FROM oficinas
ORDER BY ventas DESC;
ciudad

region

ventas

Badajoz

oeste

83600,00

Alicante

este

73500,00

Valencia

este

69300,00

Castellon

este

36800,00

A Corua

oeste

18600,00

Aranjuez

centro

15000,00

Valencia

este

0,00

Pamplona

norte

NULL

Madrid

centro

NULL

Listar las oficinas clasificadas en orden descendente de rendimiento de ventas, de modo que las de mayor rendimiento
aparezcan las primeras.
SELECT ciudad, region, ventas-objetivo
FROM oficinas
ORDER BY 3 DESC;
Lo mismo que el anterior pero agrupadas por regin.
SELECT region, ciudad, (ventas-objetivo) AS superavit
FROM oficinas

82

ORDER BY region, superavit DESC;


Resultado:
Region

ciudad

superavit

centro

Aranjuez

-10000,00

centro

Madrid

NULL

este

Valencia

11800,00

este

Castelln

1800,00

este

Alicante

-6500,00

este

Valencia

-90000,00

norte

Pamplona

NULL

oeste

Badajoz

11100,00

oeste

A Corua

-11400,00

En este caso hemos utilizado el alias de columna para hacer referencia a la columna calculada y tambin se puede observar
que las filas aparecen ordenadas por regin ascendente (no hemos incluido nada despus del nombre de la columna) y
dentro de cada regin por supervit y descendente.

3.11. Eliminar filas duplicadas DISTINCT/ALL


SQL no elimina las filas duplicadas en el resultado de la consulta, si nosotros no queremos que se repitan las filas, tenemos
la clusula DISTINCT.
Al incluir la clusula DISTINCT en la SELECT, se eliminar del resultado las repeticiones de filas de resultado. Si por el
contrario queremos que aparezcan todas las filas seleccionadas podemos incluir la clusula ALL o nada, ya que ALL es el
valor por defecto.
Listar los n de empleado de los directores de las oficinas.
SELECT dir
FROM oficinas;
dir

83

106
104
105
108
108
108
108
NULL
NULL
Si un mismo empleado dirige varias oficinas (por ejemplo el 108), su cdigo aparece repetido en el resultado. Para evitarlo
modificamos la consulta:
SELECT DISTINCT dir
FROM oficinas;
dir
NULL
104
105
106
108
Han desaparecido los valores duplicados.
Los que se eliminan son valores duplicados de filas del resultado, por ejemplo:
SELECT DISTINCT dir, region
FROM oficinas;

84

dir

region

NULL

este

NULL

norte

104

este

105

este

106

este

108

centro

108

oeste

Ahora el 108 aparece dos veces porque las dos filas donde aparece no son iguales (porque tienen distinta regin).
NOTA: La clusula DISTINCT hace que la consulta tarde algo ms en ejecutarse debido al proceso adicional de buscar y
eliminar las repeticiones, por lo que se aconseja utilizarla nicamente cuando sea imprescindible.
3.12. La clusula TOP
[TOP <expresin> [PERCENT] [WITH TIES]]
La clusula TOP indica que en el resultado no deben aparecer todas las filas resultantes sino un cierto nmero de registros,
las n primeras. Si la consulta incluye la clusula ORDER BY, se realiza la ordenacin antes de extraer los n primeros
registros.
La expresin representa ese nmero n y debe devolver un nmero entero sin signo.
Por ejemplo tenemos la siguiente tabla:
SELECT * FROM productos:

Si ordenamos por ventas:


SELECT * FROM productos

85

ORDER BY ventas;

Obtenemos el siguiente resultado:


Si aadimos la clusula TOP:
SELECT TOP 3 * FROM productos
ORDER BY ventas
Obtenemos los 3 primeros registros:

Si existen ms registros con las mismas ventas que el ltimo valor de la lista, stos no saldrn en el resultado de la
consulta.
En el ejemplo el registro con cod = 2 no sale en el resultado y tiene las mismas ventas que cod = 3.
Si queremos que salgan aadimos la clusula WITH TIES. La clusula WITH TIES slo se puede emplear si la SELECT
incluye un ORDER BY, de lo contrario dar error.
Si aadimos la clusula WITH TIES:
SELECT TOP 3 WITH TIES *
FROM productos
ORDER BY ventas
Obtenemos:

Se incluyen en el resultado todos los registros que tienen ventas iguales al ltimo registro.
Otro ejemplo:

86

SELECT TOP 10 oficina, ciudad, ventas


FROM oficinas
ORDER BY ventas;
Devuelve las 10 peores oficinas en cuanto a ventas: ordenamos las oficinas por ventas de menor a mayor y sacamos las 10
primeras.
Si incluimos la palabra PERCENT, entonces n no indica el nmero de registros a recuperar sino el porcentaje de registros a
recuperar del total de filas recuperadas despus de ejecutar la clusula WHERE.
SELECT TOP 50 PERCENT *
FROM productos
ORDER BY ventas
Devuelve:

Si el porcentaje no da exacto, siempre redondea al alza.


3.13. Seleccin de filas WHERE
La clusula WHERE se emplea para especificar las filas que se desean recuperar del origen de datos.
WHERE <condicion_bsqueda>
<condicion_bsqueda> ::=
{ [NOT]<predicado>
|(<condicion_bsqueda>)
}
[{AND|OR} [NOT] {<predicado>|(<condicion_bsqueda>)}]
[ ...n ]
En el resultado de la consulta slo aparecern las filas que cumplan que la condicin de bsqueda sea TRUE, los valores
NULL no se incluyen, por lo tanto, en las filas del resultado. La condicin de bsqueda puede ser una condicin simple o
una condicin compuesta por varias condiciones (predicados) unidas por operadores AND y OR, no hay lmite en cuanto al
nmero de predicados que se pueden incluir. En las condiciones compuestas se pueden utilizar parntesis para delimitar
predicados y se aconseja su uso cuando se incluyen operadores AND y OR en la misma condicin de bsqueda.

87

3.14. Predicados
En SQL tenemos 7 tipos de predicados, condiciones bsicas de bsqueda:

Comparacin estndar

Pertenencia a un intervalo (BETWEEN)

Pertenencia a un conjunto (IN)

Test de valor nulo (IS NULL).

Coincidencia con patrn (LIKE)

Si contiene (CONTAINS)

FREETEXT

Comparacin estndar.
Compara el valor de una expresin con el valor de otra. Para la comparacin se pueden emplear = , <> , !=, < , <= , !<,
> , >= ,!>
Sintaxis:
<expresion> {=|<>|!=|>|>=|!>|<|<=|!<} <expresion>
<expresion> Puede ser:

Un nombre de columna,

una constante,

una funcin (inclusive la funcin CASE),

una variable,

una subconsulta escalar o

cualquier combinacin de nombres de columna, constantes y funciones conectados mediante uno o varios
operadores o una subconsulta.

Ejemplo:
Listar los "buenos" vendedores (los que han rebasado su cuota).
SELECT numemp, nombre, ventas, cuota
FROM empleados
WHERE ventas > cuota

88

numemp

nombre

ventas

cuota

101

Antonio Viguer

30500,00

30000,00

102

Alvaro Jaumes

47400,00

35000,00

103

Juan Rovira

28600,00

27500,00

105

Vicente Pantalla

36800,00

35000,00

106

Luis Antonio

29900,00

27500,00

108

Ana Bustamante

36100,00

35000,00

109

Mara Sunta

39200,00

3000,00

Las columnas que aparecen en el WHERE no tienen por qu aparecer en la lista de seleccin, esta instruccin es igual de
vlida:
SELECT numemp, nombre
FROM empleados
WHERE ventas > cuota;
Hallar vendedores contratados antes de 1988.
SELECT numemp, nombre, contrato
FROM empleados
WHERE contrato < '01/01/1988';
numemp

nombre

contrato

101

Antonio Viguer

1986-10-20

102

Alvaro Jaumes

1986-12-10

103

Juan Rovira

1987-03-01

104

Jos Gonzlez

1987-05-19

Tambin podemos utilizar funciones, sta es equivalente a la anterior:

89

SELECT numemp, nombre


FROM empleados
WHERE YEAR(contrato) < 1988;
La funcin YEAR(fecha) devuelve el ao de una fecha.
Hallar oficinas cuyas ventas estn por debajo del 80% de su objetivo:
SELECT oficina
FROM oficinas
WHERE ventas < (.8 * objetivo);
Hallar las oficinas dirigidas por el empleado 108:
SELECT oficina
FROM oficinas
WHERE dir = 108;

Pertenencia a un intervalo. BETWEEN


<expresion> [NOT] BETWEEN <expresion2> AND <expresion3>
Examina si el valor de la expresin de test est en el rango delimitado por los valores resultantes de expresion1 y
expresion2, estos valores no tienen porqu estar ordenados en ANSI/ISO; expresion1 debe ser menor o igual a expresion2.
Hallar vendedores cuyas ventas estn entre 20.000 euros y 50.000.
SELECT numemp, nombre, ventas
FROM empleados
WHERE ventas BETWEEN 20000 AND 100000;
numemp

nombre

ventas

101

Antonio Viguer

30500,00

102

Alvaro Jaumes

47400,00

103

Juan Rovira

28600,00

105

Vicente Pantalla

36800,00

106

Luis Antonio

29900,00

108

Ana Bustamante

36100,00

90

109

Mara Sunta

39200,00

La instruccin anterior es equivalente a:


SELECT numemp, nombre, ventas
FROM empleados
WHERE ventas >= 20000 AND ventas <=100000;
Parece que con BETWEEN se lee mejor.
Observa que no hemos utilizado separadores de millares (100.000), porque se habra interpretado por una coma decimal.

Test de pertenencia a conjunto IN


<expresion> IN ( <exp_valor> [ ,...n ] )
Examina si el valor de la expresion es uno de los valores incluidos en la lista de valores indicados entre parntesis. Se
pueden expresar los valores mediante cualquier expresin, la nica condicin es que todas las exp_valor devuelvan el
mismo tipo de datos.
Ejemplo:
Obtener los empleados que trabajan en las oficinas 11, 20 o 22:
SELECT oficina, numemp, nombre
FROM empleados
WHERE oficina IN (11,20,22);
oficina

numemp

nombre

11

106

Luis Antonio

22

107

Jorge Gutirrez

11

109

Mara Sunta

Para practicar puedes realizar este Ejercicio Pertenencia a un conjunto con IN.
Test de valor nulo IS NULL
<expression> IS [NOT] NULL
Una condicin de bsqueda puede ser TRUE, FALSE o NULL/UNKNOW, este ltimo caso se produce cuando algn campo
que interviene en la condicin tiene valor NULL.
A veces es til comprobar explcitamente los valores NULL en una condicin de bsqueda ya que estas filas puede que
queramos darles un tratamiento especial, para ello tenemos el predicado IS NULL.

91

Este test produce un valor TRUE o FALSE, por lo que se podr combinar con otras condiciones. El valor NULL no es en s
un valor por eso no lo podemos utilizar en una igualdad.
SELECT numemp,nombre
FROM empleados
WHERE oficina = NULL;
Esta instruccin no da error pero no obtiene lo que en principio parece que quiere obtener. No obtenemos los empleados
cuya oficina sea un valor nulo (es decir los empleados que no tienen oficina), no obtenemos nada, en cambio los
obtendremos utilizando el test de valor nulo:
SELECT numemp,nombre, oficina
FROM empleados
WHERE oficina IS NULL;
Resultado:
numemp

nombre

oficina

110

Juan Victor

NULL

Juan Victor es el nico empleado que no tiene oficina asignada.


Listar los vendedores asignados a alguna oficina.
SELECT numemp, nombre, oficina
FROM empleados
WHERE oficina IS NOT NULL;
numemp

nombre

oficina

101

Antonio Viguer

12

102

Alvaro Jaumes

21

103

Juan Rovira

12

104

Jos Gonzlez

12

105

Vicente Pantalla

13

106

Luis Antonio

11

92

107

Jorge Gutirrez

22

108

Ana Bustamante

21

109

Mara Sunta

11

Test de correspondencia con patrn LIKE


Se utiliza cuando queremos comparar el valor de una columna con un patrn en el que se utilice caracteres comodines.
<expression> [NOT] LIKE <patron> [ESCAPE 'car_escape']
Con expresin indicamos el valor a comparar (normalmente ser el nombre de una columna) y patrn es la cadena que se
busca. El patrn es de tipo texto y tiene que escribirse entre comillas simples. Dentro del patrn podemos utilizar los
siguientes comodines:
%

representa cualquier cadena de cero o ms caracteres.

SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE An%;
numemp

nombre

101

Antonio Viguer

108

Ana Bustamante

Obtiene todos los nombres que empiecen por An.


SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE %z;
numemp

nombre

104

Jos Gonzlez

107

Jos Gonzlez

Obtiene los nombres que acaban en z.

93

SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE %on%;
numemp

nombre

101

Antonio Viguer

104

Jos Gonzlez

106

Luis Antonio

Obtiene los nombres que contienen on.


_

representa cualquier carcter (slo uno).

SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '__a%';
numemp

nombre

103

Juan Rovira

108

Ana Bustamante

110

Juan Victor

Obtiene los nombres cuya tercera letra sea una a (en el patrn tenemos dos caracteres subrayado).
[ ] sirve para indicar un carcter cualquiera perteneciente al conjunto indicando.
El conjunto se indica enumerando los caracteres o indicando un intervalo.
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '[a-d]%';
Obtiene los nombres que empiezan por cualquier letra de la a a la d.
Es equivalente a escribir:
SELECT numemp,nombre

94

FROM empleados
WHERE nombre LIKE '[abcd]%';
[^] significa cualquier carcter individual que no se encuentre en el conjunto.
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '[^abcd]%';
Y
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '[^a-d]%';
Obtienen los nombres que no empiecen por a, b, c ni d.
Es importante tener en cuenta que dentro del patrn el espacio en blanco es considerado como un carcter ms, si
colocamos dos espacios en el patrn, se buscarn dos espacios en el campo.
Si queremos incluir en el patrn uno de los caracteres comodines y que no sea interpretado como un comodn, sino como un
carcter normal, lo tenemos que encerrar entre corchetes o utilizar un carcter de escape.
[ESCAPE 'car_escape']
La clusula ESCAPE es opcional y permite definir un carcter de escape.
Un carcter de escape es un carcter que se coloca delante de un carcter comodn para indicar que el comodn no debe
interpretarse como tal, sino como un carcter normal.
Por ejemplo queremos buscar los nombres compuestos que incluyen un subrayado. En este caso tenemos que poner el
carcter _ como un carcter normal no como un comodn, as que lo escribiremos as:
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '%[_]%';
O bien,
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '%!_%' ESCAPE '!';

3.15. Condiciones de bsqueda compuestas


En una clusula WHERE podemos incluir una condicin de bsqueda simple (formada por un solo predicado) o compuesta
(formada por la combinacin de predicados unidos por los operadores lgicos NOT, AND, OR).

95

Cuando la condicin incluye varios operadores lgicos, el orden de prioridad de estos operadores es:

NOT (el ms alto),

seguido de AND y OR (estos dos al mismo nivel).

Como siempre, se pueden utilizar parntesis para alterar esta prioridad en una condicin de bsqueda.
El orden de evaluacin de los operadores lgicos puede variar dependiendo de las opciones elegidas por el optimizador de
consultas.
Los operadores lgicos pueden devolver tres valores distintos: TRUE, FALSE, NULL (UNKNOWN).
Tablas de verdad de los operadores:
AND Combina dos condiciones y se evala como TRUE cuando ambas condiciones son TRUE.
AND

TRUE FALSE NULL

TRUE TRUE FALSE NULL


FALSE FALSE FALSE FALSE
NULL

NULL

FALSE NULL

OR Combina dos condiciones y se evala como TRUE cuando alguna de las condiciones es TRUE.
OR

TRUE FALSE NULL

TRUE TRUE TRUE TRUE


FALSE TRUE FALSE NULL
NULL

TRUE NULL

NULL

NOT Niega la expresin booleana que especifica el predicado


NOT TRUE FALSE NULL
FALSE TRUE NULL
Hallar los vendedores que estn por debajo de su cuota y tienen ventas inferiores a 30.000.
SELECT nombre
FROM empleados

96

WHERE ventas < cuota AND ventas < 30000;


Hallar los vendedores que estn debajo de su cuota, pero cuyas ventas no sean inferiores a 150.000.
SELECT nombre
FROM empleados
WHERE ventas < cuota AND ventas < 150000;
Hallar las oficinas no dirigidas por el empleado 108
SELECT oficina
FROM oficinas
WHERE NOT dir = 108;
O
SELECT oficina
FROM oficinas
WHERE dir <> 108;
Devuelven:
oficina
11
12
13
Las oficinas sin director no aparecen, para que aparezcan deben aadir otro predicado:
SELECT oficina, dir
FROM oficinas
WHERE NOT dir = 108 or dir is null;
oficina

dir

11

106

12

104

13

105

97

26

NULL

28

NULL

Unidad 4. Consultas multitabla (I)


4.1. Introduccin
Hasta ahora hemos visto consultas que obtienen los datos de una sola tabla, en este tema veremos cmo obtener datos de
diferentes tablas.
En esta parte ampliaremos la clusula FROM y descubriremos nuevas palabras reservadas (UNION, EXCEPT e
INTERSECT) que corresponden a operaciones relacionales.
Para obtener datos de varias tablas tenemos que combinar estas tablas mediante alguna operacin basada en el lgebra
relacional.
El lgebra relacional define una serie de operaciones cuyos operandos son tablas y cuyo resultado es tambin una tabla.
Las operaciones de lgebra relacional implementadas en Transact-Sql son:

La unin UNION

La diferencia EXCEPT

La interseccin INTERSECT

El producto cartesiano CROSS JOIN

La composicin interna INNER JOIN

La composicin externa LEFT JOIN, RIGHT JOIN Y FULL JOIN

En todo el tema cuando hablemos de tablas nos referiremos tanto a las tablas que fsicamente estn almacenadas en la
base de datos como a las tablas temporales y a las resultantes de una consulta o vista.
4.2. La unin de tablas UNION
La unin de tablas consiste en coger dos tablas y obtener una tabla con las filas de las dos tablas, en el resultado
aparecern las filas de una tabla y, a continuacin, las filas de la otra tabla.
Para poder realizar la operacin, las dos tablas tienen que tener el mismo esquema (mismo nmero de columnas y tipos
compatibles) y la tabla resultante hereda los encabezados de la primera tabla.
La sintaxis es la siguiente:
{< consulta >|(< consulta >)}
UNION [ALL]
{< consulta >|(< consulta >)}
[{UNION [ALL] {< consulta >|(< consulta >)}}[ ...n ] ]
[ORDER BY {expression_columna|posicion_columna [ASC|DESC]}

98

[ ,...n ]]
<

consulta

>

representa

la

especificacin

de

la

consulta

que

nos

devolver

la

tabla

combinar.

Puede ser cualquier especificacin de consulta con la limitacin de que no admite la clusula ORDER BY, los alias de
campo se pueden definir pero slo tienen efecto cuando se indican en la primera consulta ya que el resultado toma los
nombres de columna de esta.
Ejemplo: Suponemos que tenemos una tabla Valencia con las nuevas oficinas de Valencia y otra tabla Madrid con las
nuevas oficinas de Madrid y queremos obtener una tabla con las nuevas oficinas de las dos ciudades:
SELECT oficina as OFI, ciudad FROM Valencia
UNION ALL
SELECT oficina, ciudad FROM Madrid;
El resultado sera:
OFI

ciudad

11

Valencia

28

Valencia

23

Madrid

El resultado coge los nombres de columna de la primera consulta y aparecen primero las filas de la primera consulta y
despus las de la segunda.
Si queremos que el resultado aparezca ordenado podemos incluir la clusula ORDER BY, pero despus de la ltima
especificacin de consulta, y expresion_columna ser cualquier columna vlida de la primera consulta.
SELECT oficina as OFI, ciudad FROM Valencia
UNION
SELECT oficina, ciudad FROM Madrid
ORDER BY ofi;
OFI

ciudad

11

Valencia

23

Madrid

28

Valencia

99

Ahora las filas aparecen ordenadas por el nmero de oficina y hemos utilizado el nombre de columna de la primera consulta.
Cuando

aparezcan

en

el

resultado

varias

filas

iguales,

el

sistema

por

defecto

elimina

las

repeticiones.

Si se especifica ALL, el sistema devuelve todas las filas resultante de la unin incluidas las repetidas
El empleo de ALL tambin hace que la consulta se ejecute ms rpidamente ya que el sistema no tiene que eliminar las
repeticiones.
Se pueden combinar varias tablas con el operador UNION. Por ejemplo supongamos que tenemos otra tabla Pamplona con
las oficinas nuevas de Pamplona:
SELECT oficina, ciudad FROM Valencia
UNION
SELECT oficina, ciudad FROM Madrid
UNION
SELECT oficina, ciudad FROM Pamplona;
Combinamos las tres tablas.
Otro ejemplo:
Obtener todos los productos cuyo precio exceda de 20 o que se haya vendido ms de 300 euros del producto en algn
pedido.
SELECT idfab, idproducto
FROM productos
WHERE precio > 20
UNION
SELECT fab, producto
FROM pedidos
WHERE importe > 300;

4.3. La diferencia EXCEPT


Aparecen

en

la

tabla

resultante

las

filas

de

la

primera

consulta

que

no

aparecen

en

la

segunda.

Las condiciones son las mismas que las de la unin.


{<consulta>|(<consulta>)}
EXCEPT
{<consulta>|(<consulta>)}
[{EXCEPT {<consulta>|(<consulta>)}}[ ...n ] ]
[ORDER BY {expression_columna|posicion_columna [ASC|DESC]}
[ ,...n ]]

100

Por ejemplo tenemos las tablas T1 y T2.


T1

T2

Cod
Codigo
1
2
2
3
4
4
5
5
6

SELECT cod FROM T1


EXCEPT
SELECT codigo FROM T2;
Devuelve:
Cod
1
6
Ejemplo:
Listar los productos que no aparezcan en ningn pedido.
SELECT idfab, idproducto
FROM productos
EXCEPT
SELECT DISTINCT fab, producto
FROM pedidos;

4.4. La interseccin INTERSECT


Tiene una sintaxis parecida a las anteriores pero en el resultado de la interseccin aparecen las filas que estn
simultneamente en las dos consultas.
Las condiciones son las mismas que las de la unin.

101

{ <consulta>|(<consulta>)}
INTERSECT
{<especificacion_consulta>|(<especificacion_consulta>)}
[{INTERSECT {<consulta>|(<consulta>)}} [ ...n ] ]
[ORDER BY {expression_columna|posicion_columna [ASC|DESC]}
[ ,...n ]]
Retomando el ejemplo anterior:
SELECT cod FROM T1
INTERSECT
SELECT cod FROM T2;
Devuelve:
Cod
2
4
5
Ejemplo: Obtener todos los productos que valen ms de 20 euros y que adems se haya vendido en un pedido ms de 300
euros de ese producto.
SELECT idfab, idproducto
FROM productos
WHERE precio > 20
INTERSECT
SELECT fab, producto
FROM pedidos
WHERE importe > 300;

4.5. La composicin de tablas


Hasta ahora hemos operado con tablas que tenan el mismo esquema, pero muchas veces lo que necesitamos es obtener
una tabla que tenga en una misma fila datos de varias tablas, por ejemplo, obtener las facturas y que en la misma fila de
factura aparezca el nombre y direccin del cliente. Pues en lo que queda del tema estudiaremos este tipo de consultas
basadas en la composicin de tablas. La composicin de tablas consiste en obtener a partir de dos tablas cualesquiera una

102

nueva tabla fusionando las filas de una con las filas de la otra, concatenando los esquemas de ambas tablas. Consiste en
formar parejas de filas.
La sentencia SELECT permite realizar esta composicin, incluyendo dos o ms tablas en la clusula FROM.
Es hora de ampliar la clusula FROM que vimos en el tema anterior.
Empezaremos por estudiar la operacin a partir de la cual estn definidas las dems operaciones de composicin de tabla,
el producto cartesiano.

4.6. El producto cartesiano CROSS JOIN


El producto cartesiano obtiene todas las posibles concatenaciones de filas de la primera tabla con filas de la segunda tabla.
Se indica escribiendo en la clusula FROM los nombres de las tablas separados por una coma o utilizando el operador
CROSS JOIN.
FROM {<tabla_origen>} [ ,...n ]

|<tabla_origen> CROSS JOIN <tabla_origen>


Tabla_origen puede ser un nombre de tabla o de vista o una tabla derivada (resultado de una SELECT), en este ltimo caso
la SELECT tiene que aparecer entre parntesis y la tabla derivada debe llevar asociado obligatoriamente un alias de tabla.
Tambin puede ser una composicin de tablas.
Se pueden utilizar hasta 256 orgenes de tabla en una instruccin, aunque el lmite vara en funcin de la memoria disponible
y de la complejidad del resto de las expresiones de la consulta. Tambin se puede especificar una variable table como un
origen de tabla.
Ejemplo:
SELECT *
FROM empleados, oficinas;
Si ejecutamos esta consulta veremos que las filas del resultado estn formadas por las columnas de empleados y las
columnas de oficinas. En las filas aparece cada empleado combinado con la primera oficina, luego los mismos empleados
combinados

con

la

segunda oficina

y as hasta combinar

todos

los

empleados

con

todas

las

oficinas.

Si ejecutamos:
SELECT *
FROM empleados CROSS JOIN oficinas;
Obtenemos lo mismo.
Este tipo de operacin no es la que se utiliza ms a menudo, lo ms frecuente sera combinar cada empleado con los datos
de SU oficina. Lo podramos obtener aadiendo a la consulta un WHERE para filtrar los registros correctos:
SELECT *
FROM empleados, oficinas

103

WHERE empleados.oficina=oficinas.oficina;
Aqu nos ha aparecido la necesidad de cualificar los campos ya que el nombre oficina es un campo de empleados y de
oficinas por lo que si no lo cualificamos, el sistema nos da error.
Hemos utilizado en la lista de seleccin *, esto nos recupera todas las columnas de las dos tablas.
SELECT empleados.*,ciudad, region
FROM empleados, oficinas
WHERE empleados.oficina=oficinas.oficina;
Recupera todas las columnas de empleados y las columnas ciudad y regin de oficinas.
Tambin podemos combinar una tabla consigo misma, pero en este caso hay que definir un alias de tabla, en al menos una,
sino el sistema da error ya que no puede nombrar los campos.
SELECT *
FROM oficinas, oficinas as ofi2;
No insistiremos ms sobre el producto cartesiano porque no es la operacin ms utilizada, ya que normalmente cuando
queramos componer dos tablas lo haremos con una condicin de seleccin basada en campos de combinacin y para este
caso es ms eficiente el JOIN que veremos a continuacin.
4.7. La composicin interna INNER JOIN
Una composicin interna es aquella en la que los valores de las columnas que se estn combinando se comparan mediante
un operador de comparacin.
Es otra forma, mejor, de expresar un producto cartesiano con una condicin.
Es la operacin que ms emplearemos ya que lo ms frecuente es querer juntar los registros de una tabla relacionada con
los registros correspondientes en la tabla de referencia (aadir a cada factura los datos de su cliente, aadir a cada lnea de
pedido los datos de su producto, etc..,).
FROM
<tabla_origen> INNER JOIN <tabla_origen> ON <condicion_combi>
tabla_origen tiene el mismo significado que en el producto cartesiano.
condicion_combi es cualquier condicin que permite seleccionar las parejas de filas que aparecen en el resultado.
Normalmente ser una condicin de igualdad.
SELECT *
FROM empleados INNER JOIN oficinas
ON empleados.oficina=oficinas.oficina;
Obtiene los empleados combinados con los datos de su oficina.

104

SELECT *
FROM pedidos INNER JOIN productos
ON producto = idproducto AND fab = idfab;
Obtiene los pedidos combinados con los productos correspondientes.
Normalmente la condicin de combinacin ser una igualdad pero se puede utilizar cualquier operador de comparacin (<>,
>).
Es fcil ver la utilidad de esta instruccin y de hecho se utilizar muy a menudo, pero hay algn caso que no resuelve. En las
consultas anteriores, no aparecen las filas que no tienen fila correspondiente en la otra tabla.
SELECT numemp,nombre,empleados.oficina, ciudad
FROM empleados INNER JOIN oficinas
ON empleados.oficina=oficinas.oficina;
numemp

nombre

oficina

ciudad

101

Antonio Viguer

12

Alicante

102

Alvaro Jaumes

21

Badajoz

103

Juan Rovira

12

Alicante

104

Jos Gonzlez

12

Alicante

105

Vicente Pantalla

13

Castelln

106

Luis Antonio

11

Valencia

107

Jorge Gutirrez

22

A Corua

108

Ana Bustamante

21

Badajoz

109

Mara Sunta

11

Valencia

No aparecen los empleados que no tienen oficina, ni las oficinas que no tienen empleados, porque para que salga la fila,
debe de existir una fila de la otra tabla que cumpla la condicin.
Para resolver este problema debemos utilizar otro tipo de composicin, la composicin externa.
4.8. La Composicin externa LEFT, RIGHT y FULL OUTER JOIN
La composicin externa se escribe de manera similar al INNER JOIN indicando una condicin de combinacin pero en el
resultado se aaden filas que no cumplen la condicin de combinacin.

105

Sintaxis
FROM
<tabla_origen> {LEFT|RIGHT|FULL} [OUTER] JOIN <tabla_origen>
ON <condicion_combi>
La palabra OUTER es opcional y no aade ninguna funcin.
Las palabras LEFT, RIGHT y FULL indican la tabla de la cual se van a aadir las filas sin correspondencia.
SELECT numemp,nombre,empleados.oficina, ciudad
FROM empleados LEFT JOIN oficinas
ON empleados.oficina=oficinas.oficina;
numemp

nombre

oficina

ciudad

101

Antonio Viguer

12

Alicante

102

Alvaro Jaumes

21

Badajoz

103

Juan Rovira

12

Alicante

104

Jos Gonzlez

12

Alicante

105

Vicente Pantalla

13

Castelln

106

Luis Antonio

11

Valencia

107

Jorge Gutirrez

22

A Corua

108

Ana Bustamante

21

Badajoz

109

Mara Sunta

11

Valencia

110

Juan Victor

NULL

NULL

Ahora s aparece el empleado 110 que no tiene oficina


Obtiene los empleados con su oficina y los empleados (tabla a la izquierda LEFT del JOIN) que no tienen oficina aparecern
tambin en el resultado con los campos de la tabla oficinas rellenados a NULL.
SELECT numemp,nombre,empleados.oficina, ciudad, oficinas.oficina

106

FROM empleados RIGHT JOIN oficinas


ON empleados.oficina=oficinas.oficina;
numemp

nombre

oficina

ciudad

oficina

106

Luis Antonio

11

Valencia

11

109

Mara Sunta

11

Valencia

11

101

Antonio Viguer

12

Alicante

12

103

Juan Rovira

12

Alicante

12

104

Jos Gonzlez

12

Alicante

12

105

Vicente Pantalla

13

Castelln

13

102

Alvaro Jaumes

21

Badajoz

21

108

Ana Bustamante

21

Badajoz

21

107

Jorge Gutirrez

22

A Corua

22

NULL

NULL

NULL

Madrid

23

NULL

NULL

NULL

Aranjuez

24

NULL

NULL

NULL

Pamplona

26

NULL

NULL

NULL

Valencia

28

Las oficinas 23,24,26 y 28 no tienen empleados.


Obtiene los empleados con su oficina y las oficinas (tabla a la derecha RIGHT del JOIN) que no tienen empleados
aparecern tambin en el resultado con los campos de la tabla empleados rellenados a NULL.
SELECT numemp,nombre,empleados.oficina, ciudad, oficinas.oficina
FROM empleados FULL JOIN oficinas
ON empleados.oficina=oficinas.oficina;

107

numemp

nombre

oficina

ciudad

oficina

101

Antonio Viguer

12

Alicante

12

102

Alvaro Jaumes

21

Badajoz

21

103

Juan Rovira

12

Alicante

12

104

Jos Gonzlez

12

Alicante

12

105

Vicente Pantalla

13

Castelln

13

106

Luis Antonio

11

Valencia

11

107

Jorge Gutirrez

22

A Corua

22

108

Ana Bustamante

21

Badajoz

21

109

Mara Sunta

11

Valencia

11

110

Juan Victor

NULL

NULL

NULL

NULL

NULL

NULL

Madrid

23

NULL

NULL

NULL

Aranjuez

24

NULL

NULL

NULL

Pamplona

26

NULL

NULL

NULL

Valencia

28

Aparecen tanto los empleados sin oficina como las oficinas sin empleados.
SELECT numemp,nombre,empleados.oficina, ciudad, oficinas.oficina
FROM empleados FULL OUTER JOIN oficinas
ON empleados.oficina=oficinas.oficina;
Es equivalente, la palabra OUTER como hemos dicho no aade ninguna funcionalidad y se utiliza si se quiere por
cuestiones de estilo.
NOTA: Cuando necesitamos obtener filas con datos de dos tablas con una condicin de combinacin utilizaremos un JOIN,
os aconsejo empezar por escribir el JOIN con la condicin que sea necesaria para combinar las filas, y luego plantearos si la
composicin debe de ser interna o externa. Para este segundo paso sta sera la norma a seguir:

108

Empezamos con INNER JOIN.

Si pueden haber filas de la primera tabla que no estn relacionadas con filas de la segunda tabla y nos interesa que
salgan en el resultado, entonces cambiamos a LEFT JOIN.

Si pueden haber filas de la segunda tabla que no estn relacionadas con filas de la primera tabla y nos interesa que
salgan en el resultado, entonces cambiamos a RIGHT JOIN.

Si necesitamos LEFT y RIGHT entonces utilizamos FULL JOIN.

Siguiendo el ejemplo anterior nos preguntaramos:


Pueden haber empleados que no tengan oficina y nos interesan?, si es que s, necesitamos un LEFT JOIN.
Seguiramos preguntando:
Pueden haber oficinas que no tengan empleados y nos interesan?, si es que s, necesitamos un RIGHT JOIN.
Si al final necesitamos LEFT y tambin RIGHT entonces utilizamos FULL JOIN.

4.9. Combinar varias operaciones


En las operaciones anteriores tabla_origen puede ser a su vez una composicin de tablas, en este caso aunque slo sea
obligatorio cuando queramos cambiar el orden de ejecucin de las composiciones, es recomendable utilizar parntesis para
delimitar las composiciones.
Por ejemplo:
SELECT numemp, nombre, empleados.oficina, ciudad, oficinas.oficina, pedidos.*
FROM (oficinas RIGHT JOIN empleados
ON empleados.oficina = oficinas.oficina)
INNER JOIN pedidos on rep=numemp;
O bien:
SELECT numemp, nombre, empleados.oficina, ciudad, oficinas.oficina, pedidos.*
FROM oficinas RIGHT JOIN (empleados INNER JOIN pedidos on rep = numemp)
ON empleados.oficina = oficinas.oficina);

Unidad 5. Consultas de resumen (II)


5.1. Introduccin
Una de las funcionalidades de la sentencia SELECT es el permitir obtener resmenes de los datos contenidos en las
columnas de las tablas.
Para poder llevarlo a cabo la sentencia SELECT consta de una serie de clusulas especficas (GROUP BY, HAVING), y
Transact-SQL tiene definidas unas funciones para poder realizar estos clculos, las funciones de agregado (tambin
llamadas funciones de columna).

109

La diferencia entre una consulta de resumen y una consulta de las que hemos visto hasta ahora es que en las consultas
normales las filas del resultado se obtienen directamente de las filas del origen de datos y cada dato que aparece en el
resultado tiene su dato correspondiente en el origen de la consulta mientras que las filas generadas por las consultas de
resumen no representan datos del origen sino un total calculado sobre estos datos. Esta diferencia har que las consultas de
resumen tengan algunas limitaciones que veremos a lo largo del tema.
Un ejemplo sera:

A la izquierda tenemos una consulta simple que nos saca las oficinas con sus ventas ordenadas por regin, y a la derecha
una consulta de resumen que obtiene la suma de las ventas de las oficinas de cada regin
5.2. Las funciones de agregado
Una funcin de agregado SQL acepta un grupo de datos (normalmente una columna de datos) como argumento, y produce
un nico dato que resume el grupo. Por ejemplo la funcin AVG() acepta una columna de datos numricos y devuelve la
media aritmtica (average) de los valores contenidos en la columna.
El mero hecho de utilizar una funcin de agregado en una consulta, convierte sta en una consulta de resumen.
Todas las funciones de agregado tienen una estructura muy parecida:
Funcin ([ALL|DISTINCT] expression)
El grupo de valores sobre el que acta la funcin lo determina el resultado de la expresin que ser un nombre de columna o
una expresin basada en una columna o varias del origen de datos. En la expresin nunca puede aparecer una funcin de
agregado ni una subconsulta.
La palabra ALL indica que se tiene que tomar en cuenta todos los valores de la columna. Es el valor por defecto.
La palabra DISTINCT hace que se consideren todas las repeticiones del mismo valor como uno slo (considera valores
distintos).
Todas las funciones de agregado se aplican a las filas del origen de datos una vez ejecutada la clusula WHERE (si la
hubiera).
Si exceptuamos la funcin COUNT, todas las funciones de agregado ignoran los valores NULL.

110

Una funcin de agregado puede aparecer en la lista de seleccin en cualquier lugar en el que puede aparecer un nombre de
columna. Puede, por ejemplo, formar parte de una expresin pero no se pueden anidar funciones de agregado.
Tampoco se pueden mezclar funciones de columna con nombres de columna ordinarios. Hay excepciones a esta regla pero
cuando definimos agrupaciones y subconsultas que veremos ms adelante.

5.3. La funcin COUNT


COUNT ({[ALL|DISTINCT] expresion | * } )
Expresion puede ser de cualquier tipo excepto text, image o ntext. No se permite utilizar funciones de agregado ni
subconsultas. El tipo de dato devuelto es int.
Si el nmero de valores devueltos por expresion es superior a 231-1, COUNT genera un error, en ese caso hay que utilizar
la funcin COUNT_BIG.
La funcin cuenta los valores distintos de NULL que hay en la columna. La palabra ALL indica que se tienen que tomar todos
los valores de la columna, mientras que DISTINCT hace que se consideren todas las repeticiones del mismo valor como uno
solo. Estos parmetros son opcionales, por defecto se considera ALL.
Por ejemplo:
SELECT COUNT(region) FROM oficinas;
Devuelve 9 porque tenemos nueve valores no nulos en la columna region. A la hora de interpretar un COUNT es
conveniente no olvidar que cuenta valores no nulos, por ejemplo si interpretramos la sentencia tal cual se lee, cuntas
regiones tenemos en oficinas sera errneo, realmente estamos obteniendo cuntas oficinas tienen una regin asignada.

SELECT COUNT(DISTINCT region) FROM oficinas;


Devuelve 4 porque tenemos cuatro valores distintos, no nulos, en la columna regin, los valores repetidos los considera slo
una vez. Ahora s nos devuelve cuntas regiones tenemos en oficinas.
Si utilizamos * en vez de expresin, devuelve el nmero de filas del origen que nos quedan despus de ejecutar la clusula
WHERE.
COUNT(*) no acepta parmetros y no se puede utilizar con DISTINCT. COUNT(*) no requiere un parmetro expression
porque, por definicin, no utiliza informacin sobre ninguna columna especfica. En el recuento se incluyen las filas que
contienen valores NULL.
SELECT COUNT(*) FROM empleados WHERE oficina=12;
Obtiene el nmero de empleados asignados a la oficina 12.
Si tenemos un COUNT(columna) y columna no contiene valores nulos, se obtiene el mismo resultado que COUNT(*) pero el
COUNT(*) es ms rpido por lo que en este caso hay que utilizarlo en vez de COUNT(columna).
Por ejemplo:
SELECT COUNT(*) FROM empleados WHERE oficina IS NOT NULL;
Es mejor que:

111

SELECT COUNT(oficina) FROM empleados WHERE oficina IS NOT NULL;

Las dos nos devuelven el nmero de empleados que tienen una oficina asignada pero la primera es mejor porque se calcula
ms rpidamente.

5.4. La funcin COUNT_BIG


Funciona igual que la funcin COUNT. La nica diferencia entre ambas funciones est en los valores devueltos,
COUNT_BIG siempre devuelve un valor de tipo bigint y por lo tanto admite ms valores de entrada, no est limitado a 2311 valores de entrada como COUNT.

5.5. La funcin MAX


MAX ([ALL|DISTINCT] expression)
Devuelve el valor mximo de la expresin sin considerar los nulos.
MAX se puede usar con columnas numricas, de caracteres y de datetime, pero no con columnas de bit. No se permiten
funciones de agregado ni subconsultas.
Utilizar DISTINCT no tiene ningn sentido con MAX (el valor mximo ser el mismo si consideramos las repeticiones o no) y
slo se incluye para la compatibilidad con SQL-92.
Por ejemplo:
SELECT SUM(ventas) AS VentasTotales, MAX(objetivo) AS MayorObjetivo
FROM oficinas;
Devuelve 9 porque tenemos nueve valores no nulos en la columna region. A la hora de interpretar un COUNT es
conveniente no olvidar que cuenta valores no nulos, por ejemplo si interpretramos la sentencia tal cual se lee, cuntas
regiones tenemos en oficinas sera errneo, realmente estamos obteniendo cuntas oficinas tienen una regin asignada.

5.6. La funcin MIN


MIN ([ALL|DISTINCT] expression)
Devuelve el valor mnimo de la expresin sin considerar los nulos.
MIN se puede usar con columnas numricas, de caracteres y de datetime, pero no con columnas de bit. No se permiten
funciones de agregado ni subconsultas.
Utilizar DISTINCT no tiene ningn sentido con MIN (el valor mnimo ser el mismo si consideramos las repeticiones o no) y
slo se incluye para la compatibilidad con SQL-92.

5.7. La funcin SUM


SUM ([ALL|DISTINCT] expresion )
Devuelve la suma de los valores devueltos por la expresin.

112

Slo puede utilizarse con columnas numricas.


El resultado ser del mismo tipo aunque puede tener una precisin mayor.
SELECT SUM(importe) FROM pedidos;
Obtiene el importe total vendido en todos los pedidos.
SELECT SUM(ventas) AS VentasTotales, MAX(objetivo) AS MayorObjetivo
FROM oficinas;
Devuelve la suma de las ventas de todas las oficinas y de los objetivos de todas las oficinas, el de mayor importe.

5.8. La funcin AVG


AVG ([ALL|DISTINCT] expresion )
Devuelve el promedio de los valores de un grupo, para calcular el promedio se omiten los valores nulos.
El grupo de valores lo determina el resultado de la expresin que ser un nombre de columna o una expresin basada en
una columna o varias del origen de datos.
La funcin se aplica tambin a campos numricos, y en este caso el tipo de dato del resultado puede cambiar segn las

necesidades del sistema para representar el valor del resultado.


5.9. La funcin VAR
VAR ([ALL|DISTINCT] expresion )
Devuelve la varianza estadstica de todos los valores de la expresin especificada.
VAR slo se puede utilizar con columnas numricas. Los valores NULL se pasan por alto.

5.10. La funcin VARP


VARP ([ALL|DISTINCT] expresion )
Devuelve

la

varianza

estadstica

de

la

poblacin

para

todos

los

valores

de

la

expresin

especificada.

Slo se puede utilizar con columnas numricas. Los valores NULL se pasan por alto.

5.11. La funcin STDEV


STDEV ([ALL|DISTINCT] expresion )
Devuelve la desviacin tpica estadstica de todos los valores de la expresin especificada.
Slo se puede utilizar con columnas numricas. Los valores NULL se pasan por alto.

5.12. La funcin STDEVP


STDEVP ([ALL|DISTINCT] expresion )
Devuelve la desviacin estadstica estndar para la poblacin de todos los valores de la expresin especificada.
Slo se puede utilizar con columnas numricas. Los valores NULL se pasan por alto.

113

5.13. La funcin GROUPING


GROUPING (nb_columna)
Es una funcin de agregado que genera como salida una columna adicional con el valor 1 si la fila se agrega mediante el
operador CUBE o ROLLUP, o el valor 0 cuando la fila no es el resultado de CUBE o ROLLUP.
Nb_columna tiene que ser una de las columnas de agrupacin y la clusula GROUP BY debe contener el operador CUBE o
ROLLUP.
En el siguiente punto, cuando veamos las clusulas CUBE y ROLLUP quedar ms claro.

5.14. Agrupamiento de filas (clusula GROUP BY).


Hasta ahora las consultas sumarias que hemos visto obtienen totales de todas las filas del origen y producen una nica fila
de resultado.
Muchas veces cuando calculamos resmenes nos interesan totales parciales, por ejemplo saber de cada empleado cunto
ha vendido, y cul ha sido su pedido mximo, de cada cliente cundo fue la ltima vez que nos compr, etc.
En todos estos casos en vez de obtener una fila nica de resultados necesitamos una fila por cada empleado, cliente, etc.
Podemos obtener estos subtotales con la clusula GROUP BY.
GROUP BY [ ALL ] expresion_agrupacion [ ,...n ]
[ WITH { CUBE | ROLLUP } ]
Una consulta con una clusula GROUP BY agrupa los datos de la tabla origen y produce una nica fila resultado por cada
grupo formado. Las columnas indicadas en el GROUP BY se llaman columnas de agrupacin o agrupamiento .
Cuando queremos realizar una agrupacin mltiple, por varias columnas, stas se indican en la clusula GROUP BY en el
orden de mayor a menor agrupacin igual que con la clusula ORDER BY.
expresion_agrupacion puede ser una columna o una expresin no agregada que haga referencia a una columna devuelta
por la clusula FROM. Un alias de columna que est definido en la lista de seleccin no puede utilizarse para especificar una
columna de agrupamiento.
No se pueden utilizar columnas de tipo text, ntext e image en expresion_agrupacion.
En las clusulas GROUP BY que no contengan CUBE o ROLLUP, el nmero de columnas de agrupacin est limitado por
los tamaos de columna de GROUP BY, las columnas de agregado y los valores de agregado que participan en la consulta.
Este lmite procede del lmite de 8.060 bytes de la tabla de trabajo intermedia que se necesita para contener los resultados
intermedios de la consulta. Se permite un mximo de 10 expresiones de agrupamiento cuando se especifica CUBE o
ROLLUP.
Si en la columna de agrupacin existen valores nulos, se generar una fila de resumen para este valor, en este caso se
considera el valor nulo como otro valor cualquiera.
Ejemplo:
SELECT oficina, count(numemp) AS [Nmero de empleados]
FROM empleados

114

GROUP BY oficina;
Resultado:
oficina Nmero de empleados
NULL

11

12

13

21

22

Hay empleados sin oficinas (con oficina a nulo), estos forman un grupo con el valor NULL en oficina, en este caso hay dos
empleados as.
Podemos indicar varias columnas de agrupacin.
Ejemplo:
SELECT rep, clie, count(numpedido) AS [Nmero de pedidos], MAX(importe) AS [Importe mximo]
FROM pedidos
WHERE YEAR(fechapedido) = 1997
GROUP BY rep, clie
ORDER BY rep, clie;
Resultado:

rep clie

Nmero

Importe

de pedidos mximo

101 2113 1

225,00

102 2106 2

21,30

102 2120 1

37,50

115

103 2111 2

21,00

105 2103 4

275,00

105 2111 1

37,45

106 2101 1

14,58

107 2109 1

313,50

107 2124 2

24,30

108 2112 1

29,25

108 2114 1

71,00

108 2118 3

14,20

De cada representante obtenemos el nmero de pedidos y el importe mximo vendido a cada cliente, de las ventas de 1997.
La clusula ORDER BY se ha incluido para que las filas aparezcan ordenadas y quede ms claro.
Hemos dicho que los resmenes se calculan sobre todas las filas del origen despus de haber ejecutado el WHERE, pues
ALL permite obtener un resumen de las filas que no cumplen el WHERE.
ALL Incluye todos los grupos y conjuntos de resultados, incluso aquellos en los que no hay filas que cumplan la condicin de
bsqueda especificada en la clusula WHERE. Cuando se especifica ALL, se devuelven valores NULL para las columnas de
resumen de los grupos que no cumplen la condicin de bsqueda. No se puede especificar ALL con los operadores CUBE y
ROLLUP.
GROUP BY ALL no se admite en consultas que tienen acceso a tablas remotas si tambin hay una clusula WHERE en la
consulta.
Por ejemplo, vamos a modificar la consulta anterior:
SELECT rep, clie, count(numpedido) AS [Nmero de pedidos], MAX(importe) AS [Importe mximo]
FROM pedidos
WHERE YEAR(fechapedido) = 1997
GROUP BY ALL rep, clie
ORDER BY rep, clie;
Resultado:
rep clie Nmero

Importe

116

de pedidos mximo
101 2102 0

NULL

101 2108 0

NULL

101 2113 1

225,00

102 2106 2

21,30

102 2120 1

37,50

103 2111 2

21,00

105 2103 4

275,00

105 2111 1

37,45

106 2101 1

14,58

106 2117 0

NULL

107 2109 1

313,50

107 2124 2

24,30

108 2112 1

29,25

108 2114 1

71,00

108 2118 3

14,20

Cul ha sido el efecto de aadir ALL? Se han aadido filas para las filas del origen que no cumplen la condicin del WHERE
pero sin que intervengan en el clculo de las funciones de agregado.
Por ejemplo el representante 101 tiene pedidos con el cliente 2102 pero estos pedidos no son del ao 1997, por eso aparece
la primera fila (no estaba en el resultado de la otra consulta) pero con 0 y NULL como resultados de las funciones de
agregado.
ROLLUP especifica que, adems de las filas que normalmente proporciona GROUP BY, se incluyen filas de resumen en el
conjunto de resultados. Los grupos se resumen en un orden jerrquico, desde el nivel inferior del grupo hasta el superior. La
jerarqua del grupo se determina por el orden en que se especifican las columnas de agrupamiento. Cambiar el orden de las
columnas de agrupamiento puede afectar al nmero de filas generadas en el conjunto de resultados.

117

Por ejemplo:
SELECT rep, clie, count(numpedido) AS [Nmero de pedidos], MAX(importe) AS [Importe mximo]
FROM pedidos
WHERE YEAR(fechapedido) = 1997
GROUP BY rep, clie WITH ROLLUP;
Resultado:
Nmero

Importe

rep

clie

101

2113 1

225,00

101

NULL 1

225,00

102

2106 1

21,30

102

2120 1

37,50

102

NULL 3

37,50

103

2111 2

21,00

103

NULL 2

21,00

105

2103 4

275,00

105

2111 1

37,45

105

NULL 5

275,00

106

2101 1

14,28

106

NULL 1

14,28

107

2109 1

313,50

107

2124 2

24,30

107

NULL 3

313,50

de pedidos mximo

118

108

2112 1

29,25

108

2114 1

71,00

108

2118 3

14,20

108

NULL 5

71,00

...

...

...

...

NULL NULL 23

450,00

Efecto: Se han aadido automticamente subtotales por cada nivel de agrupamiento y una lnea de totales generales al final.
En este caso no hemos incluido ORDER BY porque las filas salen ya ordenadas.
CUBE especifica que, adems de las filas que normalmente proporciona GROUP BY, deben incluirse filas de resumen en el
conjunto de resultados. Se devuelve una fila de resumen GROUP BY por cada posible combinacin de grupo y subgrupo del
conjunto de resultados. En el resultado se muestra una fila de resumen GROUP BY como NULL, pero se utiliza para indicar
todos los valores.
Por ejemplo:
SELECT rep, clie, count(numpedido) AS [Nmero de pedidos], MAX(importe) AS [Importe mximo]
FROM pedidos
WHERE YEAR(fechapedido) = 1997
GROUP BY rep, clie WITH CUBE;
Resultado:
Nmero

Importe

rep

clie

101

2113 1

225,00

101

NULL 1

225,00

102

2106 1

21,30

102

2120 1

37,50

102

NULL 3

37,50

de pedidos mximo

119

103

2111 2

21,00

103

NULL 2

21,00

105

2103 4

275,00

105

2111 1

37,45

105

NULL 5

275,00

106

2101 1

14,28

106

NULL 1

14,28

107

2109 1

313,50

107

2124 2

24,30

107

NULL 3

313,50

108

2112 1

29,25

108

2114 1

71,00

108

2118 3

14,20

108

NULL 5

71,00

...

...

...

...

NULL NULL 23

450,00

NULL 2101 1

14,58

NULL 2103 4

275,00

NULL 2106 2

21,30

NULL 2107 1

6,32

NULL 2108 1

56,25

120

NULL 2109 1

313,50

NULL 2111 3

37,45

NULL 2112 2

450,00

NULL 2113 1

225,00

NULL 2114 1

71,00

NULL 2118 3

14,20

NULL 2120 1

37,50

NULL 2124 2

24,30

Efecto: Obtenemos adems de los resultados obtenidos con ROLLUP (los totales por cada representante), los totales por el
otro criterio (los totales por cada cliente).
El nmero de filas de resumen del conjunto de resultados se determina mediante el nmero de columnas que contiene la
clusula GROUP BY. Cada operando (columna) de la clusula GROUP BY se enlaza segn el agrupamiento NULL y se
aplica el agrupamiento al resto de los operandos (columnas). CUBE devuelve todas las combinaciones posibles de grupo y
subgrupo.
Tanto si utilizamos CUBE como ROLLUP, nos ser til la funcin de agregado GROUPING.
Si cogemos por ejemplo la primera fila remarcada (101 NULL ) el valor NULL, no sabemos si se refiere a una fila de
subtotal o a que el representante 101 ha realizado un pedido sin nmero de cliente. Para poder salvar este problema se
utiliza la funcin de agregado GROUPING.
SELECT rep, clie, count(numpedido) AS [Nmero de pedidos], MAX(importe) AS [Importe mximo], GROUPING(clie) AS
[Fila resumen]
FROM pedidos
WHERE YEAR(fechapedido) = 1997
GROUP BY rep, clie WITH ROLLUP;

rep clie

Nmero

Importe Fila

de pedidos mximo Resumen

101 2113 1

225,00

101 NULL 1

225,00

121

102 2106 2

21,30

102 2120 1

37,50

102 NULL 3

37,50

103 2111 2

21,00

Las filas que corresponden a subtotales aparecen con un 1 y las normales con un cero.
Ahora que estamos ms familiarizados con las columnas de agrupamiento debemos comentar una regla a no olvidar:
EN LA LISTA DE SELECCIN DE UNA CONSULTA DE RESUMEN UN NOMBRE DE COLUMNA NO PUEDE APARECER
FUERA DE UNA FUNCIN DE AGREGADO SI NO ES UNA COLUMNA DE AGRUPACIN.
5.15. Seleccin sobre grupos de filas, la clusula HAVING
Cuando queremos incluir una clusula de seleccin sobre las filas del origen, utilizamos la clusula WHERE, pero cuando
estamos definiendo una consulta de resumen, no podemos utilizar esta clusula para seleccionar filas del resultado ya que
cada una de stas representa un grupo de filas de la tabla original. Para seleccionar filas del resumen tenemos la clusula
HAVING.

HAVING condicin de bsqueda


HAVING funciona igual que la clusula WHERE pero en vez de actuar sobre las filas del origen de datos, acta sobre las
filas del resultado, selecciona grupos de filas por lo que la condicin de bsqueda sufrir alguna limitacin, la misma que
para la lista de seleccin:
Ejemplo:
SELECT oficina, count(numemp) AS [Nmero de empleados]
FROM empleados
GROUP BY oficina
HAVING COUNT(numemp)<2;
Resultado:
oficina Nmero de empleados
13

22

122

Esta SELECT es la misma que la del primer ejemplo del apartado sobre la clusula GROUP BY, la diferencia es que le
hemos aadido la clusula HAVING, que hace que del resultado slo se visualicen los grupos que cumplan la condicin. Es
decir slo aparecen las oficinas que tienen menos de 2 empleados.
Siempre que en una condicin de seleccin haya una funcin de columna, la condicin deber incluirse en la clusula
HAVING, adems, como HAVING filtra filas del resultado, slo puede contener expresiones (nombres de columnas,
expresiones, funciones) que tambin pueden aparecer en la lista de seleccin, por lo que tambin se aplica la misma regla
a no olvidar:
EN LA CLUSULA HAVING UN NOMBRE DE COLUMNA NO PUEDE APARECER FUERA DE UNA FUNCIN DE
AGREGADO SI NO ES UNA COLUMNA DE AGRUPACIN.
Las expresiones que pongamos en HAVING no tienen porqu aparecer en la lista de seleccin, por ejemplo en la SELECT
anterior se poda haber escrito:
HAVING SUM(ventas)=10000

Unidad 6. Las subconsultas (I)


6.1. Introduccin
Una subconsulta es una consulta que aparece dentro de otra consulta o subconsultas, en la lista de seleccin o en la
clusula WHERE o HAVING, originalmente no se podan incluir en la lista de seleccin.
Una subconsulta se denomina tambin consulta o seleccin interna, mientras que la instruccin que contiene la subconsulta
es conocida como consulta o seleccin externa.
Aparece siempre encerrada entre parntesis y tiene la misma sintaxis que una sentencia SELECT normal con alguna
limitacin:
No puede incluir una clusula COMPUTE o FOR BROWSE y slo puede incluir una clusula ORDER BY cuando se
especifica tambin una clusula TOP.
Una subconsulta puede anidarse en la clusula WHERE o HAVING de una instruccin externa SELECT, INSERT, UPDATE
o DELETE, o bien en otra subconsulta. Se puede disponer de hasta 32 niveles de anidamiento, aunque el lmite vara
dependiendo de la memoria disponible y de la complejidad del resto de las expresiones de la consulta. Hay que tener en
cuenta que para cada fila de la consulta externa, se calcula la subconsulta, si anidamos varias consultas, el nmero de
veces que se ejecutarn las subconsultas puede dispararse!
Cuando la subconsulta aparece en la lista de seleccin de otra consulta, deber devolver un solo valor, de lo contrario
provocar un error.
Ejemplo de subconsulta: Listar los empleados cuya cuota no supere el importe vendido por el empleado.
SELECT nombre
FROM empleados
WHERE cuota <= (SELECT SUM(importe)
FROM pedidos

WHERE rep = numemp);

123

Por cada fila de la tabla de empleados (de la consulta externa) se calcula la subconsulta y se evala la condicin, por lo que
utilizar una subconsulta puede en algunos casos ralentizar la consulta, en contrapartida se necesita menos memoria que
una composicin de tablas.
Muchas de las instrucciones Transact-SQL que incluyen subconsultas se pueden formular tambin utilizando composiciones
de tablas. Otras preguntas se pueden formular slo con subconsultas.
En Transact-SQL, normalmente no hay una regla fija en cuanto a diferencias de rendimiento entre una instruccin que
incluya una subconsulta y una versin semnticamente equivalente que no la incluya.
Podremos utilizar una subconsulta siempre y cuando no se quiera que aparezcan en el resultado columnas de la
subconsulta ya que si una tabla aparece en la subconsulta y no en la consulta externa, las columnas de esa tabla no se
pueden incluir en la salida (la lista de seleccin de la consulta externa).
Tenemos tres tipos de subconsultas:

Las que devuelven un solo valor, aparecen en la lista de seleccin de la consulta externa o con un operador de
comparacin sin modificar.

Las que generan una columna de valores, aparecen con el operador IN o con un operador de comparacin
modificado con ANY, SOME o ALL.

Las que pueden generar cualquier nmero de columnas y filas, son utilizadas en pruebas de existencia
especificadas con EXISTS.

A lo largo del tema las estudiaremos todas.


Antes de terminar con la introduccin queda comentar el concepto de referencia externa muy til en las subconsultas.
A menudo, es necesario, dentro del cuerpo de una subconsulta, hacer referencia al valor de una columna en la fila actual de
la consulta externa, el nombre de columna de la consulta externa dentro de la subconsulta recibe el nombre de referencia
externa, ya que hace referencia a una columna externa.
En el ejemplo anterior numemp es una referencia externa, no es una columna del origen de datos de la subconsulta
(pedidos), es una columna del origen de la consulta externa (empleados).
Hay que tener en cuenta de cmo se ejecuta la consulta; por cada fila de la consulta externa se calcula el resultado de la
subconsulta y se evala la comparacin.
En el ejemplo, se coge el primer empleado (numemp= 101, por ejemplo) y se calcula la subconsulta sustituyendo numemp
por el valor 101, se calcula la suma de los pedidos del rep = 101, y el resultado se compara con la cuota de ese empleado, y
as se repite el proceso con todas las filas de empleados.
El nombre de una columna dentro de la subconsulta se presupone del origen de datos de la subconsulta y, slo si no se
encuentra en ese origen, la considera como columna externa y la busca en el origen de la consulta externa.
Por ejemplo:
SELECT oficina, ciudad
FROM oficinas

124

WHERE objetivo > (SELECT SUM(ventas)


FROM empleados
WHERE oficina = oficina);
La columna oficina se encuentra en los dos orgenes (oficinas y empleados) pero esta consulta no dar error (no se nos
pedir cualificar los nombres como pasara en una composicin de tablas), dentro de la subconsulta se considera oficina el
campo de la tabla empleados. Con lo que comparara la oficina del empleado con la misma oficina del empleado y eso no es
lo que queremos, queremos comparar la oficina del empleado con la oficina de oficinas, lo escribiremos pues as para forzar
a que busque la columna en la tabla oficinas.
SELECT oficina, ciudad
FROM oficinas
WHERE objetivo > (SELECT SUM(ventas)
FROM empleados
WHERE oficina = oficinas.oficina);
6.2. Subconsultas de resultado nico
Existen subconsultas que deben obligatoriamente devolver un nico valor, son las que aparecen en la lista de seleccin de
la consulta externa o las que aparecen en WHERE o HAVING combinadas con un operador de comparacin sin modificar.
Los operadores de comparacin sin modificar son los operadores de comparacin que vimos con la clusula WHERE.
Sintaxis:
<expresion> {=|<>|!=|>|>=|!>|<|<=|!<} <subconsulta>
En este caso la segunda expresin ser una subconsulta, con una sola columna en la lista de seleccin y deber devolver
una nica fila como mucho.
Ese valor nico ser el que se compare con el resultado de la primera expresin.
Si la subconsulta no devuelve ninguna fila, la comparacin opera como si la segunda expresin fuese nula.
Si la subconsulta devuelve ms de una fila o ms de una columna, da error.
Ejemplo:
SELECT nombre
FROM empleados
WHERE cuota <= (SELECT SUM(importe)

FROM pedidos
WHERE rep = numemp);

125

La subconsulta devuelve una sola columna y como mucho una fila ya que es una consulta de resumen sin clusula GROUP
BY.

6.3. Subconsultas de lista de valores


Otro tipo de subconsultas son las que devuelven una lista de valores en forma de una columna y cero, una o varias filas.
Estas consultas aparecen en las clusulas WHERE o HAVING combinadas con el operador IN o con comparaciones
modificadas.

6.4. El operador IN con subconsulta


<expresion> IN subconsulta
IN examina si el valor de expresion es uno de los valores incluidos en la lista de valores generados por la subconsulta.
La subconsulta tiene que generar valores de un tipo compatible con la expresin.
Ejemplo:
SELECT * FROM empleados WHERE oficina IN (SELECT oficina FROM oficinas WHERE region = 'Este');
Por cada empleado se calcula la lista de las oficinas del Este (n de oficina) y se evala si la oficina del empleado est en
esta lista. Obtenemos pues los empleados de oficinas del Este.
numemp nombre

edad oficina titulo

101

Antonio Viguer

45

12

representante 1986-10-20 104

30000,00 30500,00

103

Juan Rovira

29

23

representante 1987-03-01 104

27500,00 28600,00

104

Jos Gonzlez

33

23

dir ventas

1987-05-19 106

20000,00 14300,00

105

Vicente Pantalla 37

13

representante 1988-02-12 104

35000,00 36800,00

106

Luis Antonio

11

dir general

52

contrato

jefe

cuota

ventas

1988-06-14 NULL 27500,00 29900,00

Si la subconsulta no devuelve ninguna fila:


SELECT * FROM empleados WHERE oficina IN (SELECT oficina FROM oficinas WHERE region = 'Otro');
La lista generada est vaca por lo que la condicin IN devuelve FALSE y en este caso no sale ningn empleado.
Muchas veces la misma pregunta se puede resolver mediante una composicin de tablas.

SELECT empleados.* FROM Empleados INNER JOIN oficinas ON empleados.oficina = oficinas.oficina WHERE region =
'Este';

126

Esta sentencia es equivalente. En el resultado no queremos ver ninguna columna de la tabla oficinas, el JOIN lo tenemos
slo para la pregunta, en este caso pues se puede sustituir por una subconsulta.
Si combinamos el operador IN con NOT obtenemos el operador NOT IN.
<expresion> NOT IN subconsulta
Devuelve TRUE si el valor de la expresin no est en la lista de valores devueltos por la subconsulta.
SELECT * FROM empleados WHERE oficina NOT IN (SELECT oficina FROM oficinas WHERE region = 'Este');
Devuelve los empleados cuya oficina no est en la lista generada por la subconsulta, es decir empleados que trabajan en
oficinas que no son del Este.
OJO con NOT IN.
Hay que tener especial cuidado con los valores nulos cuando utilizamos el operador NOT IN porque el resultado obtenido no
siempre ser el deseado por ejemplo:
* En la consulta anterior no salen los empleados que no tienen oficina ya que para esos empleados la columna oficina
contiene NULL por lo que no se cumple el NOT IN.
* Si la subconsulta no devuelve ninguna fila, la condicin se cumplir para todas las filas de la consulta externa, en este caso
todos los empleados.
* Si la subconsulta devuelve algn valor NULL, la condicin NOT IN es NULL lo que nos puede ocasionar algn problema.
Por ejemplo, queremos obtener las oficinas que no estn asignadas a ningn empleado.
SELECT *

FROM Oficinas

WHERE oficina NOT IN (SELECT oficina

FROM empleados);
Esta consulta no devuelve ninguna fila cuando s debera ya que hay oficinas que nos estn asignadas a ningn empleado.
El problema est en que la columna oficina de la tabla empleados admite nulos por lo que la subconsulta devuelve valores
nulos en todos los empleados que no estn asignados a ninguna oficina. Estos valores nulos hacen que no se cumpla el
NOT IN. La solucin pasa por eliminar estos valores molestos:
SELECT *

FROM Oficinas

127

WHERE oficina NOT IN (SELECT oficina

FROM empleados

WHERE oficina IS NOT NULL);


En el primer ejemplo no tenemos ese problema porque la columna oficina en oficinas no admite nulos.
A diferencia de IN, NOT IN no siempre puede resolverse con una composicin:
SELECT numemp AS [IN]

FROM empleados

WHERE numemp IN (SELECT rep

FROM pedidos

WHERE fab = 'ACI');


Se puede resolver con una composicin:

SELECT DISTINCT empleados.numemp AS [=]

FROM Empleados INNER JOIN pedidos ON numemp = rep

WHERE fab = 'ACI';


En este caso, como un empleado puede tener varios pedidos hay que aadir DISTINCT para eliminar las repeticiones de
empleados (si un empleado tiene varios pedidos de ACI aparecera varias veces).
Sin embargo esta sentencia con NOT IN, queremos los empleados que no tienen pedidos de ACI:
SELECT numemp AS [NOT IN]

FROM empleados

128

WHERE numemp NOT IN (SELECT rep

FROM pedidos

WHERE fab = 'ACI');


No se puede resolver con una composicin:
SELECT DISTINCT empleados.numemp AS [<>]

FROM Empleados INNER JOIN pedidos ON numemp = rep

WHERE fab <> 'ACI';


Esta consulta devuelve los empleados que tienen pedidos que no son de ACI, pero un empleado puede tener pedidos de
ACI y otros de otros fabricantes y por estos otros saldra en el resultado cuando s tiene pedidos de ACI y no debera salir.
Hay que tener mucho cuidado con este tipo de preguntas.
6.5. La comparacin modificada (ANY, ALL)
Los operadores de comparacin que presentan una subconsulta se pueden modificar mediante las palabras clave ALL, ANY
o SOME. SOME es un equivalente del estndar de SQL-92 de ANY.
Se utiliza este tipo de comparacin cuando queremos comparar el resultado de la expresin con una lista de valores y actuar
en funcin del modificador empleado.
El test ANY
<expresion> {=|<>|!=|>|>=|!>|<|<=|!<} {ANY|SOME} subconsulta
ANY significa que, para que una fila de la consulta externa satisfaga la condicin especificada, la comparacin se debe
cumplir para al menos un valor de los devueltos por la subconsulta.
Por cada fila de la consulta externa se evala la comparacin con cada uno de los valores devueltos por la subconsulta y si
la comparacin es True para alguno de los valores ANY es verdadero, si la comparacin no se cumple con ninguno de los
valores de la consulta, ANY da False a no ser que todos los valores devueltos por la subconsulta sean nulos en tal caso
ANY

dar

NULL.

Si la subconsulta no devuelve filas ANY da False incluso si expresion es nula.


Ejemplo:
SELECT *

FROM empleados

129

WHERE cuota > ANY (SELECT cuota

FROM empleados empleados2

WHERE empleados.oficina = empleados2.oficina);


Obtenemos los empleados que tienen una cuota superior a la cuota de alguno de sus compaeros de oficina, es decir los
empleados que no tengan la menor cuota de su oficina.
En este caso hemos tenido un alias de tabla en la subconsulta (empleados2) para poder utilizar una referencia externa.
Para practicar puedes realizar este Ejercicio Comparacin modificada ANY.
El test ALL

<expresion> {=|<>|!=|>|>=|!>|<|<=|!<} ALL subconsulta

Con el modificador ALL, para que se cumpla la condicin, la comparacin se debe cumplir con cada uno de los valores
devueltos

por

la

subconsulta.

Si la subconsulta no devuelve ninguna fila ALL da True.


SELECT *

FROM empleados

WHERE cuota > ALL (SELECT cuota

FROM empleados empleados2

WHERE empleados.oficina = empleados2.oficina);


En el ejemplo anterior obtenemos los empleados que tengan una cuota superior a todas las cuotas de la oficina del
empleado. Podramos pensar que obtenemos el empleado de mayor cuota de su oficina pero no lo es, aqu tenemos un
problema, la cuota del empleado aparece en el resultado de subconsulta por lo tanto > no se cumplir para todos los valores
y slo saldrn los empleados que no tengan oficina (para los que la subconsulta no devuelve filas).
Para salvar el problema tendramos que quitar del resultado de la subconsulta la cuota del empleado modificando el
WHERE:

130

WHERE empleados.oficina = empleados2.oficina

AND empleados.numemp <> empleados2.numemp);


De esta forma saldran los empleados que tienen una cuota mayor que cualquier otro empleado de su misma oficina.
O bien
WHERE empleados.oficina = empleados2.oficina

AND empleados.cuota <> empleados2.cuota);


Para no considerar los empleados que tengan la misma cuota que el empleado. En este caso saldran los empleados con la
mayor cuota de sus oficina, pero si dos empleados tienen la misma cuota superior, saldran, hecho que no sucedera con la
otra versin.
Cuando la comparacin es una igualdad, = ANY es equivalente a IN y <> ALL es equivalente a NOT IN (con los mismos
problemas).
6.6. Subconsultas con cualquier nmero de columnas (EXISTS)
Existe otro operador de subconsulta con el que la subconsulta puede devolver ms de una columna, el operador EXISTS.
En este caso la sintaxis es algo diferente:
WHERE [NOT] EXISTS subconsulta
No se realiza ninguna comparacin con los valores devueltos por la subconsulta, simplemente se evala si la subconsulta
devuelve alguna fila, en este caso EXISTS ser True y si la subconsulta no devuelve ninguna fila, EXISTS ser False.
Ejemplo:
SELECT *

FROM empleados

WHERE EXISTS (SELECT *

FROM pedidos

WHERE numemp = rep and fab ='ACI');

131

Obtenemos los empleados que tengan un pedido del fabricante ACI. Por cada empleado, se calcula la subconsulta
(obteniendo los pedidos de ese empleado y con fabricante ACI), si existe alguna fila, el empleado sale en el resultado, si no,
no sale.
Cuando se utiliza el operador EXISTS es muy importante aadir una referencia externa, no es obligatorio pero en la mayora
de los casos ser necesario. Vemoslo con ese mismo ejemplo, si quitamos la referencia externa:
SELECT *

FROM empleados

WHERE EXISTS (SELECT *

FROM pedidos

WHERE fab ='ACI');


Sea el empleado que sea, la subconsulta siempre devolver filas (si existe algn pedido cuyo fabricante sea ACI) o nunca,
indistintamente del empleado que sea, por lo que se obtendrn todos los empleados o ninguno para que el resultado vare
segn las filas de la consulta externa habr que incluir una referencia externa.
Otra cosa a tener en cuenta es que la lista de seleccin de una subconsulta que se especifica con EXISTS casi siempre
consta de un asterisco (*). No hay razn para enumerar los nombres de las columnas porque no se van a utilizar y supone
un trabajo extra para el sistema.
Si utilizamos NOT EXISTS el resultado ser el contrario.
SELECT *

FROM empleados

WHERE NOT EXISTS (SELECT *

FROM pedidos

WHERE fab ='ACI' AND rep=numemp);


Devuelve los empleados que no tienen ningn pedido de ACI.

132

Unidad 7. Actualizacin de datos (I)


7.1. Introduccin
Hasta ahora hemos trabajado con tablas que tenan datos introducidos y cuando nos ha hecho falta hemos aadido nuevos
datos en las mismas y hemos modificado algn dato directamente desde el entorno de SSMS, en este tema veremos cmo
hacerlo

con

instrucciones

de

Transact-SQL.

Seguimos en el DML porque las instrucciones que veremos actan sobre los datos de la base de datos no sobre su
definicin y tenemos tres tipos de operaciones posibles:

Insertar nuevas filas en una tabla.

Modificar datos ya almacenados.

Eliminar filas de una tabla.

7.2. Insertar creando una nueva tabla


Una forma de insertar datos es crear una tabla que incluya los datos de otra. Esta es la sentencia SELECT... INTO.

SELECT ...

INTO nb_NuevaTabla

FROM ...

nb_NuevaTabla es el nombre de la tabla que se va a crear, si en la base de datos ya hay una tabla con ese nombre, el
sistema genera un error y no se ejecuta la sentencia.
En la nueva tabla las columnas tendrn el mismo tipo y tamao que las columnas del resultado de la SELECT, se llamarn
con el nombre de alias de la columna o en su defecto con el nombre de la columna, pero no se transfiere ninguna otra
propiedad del campo o de la tabla como por ejemplo las claves e ndices.
Si retomamos el ejemplo del punto anterior:

CREATE TABLE trabajo (col1 INT, col2 VARCHAR(20), col3 MONEY);

INSERT INTO trabajo SELECT oficina, ciudad, ventas

FROM oficinas

133

WHERE region = 'Centro';


Se podra obtener el mismo resultado con una sola instruccin:

SELECT oficina AS col1, ciudad AS col2, ventas AS col3

INTO trabajo

FROM oficinas

WHERE region = 'Centro'


Si se tiene poca experiencia en esta instruccin, lo mejor es primero escribir la SELECT que permite obtener las filas a
insertar y una vez la tenemos aadir la clusula INTO destino delante de FROM.
Para practicar puedes realizar este Ejercicio Insertar datos creando una nueva tabla.
7.3. 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).

De la sentencia INSERT completa, nosotros estudiaremos la sintaxis ms utilizada y estndar:

INSERT [INTO] <destino>

[(lista_columnas)]

{VALUES ({DEFAULT|NULL|expresion}[ ,...n ])

|tabla_derivada

134

|DEFAULT VALUES

[;]

<destino> ::=

[nbBaseDatos.nbEsquema. | nbEsquema.]nbTablaVista

}
Con esta instruccin podemos insertar una fila de valores determinados o un conjunto de filas derivadas de otra consulta.
7.1. Introduccin
Hasta ahora hemos trabajado con tablas que tenan datos introducidos y cuando nos ha hecho falta hemos aadido nuevos
datos en las mismas y hemos modificado algn dato directamente desde el entorno de SSMS, en este tema veremos cmo
hacerlo

con

instrucciones

de

Transact-SQL.

Seguimos en el DML porque las instrucciones que veremos actan sobre los datos de la base de datos no sobre su
definicin y tenemos tres tipos de operaciones posibles:

Insertar nuevas filas en una tabla.

Modificar datos ya almacenados.

Eliminar filas de una tabla.

7.2. Insertar creando una nueva tabla


Una forma de insertar datos es crear una tabla que incluya los datos de otra. Esta es la sentencia SELECT... INTO.

SELECT ...

INTO nb_NuevaTabla

135

FROM ...

nb_NuevaTabla es el nombre de la tabla que se va a crear, si en la base de datos ya hay una tabla con ese nombre, el
sistema genera un error y no se ejecuta la sentencia.
En la nueva tabla las columnas tendrn el mismo tipo y tamao que las columnas del resultado de la SELECT, se llamarn
con el nombre de alias de la columna o en su defecto con el nombre de la columna, pero no se transfiere ninguna otra
propiedad del campo o de la tabla como por ejemplo las claves e ndices.
Si retomamos el ejemplo del punto anterior:

CREATE TABLE trabajo (col1 INT, col2 VARCHAR(20), col3 MONEY);

INSERT INTO trabajo SELECT oficina, ciudad, ventas

FROM oficinas

WHERE region = 'Centro';


Se podra obtener el mismo resultado con una sola instruccin:

SELECT oficina AS col1, ciudad AS col2, ventas AS col3

INTO trabajo

FROM oficinas

WHERE region = 'Centro'


Si se tiene poca experiencia en esta instruccin, lo mejor es primero escribir la SELECT que permite obtener las filas a
insertar y una vez la tenemos aadir la clusula INTO destino delante de FROM.
Para practicar puedes realizar este Ejercicio Insertar datos creando una nueva tabla.
7.3. Insertar en una tabla existente INSERT INTO

136

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).

De la sentencia INSERT completa, nosotros estudiaremos la sintaxis ms utilizada y estndar:

INSERT [INTO] <destino>

[(lista_columnas)]

{VALUES ({DEFAULT|NULL|expresion}[ ,...n ])

|tabla_derivada

|DEFAULT VALUES

[;]

<destino> ::=

[nbBaseDatos.nbEsquema. | nbEsquema.]nbTablaVista

137

Con esta instruccin podemos insertar una fila de valores determinados o un conjunto de filas derivadas de otra consulta.
7.4. Insertar una fila de valores
Para insertar una fila de valores utilizamos la sintaxis:

INSERT [INTO] <destino> [(lista_columnas)]

VALUES ({DEFAULT|NULL|expresion}[ ,...n ]) [;]


La palabra reservada INTO es opcional y no aade funcionalidad a la instruccin, originalmente era obligatoria.
Despus

de

indicar

que

queremos

insertar,

debemos

indicar

dnde,

mediante

<destino>.

<destino> es el nombre de la tabla donde queremos insertar, puede ser un nombre de tabla o un nombre de vista.
Si utilizamos una vista, y sta tiene un origen basado en varias tablas, en su lista de seleccin debern aparecer columnas
de

una

Con

la

sola
clusula

tabla
VALUES

(no

podemos

indicamos

entre

insertar
parntesis

datos
los

en

valores

varias
a

insertar,

tablas

la

vez).

separados

por

comas.

Cada valor se puede indicar mediante:

una expresin que normalmente ser una constante,

mediante la palabra reservada DEFAULT que indica valor por defecto en este caso la columna se rellenar con el
valor predeterminado de la columna, si la columna no tiene DEFAULT se sustituir por el valor nulo NULL.

Mediante la palabra reservada NULL valor nulo.

Delante de VALUES, de forma opcional podemos indicar una lista de columnas entre parntesis. Las columnas son
columnas

del

destino.

Cuando indicamos nombres de columnas, esas columnas sern las que reciban los valores a insertar, la asignacin de
valores se realiza por posicin, la primera columna recibe el primer valor, la segunda columna el segundo, y as
sucesivamente.
En la lista, las columnas pueden estar en cualquier orden y tambin se pueden omitir algunas columnas.
Una columna que no aparezca en la lista de columnas se rellenar de acuerdo a su definicin:

con su valor por defecto si est definida con la clusula DEFAULT

con el valor de identidad incremental siguiente si tiene la propiedad IDENTITY.

con el valor calculado si es una columna calculada.

con el valor NULL , en cualquier otro caso y si la columna lo admite.

Cuando no se indica una lista de columnas el sistema asume por defecto todas las columnas de la tabla y en el mismo orden
que aparecen en la definicin de la tabla, en este caso, los valores se tienen que especificar en el mismo orden que las
columnas en la definicin de la tabla, y se tiene que especificar un valor por cada columna ya que los valores se rellenan por
posicin, la primera columna recibe el primer valor, la segunda columna el segundo, y as sucesivamente.

138

En cualquier caso, el nmero de valores debe coincidir con el nmero de columnas y los tipos de dato de los valores deben
ser compatibles con las columnas.
Aunque pueda parecer ms engorroso escribir la lista de columnas, es un hbito recomendable, hace que la sentencia sea
ms fcil de leer y mantener (cuando leemos la sentencia sabemos en qu columnas asignamos los valores sin necesidad
de consultar la definicin de la tabla) y evita que se tenga que cambiar la sentencia si se modifica el esquema de la tabla (si
el orden de las columnas dentro de la tabla cambia).
Los registros se agregan al final de la tabla.
Cuando se insertan nuevas filas en una tabla, el sistema comprobar que la nueva fila no infrinja ninguna regla de
integridad, por ejemplo no podremos asignar a una columna PRIMARY KEY un valor nulo o que ya exista en la tabla, a una
columna UNIQUE un valor que ya exista en la tabla, a una columna NOT NULL un valor NULL, a una clave ajena (FOREIGN
KEY)

un

valor

que

no

exista

en

la

tabla

de

referencia.

De producirse alguna de las situaciones anterior, la instruccin genera un mensaje de error y la fila no se inserta.
Ejemplos.

INSERT INTO oficinas (oficina, ciudad) VALUES (26, 'Elx');

En este caso hemos indicado slo dos columnas y dos valores, las dems columnas se rellenan con el valor por defecto si lo
tiene (DEFAULT) o con NULL. Si alguna columna no nombrada no admite nulos ni tiene clusula DEFAULT definida, la
instruccin dar error.

INSERT INTO oficinas

VALUES (27,'Mstoles','Centro',default ,null, default)


Aqu no hemos indicado una lista de columnas luego los valores se tienen que indicar en el mismo orden que las columnas
dentro de la tabla, si nos equivocamos de orden, el valor se guardar en una columna errnea (si los tipos son compatibles)
o generar un mensaje de error y la fila no se insertar (si los tipos no son compatibles).
7.5. Insercin de varias filas
Si los valores que queremos insertar los tenemos en otras tablas, podemos insertar varias filas a la vez indicando una
consulta que genere las filas de valores a insertar. En este caso utilizamos la sintaxis:

INSERT [INTO] <destino> [(lista_columnas)]

tabla_derivada [;]

139

<destino> y lista_columnas funcionan igual que en el punto anterior.


Tabla_derivada es cualquier instruccin SELECT vlida que devuelva filas con los datos que se van a cargar en el destino.
Cada fila devuelta por la SELECT es una lista de valores que se intentar insertar como con la clusula VALUES, por lo que
las columnas devueltas por la SELECT debern cumplir las mismas reglas que los valores de la lista de valores anteriores.
Ejemplo:

CREATE TABLE trabajo (col1 INT, col2 VARCHAR(20), col3 MONEY);


Creamos una tabla trabajo de 3 columnas

INSERT INTO trabajo SELECT oficina, ciudad, ventas

FROM oficinas

WHERE region = 'Centro';


Insertamos en trabajo el resultado de la SELECT (el nmero de oficina, ciudad y ventas de las oficinas del Centro).
En este caso no hemos incluido una lista de columnas, por lo que en la SELECT tenemos que generar los valores en el
mismo orden que en trabajo.
Si hubiesemos escrito:

INSERT INTO trabajo SELECT ciudad, oficina, ventas

FROM oficinas

WHERE region = 'Centro';


Hubiese dado error porque la columna col1 es INT y el valor a asignar es texto (el nombre de la ciudad de la oficina).

INSERT INTO trabajo (col2, col1)

SELECT ciudad, oficina

FROM oficinas

140

WHERE region = 'Este';


En este caso hemos incluido una lista de columnas, la SELECT debe generar los valores correspondientes, y col3 que no se
rellena explcitamente se rellenar con NULL porque la columna col3 no est definida como columna calculada, ni con
DEFAULT, ni IDENTITY y adems admite nulos.
7.6. Insertar una fila de valores por defecto
TRANSACT-SQL nos permite insertar una fila de valores por defecto utilizando la sintaxis:

INSERT [INTO] <destino> DEFAULT VALUES

[;]
Hace

que

la

Hay

que

Puede

generar

nueva

tener
filas

fila
en

contenga
cuenta

duplicadas

en

los
una

la

tabla

valores
serie
si

los

predeterminados
de

aspectos

valores

que

se

definidos
al
generan

para

utilizar
son

cada
esta

siempre

columna.
instruccin:

los

mismos.

Si la tabla tiene una clave principal, esta tendr que estar basada en una columna con la propiedad IDENTITY para que se
generen

valores

diferentes

automticamente.

Si una columna est definida como NOT NULL tendr que incluir un DEFAULT o ser una columna calculada con una
expresin compatible.
7.7. Modificar datos almacenados - 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 ]

141

[ FROM{ <origen> }]

[ WHERE <condicion> ]

[;]

<destino> ::=

[nbBaseDatos.[nbEsquema.]| nbEsquema.]nbTablaVista

Con

<destino>

indicamos

la

tabla

que

se

va

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 subconsulta siempre y cuanto devuelva un nico valor y cumpla las condiciones
anteriormente expuestas.
Por ejemplo:

UPDATE oficinas SET ventas = 0;

Actualiza

todas

las

filas

de

la

tabla

oficinas

dejando

el

campo

ventas

con

el

valor

cero.

Si el campo ventas est definido con un valor predeterminado 0, la sentencia anterior equivale a:

UPDATE oficinas SET ventas = DEFAULT;


Si lo que queremos es dejar el campo a nulo:

142

UPDATE oficinas SET ventas = NULL;

En una misma sentencia podemos actualizar varias columnas, slo tenemos que indicar las distintas asignaciones
separadas por comas:

UPDATE oficinas SET ventas = 0, objetivo = 0;

Los nombres de columna pueden especificarse en cualquier orden.


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 ( expresion ) [ PERCENT ]

Especifica

el

nmero

porcentaje

de

filas

aleatorias

que

se

van

modificar.

expression debe generar un valor numrico e indica el nmero de filas a modificar empezando por el principio. Como en la
SELECT, si aadimos la palabra PERCENT, el nmero representado por expresin se refiere al porcentaje de filas a
modificar sobre el total. La clusula TOP funciona casi igual que en la SELECT pero en este caso, las filas no se ordenan, y
la expresin debe ir entre parntesis.
Por ejemplo:

UPDATE TOP (10) PERCENT oficinas

SET ventas = 0;
Actualiza el 10% de filas de la tabla oficinas.

[ WHERE <condicion> ]
Utilizamos la clusula WHERE para filtrar las filas a actualizar. Se actualizarn todas las filas que cumplan la condicin. Por
ejemplo si queremos actualizar slo las oficinas del Este:

UPDATE oficinas

143

SET ventas = 0

WHERE region = 'Este';


Cuando para la condicin de la clusula WHERE necesitamos un dato de otra tabla podemos utilizar una subconsulta:

UPDATE empleados SET ventas = 0

WHERE oficina IN (SELECT oficina

FROM oficinas

WHERE region = 'Este');


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;


Modificamos la tabla pedidos dejando en la columna importe el resultado de multiplicar la cantidad del pedido por el precio
del producto que se encuentra en la tabla productos.
Si la actualizacin de una fila infringe una restriccin o una regla, infringe la configuracin de valores NULL de la columna o
si el nuevo valor es de un tipo de datos incompatible con la columna, se cancela la instruccin, se devuelve un error y no se
actualiza

ningn

registro.

Cuando una instruccin UPDATE encuentra un error aritmtico (error de desbordamiento, divisin por cero o de dominio)
durante la evaluacin de la expresin, la actualizacin no se lleva a cabo. El resto del lote no se ejecuta y se devuelve un
mensaje de error.
Adems del permiso de UPDATE, se requieren permisos SELECT para la tabla que se actualiza si la instruccin UPDATE
contiene una clusula WHERE o en el caso de que el argumento expression de la clusula SET utilice una columna de la
tabla, y permisos SELECT para la tabla del origen si utilizamos una clusula FROM o un WHERE con subconsulta.

144

7.8. Eliminar filas - 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:

DELETE oficinas;

145

Equivalente a:

DELETE FROM oficinas;


Con esta instruccin eliminamos todas las filas de la tabla oficinas.
La clusula WHERE permite eliminar determinadas filas, indica una condicin que deben cumplir las filas que se eliminan.
Por ejemplo:

DELETE oficinas

WHERE region = Este;

Elimina las oficinas del Este.

TOP ( expresion ) [ PERCENT ]


Especifica

el

nmero

porcentaje

de

filas

aleatorias

que

se

van

eliminar.

expression debe generar un valor numrico e indica el nmero de filas a eliminar empezando por el principio. Como en la
SELECT, si aadimos la palabra PERCENT, el nmero representado por expresin se refiere al porcentaje de filas a eliminar
sobre el total. La clusula TOP funciona casi igual que en la SELECT pero en este caso, las filas no se ordenan, y la
expresin debe ir entre parntesis.
Por ejemplo:

DELETE TOP (10) PERCENT

FROM oficinas;
Elimina el 10% de filas de la tabla oficinas.
Originalmente slo se poda indicar una tabla en la clusula FROM, pero ahora podemos indicar un origen basado en varias
tablas.
Si utilizamos un origen basado en varias tablas, se debe de utilizar una extensin de TRANSACT-SQL que consiste en
escribir dos clusulas FROM, una indica la tabla de donde eliminamos las filas y la otra el origen que utilizamos para
eliminar.
Este caso se produce cuando las filas a eliminar dependen de un valor que est en otra tabla. Por ejemplo queremos
eliminar los empleados de las oficinas del Este. Como la regin de la oficina no est en empleados, habra que aadir al
origen la tabla oficinas para poder formular la condicin del WHERE:

146

DELETE FROM empleados

FROM empleados INNER JOIN oficinas

ON empleados.oficina = oficinas.oficina

WHERE region = 'Este';


En el origen tenemos las dos tablas y en la primera FROM indicamos de qu tabla queremos borrar.
Esto se poda haber resuelto, como toda la vida, mediante una subconsulta:

DELETE FROM empleados

WHERE oficina IN (SELECT oficina

FROM oficinas

WHERE region = 'Este');


Para finalizar no debemos olvidar que para poder ejecutar un DELETE se requieren permisos DELETE en la tabla de donde
vamos a eliminar, y tambin se requieren los permisos para utilizar SELECT si la instruccin contiene una clusula WHERE.
Muy importante siempre que actualicemos datos en nuestras tablas, no debemos olvidar tampoco las reglas de integridad
referencial. Si la tabla afectada interviene como tabla principal en una relacin con otra tabla, no se podrn eliminar sus filas
que estn relacionadas con registros de la otra tabla (no se pueden eliminar padres que tengan hijos ). Si se van a
eliminar varias filas y al menos una no se puede eliminar por infringir las reglas de integridad, entonces la operacin
abortar y no se eliminar ninguna fila.
En el ejemplo anterior, si un empleado asignado a una oficina del Este tiene pedidos, no se podr eliminar y entonces no se
eliminar ningn empleado.
7.9. Borrado masivo - TRUNCATE
Si queremos eliminar todas las filas de una tabla podemos utilizar tambin la instruccin TRUNCATE TABLE.

TRUNCATE TABLE

147

[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.

Unidad 8. El DDL, Lenguaje de Definicin de Datos (I)


8.1. Introduccin
El DDL (Data Definition Language, o Data Description Language segn autores), es la parte del SQL dedicada a la definicin
de la base de datos, consta de sentencias para definir la estructura de la base de datos, permite definir gran parte del nivel
interno de la base de datos. Por este motivo estas sentencias sern utilizadas normalmente por el administrador de la base
de

datos.

La definicin de la estructura de la base de datos incluye tanto la creacin inicial de los diferentes objetos que formarn la
base de datos, como el mantenimiento de esa estructura. Las sentencias del DDL utilizan unos verbos que se repiten para
los distintos objetos. Por ejemplo para crear un objeto nuevo el verbo ser CREATE y a continuacin el tipo de objeto a
crear. CREATE DATABASE es la sentencia para crear una base de datos, CREATE TABLE nos permite crear una nueva

148

tabla, CREATE INDEX crear un nuevo ndice Para eliminar un objeto utilizaremos el verbo DROP (DROP TABLE, DROP
INDEX) y para modificar algo de la definicin de un objeto ya creado utilizamos el verbo ALTER (ALTER TABLE, ALTER
INDEX).
Los objetos que veremos en este tema son:

Bases de datos

Tablas

Vistas

ndices

Como ya hemos comentado, las sentencias DDL estn ms orientadas al administrador de la base de datos, es el que ms
las va a utilizar, el programador tiene que conocer cuestiones relativas a la estructura interna de una base de datos, pero no
tiene que ser experto en ello por lo que el estudio del tema se centrar en las sentencias y sobre todo en las clusulas que
pensamos pueden ser tiles a un programador y no entraremos en mucho detalle en cuanto a la estructura fsica de la base
de datos y en la administracin de la misma.
8.2. 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 ] } ]

149

[ 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 ] ]

150

[ , 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.
Si no se especifica un nombre de archivo de datos, SQL Server utiliza el nombre de la base de datos como nbfichero_logico
y nbfichero_fisico.
Si queremos definir varios archivos de datos, despus de la palabra ON escribiremos las definiciones de cada archivo
separadas por comas.
PRIMARY especifica que la lista de archivos asociada define el grupo de archivos principal, y el primer archivo especificado
se

convierte

en

el

archivo

de

datos

principal.

Si no se especifica PRIMARY, el primer archivo enumerado en la instruccin CREATE DATABASE se convierte en el archivo
principal.
Detrs de la lista de archivos del grupo de archivos principal, con <grupo> se puede colocar una lista opcional de
elementos separados por comas que definan los grupos de archivos de usuario y sus archivos.

<grupo> ::=

151

FILEGROUP nbgrupo [ DEFAULT ]

<esp_fichero> [ ,...n ]

}
Nbgrupo es el nombre del grupo y a continuacin indicamos los archivos de datos que pertenecen a ese grupo, los archivos
pertenecientes

al

grupo

se

indican

con

los

del

grupo

principal.

DEFAULT
Cambia el grupo de archivos predeterminado de la base de datos a Nbgrupo. Slo un grupo de archivos de la base de datos
puede ser el grupo de archivos predeterminado.
Con la clusula LOG ON definiremos los archivos utilizados para almacenar el registro de la base de datos (los archivos de
registro).

[ LOG ON { <esp_fichero> [ ,...n ] } ]


Si no se especifica LOG ON, se crea automticamente un archivo de registro cuyo tamao es el 25 por ciento de la suma de
los tamaos de todos los archivos de datos de la base de datos, o 512 KB (lo que sea mayor), tambin limitar el nombre de
la base de datos a 123 caracteres ya que el sistema generar el nombre del archivo de registro aadiendo al nombre de la
base
Con

de
la

clusula

datos
COLLATE

podemos

un
cambiar

la

intercalacin

sufijo.
predeterminada.

La intercalacin define:

El alfabeto o lenguaje cuyas reglas de ordenacin se aplican si se especifica la ordenacin de diccionario.

La pgina de cdigos usada para almacenar datos de caracteres que no son Unicode.

Las reglas de comportamiento frente a maysculas y minsculas y caracteres acentuados.

La sintaxis es la siguiente:

COLLATE <nbintercalacion>

< nbintercalacion >:: =

nbinterWindows_ CaseSensitivity_AccentSensitivity
nbinterWindows: Es un nombre de intercalacin de Windows. Visita el siguiente bsico para saber ms sobre las
intercalaciones.
CaseSensitivity: Especifica que s se distingue entre maysculas y minsculas (CS), o no (CI). SQL Server Mobile slo

152

admite

esta

opcin.

AccentSensitivity: Especifica si se distinguen los caracteres acentuados (AS), o no (AI). SQL Server Mobile slo admite la
opcin

AS.

Si no se especifica, se asigna a la base de datos la intercalacin predeterminada de la instancia de SQL Server. No se


puede especificar un nombre de intercalacin en una instantnea de base de datos, ni tampoco con las clusulas FOR
ATTACH

FOR.

Existen otras clusulas a nivel de administracin de la base de datos que no detallaremos aqu como son:

[ WITH <external_access_option> ]

<external_access_option> ::=

DB_CHAINING { ON | OFF }

| TRUSTWORTHY { ON | OFF }

}
Para controlar el acceso externo a la base de datos y desde sta.

CREATE DATABASE nbBasedeDatos

ON <esp_fichero> [ ,...n ]

FOR { ATTACH [ WITH <service_broker_option> ]

| ATTACH_REBUILD_LOG }

[;]

<service_broker_option> ::=

153

ENABLE_BROKER

| NEW_BROKER

| ERROR_BROKER_CONVERSATIONS

}
Para adjuntar una base de datos.

CREATE DATABASE nbInstantanea_basedatos

ON

NAME = nbfichero_logico ,

FILENAME = 'nbfichero_fisico'

) [ ,...n ]

AS SNAPSHOT OF nbBaseDatos_origen

[;]
Para crear una instantnea de base de datos (copia de slo lectura de una base de datos).

CREATE DATABASE database_name

154

[DATABASEPASSWORD 'database_password'

[ENCRYPTION {ON|OFF}]

[COLLATE collation_name comparison_style]

database password ::= identifier


Para crear una base de datos protegida mediante contrasea, opcin disponible para SQL Server Mobile (Microsoft SQL
Server 2005 Mobile Edition (SQL Server Mobile), antes denominado Microsoft SQL Server 2000 Windows CE 2.0 (SQL
Server CE), es una base de datos compacta y con una gran variedad de funciones diseada para admitir una lista ampliada
de dispositivos inteligentes y Tablet PC. Entre los dispositivos inteligentes estn todos los dispositivos que ejecuten Microsoft
Windows CE 5.0, Microsoft Mobile Pocket PC 2003, Microsoft Mobile Version 5.0 Pocket PC o Microsoft Mobile Version 5.0
Smart Phone. Esta compatibilidad adicional con dispositivos permite a los programadores usar la misma funcionalidad de
base de datos en un gran nmero de dispositivos.)
8.3. Eliminar una base de datos DROP DATABASE
Para eliminar una base de datos tenemos la instruccin DROP DATABASE.

DROP DATABASE { nbBasedeDatos } [ ,...n ] [;]


La

base

de

datos

puede

ser

una

base

de

datos

normal

una

instantnea

de

base

de

datos.

Para poder ejecutar la sentencia el usuario debe tener permiso de CONTROL y se debe de ejecutar en un contexto diferente
del de la base de datos a eliminar, por ejemplo:

use b1

DROP DATABASE b1
Falla porque con el use estamos en el contexto de la base de datos a eliminar.
Como se ve en la sintaxis podemos eliminar varias bases de datos con una sla sentencia DROP DATABASE.
Por ejemplo:

155

DROP DATABASE b1,b2


Elimina las bases de datos b1 y b2.
8.4. Modificar las propiedades de una BD ALTER DATABASE
Si despus de crear la base de datos queremos cambiar algo de su definicin podramos eliminarla (con DROP DATABASE)
y luego crearla otra vez (con CREATE DATABASE), pero si ya la hemos rellenado con tablas u otros objetos, esta solucin
no sera muy prctica. Para cambiar la definicin de la base de datos una vez creada tenemos que utilizar la sentencia
ALTER DATABASE.
Para poder ejecutar esta sentencia se debe de tener el permiso ALTER en la base de datos. Esta sentencia se debe
ejecutar en el modo de confirmacin automtica (modo de administracin de transacciones predeterminado) y no se permite
en

una

transaccin

explcita

implcita.

Las instantneas de bases de datos no se pueden modificar, y para modificar las opciones de base de datos asociadas a la
rplica, se utiliza el procedimiento almacenado del sistema sp_replicationdboption.
Sintaxis:

ALTER DATABASE nbBasedeDatos

<cambiar_ficheros>

| <cambiar_grupos>

| <opciones>

| MODIFY NAME = nuevo_nbBasedeDatos

| COLLATE nbintercalacin

[;]

156

Con esta sentencia resumida vemos que nos permite cambiar la definicin de la base de datos, nos va a permitir cambiar la
definicin de los ficheros que conforman la base de datos, tambin nos permite cambiar la definicin de los grupos, la
definicin de varias opciones, el tipo de intercalacin e incluso cambiar el nombre de la base de datos (con la clusula
MODIFY NAME).
Por ejemplo:

ALTER DATABASE Cliente

MODIFY NAME = Clientes;


La base de datos Cliente pasa a llamarse Clientes.
Como con la instruccin CREATE DATABASE veremos aqu un resumen de lo que ms le puede interesar a un
programador,

sin

entrar

en

demasiados

detalles

de

administracin.

Como muchas de las palabras ya las hemos explicado con la sentencia CREATE DATABASE, slo insistiremos en lo nuevo.

<cambiar_ficheros>::=

ADD FILE < esp_fichero > [ ,...n ]

[ TO FILEGROUP { nbgrupo | DEFAULT } ]

| ADD LOG FILE < esp_fichero > [ ,...n ]

| REMOVE FILE nbfichero

| MODIFY FILE < esp_fichero >

}
Con este grupo de opciones podemos cambiar la definicin de los archivos de datos de la base de datos.
ADD FILE permite aadir un nuevo archivo de datos (o varios) si no se aade nada (o TO FILEGROUP DEFAULT), el
archivo se aadir al grupo principal, si aadimos TO FILEGROUP nbgrupo, se aadir el archivo al grupo indicado.

157

Con

ADD

LOG

Con

REMOVE

FILE

FILE

podemos

nbfichero

aadir

eliminamos

un

nuevo

el

archivo

archivo
con

de

nombre

registro.
nbfichero.

Se elimina la definicin del archivo lgico (nbfichero) y elimina el archivo fsico asociado. El archivo no se puede quitar a
menos que est vaco.
Con MODIFY FILE <esp_fichero> podemos cambiar las especificaciones de alguno de los archivos de la base de datos.

<esp_fichero>::=

NAME = nbarchivo

[ , NEWNAME = nuevo_nbarchivo ]

[ , FILENAME = 'nbarchivo_fisico' ]

[ , SIZE = tamao [ KB | MB | GB | TB ] ]

[ , MAXSIZE = { tamao_mximo [ KB | MB | GB | TB ] | UNLIMITED } ]

[ , FILEGROWTH = incremento [ KB | MB | GB | TB| % ] ]

[ , OFFLINE ]

)
Slo
NAME

se
se

puede
debe

cambiar

especificar

siempre

una
para

propiedad
identificar

<especificacinDeArchivo>
el

archivo

que

se

cada
va

vez.
modificar.

Si se especifica SIZE, el nuevo tamao debe ser mayor que el tamao actual del archivo. Para reducir el tamao de una
base de datos, se utiliza el comando de consola SHRINKDATABASE de Transact_SQL.
Para modificar el nombre lgico de un archivo de datos o de un archivo de registro, especificamos el nombre lgico nuevo
para el archivo en la clusula NEWNAME. Por ejemplo:

158

ALTER DATABASE MiBasedeDatos

MODIFY FILE ( NAME = bd1, NEWNAME = base1)


Con esta sentencia, el archivo bd1 ahora se llama base1.
Con FILENAME podemos cambiar el nombre del fichero fsico, esto nos permite tambin cambiar la ubicacin del archivo
fsico.
Por ejemplo:

ALTER DATABASE MiBasedeDatos

MODIFY FILE(NAME = nbficherolgico,

FILENAME = 'nueva_ruta/nb_fichero_fsico')
La clusula OFFLINE establece el archivo sin conexin e impide el acceso a todos los objetos del grupo de archivos. Muy
importante!, esta opcin slo se debe de utilizar si el archivo est daado y si se puede restaurar. Un archivo establecido en
OFFLINE slo se puede restablecer con conexin mediante la restauracin del archivo a partir de una copia de seguridad.
Para obtener ms informacin acerca de cmo restaurar un solo archivo, consultar en la ayuda la sentencia RESTORE
(Transact-SQL).
UNLIMITED especifica que el tamao del archivo aumenta hasta que el disco est lleno. En SQL Server 2005, un archivo de
registro especificado con un aumento ilimitado tiene un tamao mximo de 2 TB y un archivo de datos tiene un tamao
mximo de 16 TB.
En cuanto a la modificacin de la definicin de grupos, tenemos esta sintaxis:

<cambiar_grupos>::=

| ADD FILEGROUP nbgrupo

| REMOVE FILEGROUP nbgrupo

| MODIFY FILEGROUP nbgrupo

159

{ READONLY | READWRITE }

| { READ_ONLY | READ_WRITE }

| DEFAULT

| NAME = nuevo_ nbgrupo

}
Con

ADD

Con

FILEGROUP

REMOVE

nbgrupo

FILEGROUP

aadimos
nbgrupo

un

nuevo

eliminamos

grupo
el

de

archivos

grupo

de

de
la

la

base

base

de
de

datos.
datos.

El grupo de archivos no se puede quitar a menos que est vaco. Para quitar todos los archivos del grupo, primero se
mueven

los

archivos

otro

grupo,

si

los

archivos

estn

vacos,

se

pueden

eliminar

directamente.

Con MODIFY FILEGROUP nbgrupo, modificamos el grupo de archivos.


DEFAULT Cambia el grupo de archivos predeterminado de la base de datos a nbgrupo.
NAME = nuevo_nbgrupo Cambia el nombre del grupo a nuevo_nbgrupo.
READ_ONLY | READONLY Especifica que el grupo de archivos es de slo lectura. En este caso no se permitir la
actualizacin de los objetos del mismo. Una base de datos de slo lectura no permite realizar modificaciones en los datos
por lo que:

Se omite la recuperacin automtica cuando se inicia el sistema.

No es posible reducir la base de datos.

No se produce ningn bloqueo en las bases de datos de slo lectura. Esto puede acelerar el rendimiento de las
consultas.

Para

cambiar

El

grupo

este
de

estado,
archivos

se

debe
principal

tener

acceso
no

exclusivo

puede

ser

la
de

base
slo

de

datos.
lectura.

160

Se puede utilizar indistintamente la palabra clave READONLY o READ_ONLY, pero READONLY se quitar en una versin
futura de Microsoft SQL Server por lo que se recomienda READ_ONLY.
READ_WRITE | READWRITE Especifica que el grupo es de lectura y escritura por lo que pueden realizarse actualizaciones
en

los

Para

cambiar

objetos
este

estado

se

del
debe

tener

grupo
acceso

exclusivo

de
a

la

archivos.
base

de

datos.

Se puede utilizar indistintamente la palabra clave READWRITE o READ_ WRITE, pero READWRITE se quitar en una
versin futura de Microsoft SQL Server por lo que se recomienda READ_WRITE.
Nota. El estado de estas opciones se puede determinar mediante el examen de la columna is_read_only de la vista de
catlogo sys.databases o la propiedad Updateability de la funcin DATABASEPROPERTYEX.
Para finalizar tenemos el apartado <opciones> que nos permite definir y/o cambiar muchas opciones de la base de datos.
La lista de opciones es muy larga, como podemos observar a continuacin, y no entraremos en detalles.

<opciones>::=

SET

{ <optionspec> [ ,...n ] [ WITH <termination> ] }

| ALLOW_SNAPSHOT_ISOLATION {ON | OFF }

| READ_COMMITTED_SNAPSHOT {ON | OFF } [ WITH <termination> ]

<optionspec>::=

<db_state_option>

161

| <db_user_access_option>

| <db_update_option> | <external_access_option>

| <cursor_option>

| <auto_option>

| <sql_option>

| <recovery_option>

| <database_mirroring_option>

| <supplemental_logging_option>

| <service_broker_option>

| <date_correlation_optimization_option>

| <parameterization_option>

<db_state_option> ::=

{ ONLINE | OFFLINE | EMERGENCY }

<db_user_access_option> ::=

162

{ SINGLE_USER | RESTRICTED_USER | MULTI_USER }

<db_update_option> ::=

{ READ_ONLY | READ_WRITE }

<external_access_option> ::=

DB_CHAINING { ON | OFF }

| TRUSTWORTHY { ON | OFF }

<cursor_option> ::=

{ CURSOR_CLOSE_ON_COMMIT { ON | OFF }

| CURSOR_DEFAULT { LOCAL | GLOBAL }

<auto_option> ::=

AUTO_CLOSE { ON | OFF }

| AUTO_CREATE_STATISTICS { ON | OFF }

163

| AUTO_SHRINK { ON | OFF }

| AUTO_UPDATE_STATISTICS { ON | OFF }

| AUTO_UPDATE_STATISTICS_ASYNC { ON | OFF }

<sql_option> ::=

ANSI_NULL_DEFAULT { ON | OFF }

| ANSI_NULLS { ON | OFF }

| ANSI_PADDING { ON | OFF }

| ANSI_WARNINGS { ON | OFF }

| ARITHABORT { ON | OFF }

| CONCAT_NULL_YIELDS_NULL { ON | OFF }

| NUMERIC_ROUNDABORT { ON | OFF }

| QUOTED_IDENTIFIER { ON | OFF }

| RECURSIVE_TRIGGERS { ON | OFF }

164

<recovery_option> ::=

RECOVERY { FULL | BULK_LOGGED | SIMPLE }

| TORN_PAGE_DETECTION { ON | OFF }

| PAGE_VERIFY { CHECKSUM | TORN_PAGE_DETECTION | NONE }

< database_mirroring_option> ::=

{ <partner_option> | <witness_option> }

<partner_option> ::=

PARTNER { = 'partner_server'

| FAILOVER

| FORCE_SERVICE_ALLOW_DATA_LOSS

| OFF

| RESUME

165

| SAFETY { FULL | OFF }

| SUSPEND

| REDO_QUEUE ( integer { KB | MB | GB } | UNLIMITED )

| TIMEOUT integer

<witness_option> ::=

WITNESS { = 'witness_server'

| OFF

<supplemental_logging_option> ::=

SUPPLEMENTAL_LOGGING { ON | OFF }

<service_broker_option> ::=

ENABLE_BROKER

| DISABLE_BROKER

166

| NEW_BROKER

| ERROR_BROKER_CONVERSATIONS

<date_correlation_optimization_option> ::=

DATE_CORRELATION_OPTIMIZATION { ON | OFF }

<parameterization_option> ::=

PARAMETERIZATION { SIMPLE | FORCED }

<termination> ::=

ROLLBACK AFTER integer [ SECONDS ]

| ROLLBACK IMMEDIATE

167

| NO_WAIT

}
Se pueden ver ms detalles de estas opciones en la ayuda de SQL SERVER buscando ALTER DABATABASE
8.5. Crear una tabla CREATE TABLE
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

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.

nbEsquema

de
Es

el

usuario
nombre

debe
del

tener

esquema

al

permisos
que

CREATE

pertenece

la

TABLE.

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

168

< 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 |

169

[ { 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.
Tambin podemos definir tipos de datos XML.
Unidad 8. Avanzado: Tipos de datos: precisin, escala, longitud y prioridad (I)
Introduccin
En SQL Server 2005, cada columna, variable local, expresin y parmetro tiene un tipo de datos relacionado. Un tipo de
datos es un atributo que especifica los valores que el objeto puede contener: datos enteros, de caracteres, de moneda, de
fecha

hora,

cadenas

binarias,

etc.

SQL Server proporciona un conjunto de tipos de datos del sistema que define todos los tipos de datos que pueden utilizarse
con SQL Server. Tambin podemos definir nuestros propios tipos de datos en Transact-SQL o Microsoft .NET Framework.
Los tipos de datos de alias estn basados en los tipos de datos proporcionados por el sistema. Para obtener ms
informacin acerca de los tipos de datos de alias, vea Trabajar con tipos de datos de alias. Los tipos definidos por el usuario
obtienen sus caractersticas de los mtodos y los operadores de una clase que se crean mediante uno de los lenguajes de
programacin compatibles con .NET Framework. Para obtener ms informacin, vea Trabajar con tipos definidos por el
usuario

para

CLR.

170

Cuando dos expresiones que tienen tipos de datos, intercalaciones, precisin, escala o longitud diferentes son combinadas
por un operador, las caractersticas del resultado vienen determinadas por lo siguiente:

El tipo de datos del resultado viene determinado por la aplicacin de las reglas de precedencia de tipos de datos a
los tipos de datos de las expresiones de entrada. Para obtener ms informacin, vea Prioridad de tipo de datos
(Transact-SQL).

La intercalacin del resultado viene determinada por las reglas de precedencia de intercalacin cuando el tipo de
datos del resultado es char, varchar, text, nchar, nvarchar o ntext. Para obtener ms informacin, vea Prioridad
de intercalacin (Transact-SQL).

La precisin, escala y longitud del resultado dependen de la precisin, escala y longitud de las expresiones de
entrada. Para obtener ms informacin, vea Precisin, escala y longitud (Transact-SQL).

SQL Server 2005 proporciona sinnimos de tipos de datos para la compatibilidad con SQL-92. Para obtener ms
informacin, vea Sinnimos de tipos de datos (Transact-SQL).
Categoras de tipos de datos
Los tipos de datos de SQL Server 2005 se organizan en las siguientes categoras:
Numricos exactos

Cadenas de caracteres Unicode

Numricos aproximados Cadenas binarias


Fecha y hora

Otros tipos de datos

Cadenas de caracteres
En SQL Server 2005, segn las caractersticas de almacenamiento, algunos tipos de datos estn designados como
pertenecientes a los siguientes grupos:

Tipos de datos de valores grandes: varchar(max), nvarchar(max) y varbinary(max)

Tipos de datos de objetos grandes: text, ntext, image, varchar(max), nvarchar(max), varbinary(max) y xml

Nota: sp_help devuelve -1 como la longitud del valor de gran tamao y de los tipos de datos xml.
Numricos exactos
bigint

decimal

int

numeric

smallint money
tinyint

smallmoney

171

bit
Numricos aproximados
float real
Fecha y hora
datetime smalldatetime
Cadenas de caracteres
char

text

varchar
Cadenas de caracteres Unicode
nchar

ntext

nvarchar
Cadenas binarias
binary

image

varbinary
Otros tipos de datos
cursor

timestamp

sql_variant uniqueidentifier
table

xml

Sinnimos de tipos de datos (Transact-SQL)


Los sinnimos de tipos de datos se incluyen en SQL Server 2005 por compatibilidad con SQL-92. En la siguiente tabla se
incluyen los sinnimos y los tipos de datos de sistema de SQL Server a los que se asignan.
Sinnimo

Tipo de datos de sistema de SQL Server

172

Binary varying

varbinary

char varying

varchar

character

char

character

char(1)

character(n)

char(n)

character varying(n)

varchar(n)

Dec

decimal

Double precision

float

float[(n)] para n = 1-7

real

float[(n)] para n = 8-15

float

integer

int

national character(n)

nchar(n)

national char(n)

nchar(n)

national character varying(n) nvarchar(n)


national char varying(n)

nvarchar(n)

national text

ntext

rowversion

timestamp

Los sinnimos de tipos de datos pueden utilizarse en lugar del nombre del tipo de datos base correspondiente en las
instrucciones del lenguaje de definicin de datos (DDL), como CREATE TABLE, CREATE PROCEDURE o DECLARE
@variable. Sin embargo, los sinnimos no tienen visibilidad despus de crear el objeto. Una vez creado el objeto, se le
asigna el tipo de datos base asociado al sinnimo. No hay ningn registro de que el sinnimo se haya especificado en la
instruccin

que

ha

creado

el

objeto.

A todos los objetos que proceden del objeto original, como las columnas del conjunto de resultados o las expresiones, se les
asigna el tipo de datos base. Todas las funciones de metadatos subsiguientes ejecutadas en el objeto original y cualquier
objeto derivado informarn del tipo de datos base y no del sinnimo. Este comportamiento se produce con las operaciones

173

de metadatos como sp_help y otros procedimientos almacenados del sistema, las vistas del esquema de informacin o las
diferentes operaciones de metadatos de la API de acceso a datos que informan de los tipos de datos de las columnas de
tablas

conjuntos

de

resultados.

Por ejemplo, puede crear una tabla si especifica national character varying:
CREATE TABLE ExampleTable (PriKey int PRIMARY KEY, VarCharCol national character varying(10))
VarCharCol se asigna a un tipo de datos nvarchar(10) y todas las funciones de metadatos posteriores informan de la
columna como columna nvarchar(10). Las funciones de metadatos nunca informarn de ellos como columna national
character varying(10).
Precisin, escala y longitud (Transact-SQL)
La precisin es el nmero de dgitos de un nmero. La escala es el nmero de dgitos situados a la derecha de la coma
decimal de un nmero. Por ejemplo, el nmero 123,45 tiene una precisin de 5 y una escala de 2.
En SQL Server 2005, la precisin mxima predeterminada de los tipos de datos numeric y decimal es 38. En versiones
anteriores

de

SQL

Server,

el

valor

predeterminado

mximo

es

28.

La longitud de un tipo de datos numrico es el nmero de bytes utilizados para almacenar el nmero. La longitud para una
cadena de caracteres o tipo de datos Unicode es el nmero de caracteres. La longitud para los tipos de datos binary,
varbinary y image es el nmero de bytes. Por ejemplo, un tipo de datos int que puede contener 10 dgitos se almacena en
4 bytes y no acepta coma decimal. El tipo de datos int tiene una precisin de 10, una longitud de 4 y una escala de 0.
Cuando se concatenan dos expresiones char, varchar, binary o varbinary, la longitud de la expresin resultante es la
suma

de

las

longitudes

de

las

dos

expresiones

de

origen

8.000

caracteres,

lo

que

sea

menor.

Cuando se concatenan dos expresiones nchar o nvarchar, la longitud de la expresin resultante es la suma de las
longitudes

de

las

dos

expresiones

de

origen

4.000

caracteres,

lo

que

sea

menor.

Cuando se comparan dos expresiones del mismo tipo de datos pero de distintas longitudes mediante UNION, EXCEPT o
INTERSECT,

la

longitud

resultante

es

la

longitud

mxima

de

las

dos

expresiones.

La precisin y la escala de los tipos de datos numricos, excepto decimal, son fijas. Si un operador aritmtico tiene dos
expresiones del mismo tipo, el resultado tiene el mismo tipo de datos con la precisin y la escala definidas para ese tipo de
datos. Si un operador tiene dos expresiones con tipos de datos numricos diferentes, las reglas de prioridad de tipos de
datos definen el tipo de datos del resultado. El resultado tiene la precisin y la escala definidas para el tipo de datos que le
corresponde.
Esta tabla define cmo se calculan la precisin y la escala del resultado de la operacin cuando ste es de tipo decimal. El
resultado
Ambas

es

decimal

cuando

expresiones

se

cumple
son

alguna

de

las

de

siguientes

condiciones:

tipo

Una expresin es decimal y la otra es de un tipo de datos con una prioridad menor que

decimal.
decimal.

Las expresiones de operando se denotan como expresin e1, con precisin p1 y escala s1, y expresin e2, con precisin p2
y escala s2. La precisin y la escala de cualquier expresin que no sea decimal es la precisin y la escala definidas para el
tipo de datos de la expresin.
Operacin

Precisin del resultado

Escala del resultado *

e1 + e2

mx(s1, s2) + mx(p1-s1, p2-s2) + 1 mx(s1, s2)

174

e1 - e2

mx(s1, s2) + mx(p1-s1, p2-s2) + 1 mx(s1, s2)

e1 * e2

p1 + p2 + 1

s1 + s2

e1 / e2

p1 - s1 + s2 + mx(6, s1 + p2 + 1)

mx(6, s1 + p2 + 1)

e1 { UNION | EXCEPT | INTERSECT } e2 mx(s1, s2) + mx(p1-s1, p2-s2)

mx(s1, s2)

* La precisin y la escala del resultado tienen un valor mximo absoluto igual a 38. Cuando la precisin de un resultado es
mayor que 38, la escala correspondiente se reduce para evitar que la parte entera del resultado se trunque.
Prioridad de tipo de datos (Transact-SQL)
Cuando un operador combina dos expresiones de tipos de datos distintos, las reglas de prioridad de tipo de datos
especifican que el tipo de datos con la prioridad ms baja se convierta al tipo de datos con la prioridad ms alta. Si la
conversin no es una conversin implcita admitida, se devuelve un error. Cuando ambas expresiones de operandos tienen
el mismo tipo de datos, el resultado de la operacin tiene ese tipo de datos.
SQL Server 2005 utiliza el siguiente orden de prioridad para los tipos de datos:

tipos de datos def. por el usuario (el +alto)

sql_variant

xml

datetime

smalldatetime

float

real

decimal

money

smallmoney

bigint

int

smallint

tinyint

bit

ntext

text

175

image

timestamp

uniqueidentifier

nvarchar

nchar

varchar

char

varbinary

binary (el +bajo)

Una vez indicado el tipo de datos de la columna podemos opcionalmente completar su definicin con una serie de
clusulas.

[ COLLATE nbIntercalacion ]
Con la clusula COLLATE podemos definir el tipo de intercalacin que se utilizar para la columna (Ver CREATE
TABLE).

[ NULL | NOT NULL ]


Determina si se permiten valores nulos (NULL) en la columna o no (NOT NULL). Realmente NULL no es
estrictamente una restriccin, si no indicamos nada la columna permitir valores nulos, pero se puede especificar de
la misma forma que NOT NULL. NOT NULL se puede especificar para las columnas calculadas slo si se especifica
tambin PERSISTED.

[ CONSTRAINT nbRestriccion ] DEFAULT exp_constante ]


Con la clusula DEFAULT podemos especificar un valor por defecto, es decir el valor que tomar el campo cuando
no se haya especificado explcitamente un valor durante la insercin. Las definiciones DEFAULT se pueden aplicar a
cualquier columna excepto a las definidas como timestamp o a aquellas que tengan la propiedad IDENTITY. Si se
especifica un valor por defecto a una columna de un tipo definido por el usuario, dicho tipo debe ser compatible con
la conversin implcita de exp_constante en el tipo definido por el usuario. exp_constante slo puede ser NULL o un
valor constante (por ejemplo, una cadena de caracteres, una funcin escalar o una funcin del sistema, definida por
el

usuario

CLR).

Para mantener la compatibilidad con las versiones anteriores de SQL Server, se puede asignar un nombre de
restriccin a DEFAULT con [ CONSTRAINT nbRestriccion ]. Los nombres de restriccin deben ser nicos en el
esquema al que pertenece la tabla.

[ IDENTITY [( semilla, incremento )] [NOT FOR REPLICATION] ]

176

IDENTITY indica que la nueva columna es una columna de identidad. Cuando se agrega una nueva fila a la tabla, el
Motor de base de datos proporciona un valor incremental nico para la columna. Las columnas de identidad se
utilizan

normalmente

como

claves

principales.

La propiedad IDENTITY se puede asignar a las columnas tinyint, smallint, int, bigint, decimal(p,0) o
numeric(p,0). Slo se puede crear una columna de identidad para cada tabla. Las restricciones DEFAULT y los
valores predeterminados enlazados no se pueden utilizar en las columnas de identidad. En este caso, deben
especificarse el valor de inicializacin y el incremento, o ninguno de esto valores. Si no se especifica ninguno, el
valor

predeterminado

semilla

es

el

valor

que

se

es

utiliza

para

la

primera

fila

(1,1).
cargada

en

la

tabla.

Incremento es el valor incremental que se agrega al valor de identidad de la fila cargada anterior.
De forma general, si se especifica la clusula NOT FOR REPLICATION para una restriccin, dicha restriccin no se
impone cuando los agentes de rplica realizan operaciones de insercin, actualizacin o eliminacin. Si se
especifica esta clusula, junto con IDENTITY, los valores no se incrementan en las columnas de identidad cuando
los agentes de rplica realizan inserciones.

[ ROWGUIDCOL ]
ROWGUIDCOL indica que la nueva columna es una columna de GUID de filas. Slo se puede designar una
columna uniqueidentifier por tabla como columna ROWGUIDCOL. La propiedad ROWGUIDCOL se puede asignar
nicamente

una

columna

uniqueidentifier.

Las columnas de tipos de datos definidos por el usuario no se pueden designar con ROWGUIDCOL.
La propiedad ROWGUIDCOL no impone la unicidad de los valores almacenados en la columna. ROWGUIDCOL
tampoco genera automticamente valores para nuevas filas insertadas en la tabla, por lo que se debe de utilizar la
funcin NEWID en las instrucciones INSERT o utilizar la funcin NEWID como el valor predeterminado de la
columna

para

generar

valores

nicos

en

cada

fila.

Para ver ms consideraciones sobre columnas IDENTITY y ROWGUIDCOL.

Por ltimo nos quedan las restricciones de clave que aparecen en la sintaxis como:

[ <restriccion_columna> [ ...n ] ]

< restriccion_columna > ::=

[ CONSTRAINT nbRestriccion]

{ PRIMARY KEY | UNIQUE }[ CLUSTERED | NONCLUSTERED ]

[ WITH FILLFACTOR = factorRelleno

| WITH ( < opcion_indice > [ , ...n ] )

177

[ ON { partition_scheme_name ( partition_column_name )

| filegroup | "default" } ]

| [ FOREIGN KEY ]

REFERENCES [ nbEsquema.] nbTablaPadre [ ( col_padre ) ]

[ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]

[ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]

[ NOT FOR REPLICATION ]

| CHECK [ NOT FOR REPLICATION ] (expresion_validacion)


nbRestriccion es el nombre de la restriccin, como hemos visto antes, debe ser nico en el esquema al que
pertenece la tabla. Las restricciones se implementan internamente con ndices por lo que a veces podemos utilizar el
trmino ndice o restriccin indistintamente.

{PRIMARY KEY | UNIQUE} [ CLUSTERED | NONCLUSTERED ]


PRIMARY KEY indica que la columna es la clave principal de la tabla. Slo se puede crear una restriccin PRIMARY
KEY para cada tabla. Si la clave primaria (principal) est compuesta por varias columnas entonces no podemos
utilizar esta restriccin, tendremos que utilizar una restriccin de tabla que veremos ms adelante.
CLUSTERED indica que el ndice que se va a crear es un ndice agrupado. Como slo puede haber un ndice
agrupado por tabla, si todava no hay ninguno definido, por defecto se crear con la clave primaria, si ya existe un
ndice

agrupado,

la

clave

principal

se

crear

sin

ndice

agrupado.

Una clave primaria no puede contener valores nulos, por lo que todas las columnas definidas en una restriccin
PRIMARY KEY se deben definir como NOT NULL. Si cuando definimos la columna, no se indica nada, la columna
se

establecer

NOT

NULL.

Si la clave principal se define en una columna de tipo definido por el usuario CLR, la implementacin del tipo debe
admitir

el

orden

binario.

UNIQUE indica que la columna no admite valores duplicados, por lo que se crea un ndice nico. Una tabla puede
tener varios ndices nicos.

Si no se especifica CLUSTERED o NONCLUSTERED, de forma predeterminada se utiliza NONCLUSTERED.


Como cada restriccin UNIQUE genera un ndice. El nmero de restricciones UNIQUE no puede hacer que el
nmero

de

ndices

de

la

tabla

exceda

de

249

ndices

no

agrupados

ndice

agrupado.

178

Si se define una restriccin UNIQUE en una columna de tipo definido por el usuario CLR, la implementacin del tipo
debe

admitir

el

orden

binario

basado

en

el

operador.

Las dems opciones de ndices:

[ WITH FILLFACTOR = factorRelleno

| WITH ( < opcion_indice > [ , ...n ] ) ]

< opcion_indice > ::=

PAD_INDEX = { ON | OFF }

| FILLFACTOR = factorRelleno

| IGNORE_DUP_KEY = { ON | OFF }

| STATISTICS_NORECOMPUTE = { ON | OFF }

| ALLOW_ROW_LOCKS = { ON | OFF}

| ALLOW_PAGE_LOCKS ={ ON | OFF}

}
Son clusulas que nos permiten definir con ms detalle el ndice pero que no veremos aqu por entrar demasiado en
cuestiones internas.

La clusula CHECK.

CHECK [ NOT FOR REPLICATION ] ( expresion_validacion )


Con CHECK indicamos una regla de validacin que debern cumplir todas las filas de la tabla, es una restriccin que
exige la integridad del dominio al limitar los valores posibles que se pueden escribir en la columna.
expression

es

una

expresin

lgica

que

devuelve

TRUE

FALSE.

Si queremos definir una restriccin CHECK sobre una columna calculada, esta se deber definir como PERSISTED.
Una columna puede tener cualquier nmero de restricciones CHECK y la condicin puede incluir varias expresiones
lgicas combinadas con AND y OR. Varias restricciones CHECK para una columna se validan en el orden en que se
crean.
La condicin de bsqueda debe evaluarse como una expresin booleana y no puede hacer referencia a otra tabla.
Una restriccin CHECK en el nivel de columna slo puede hacer referencia a la columna restringida y una restriccin

179

CHECK

en

el

nivel

de

tabla

slo

puede

hacer

referencia

columnas

de

la

misma

tabla.

Las restricciones CHECK no se pueden definir en las columnas text, ntext o image.

Por ejemplo queremos que la columna Precio de la tabla que estamos definiendo no pueda contener valores
negativos:

Precio CURRENCY CONSTRAINT precio_pos CHECK (Precio > = 0)

Por ltimo a nivel de columna podemos definir una restriccin de clave ajena:

[ FOREIGN KEY ]

REFERENCES [ nbEsquema.] nbTablaPadre [ ( col_padre ) ]

[ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]

[ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]

[ NOT FOR REPLICATION ]


Con esta clusula definimos una regla de integridad referencial, los valores contenidos en la columna debern
apuntar

un

registro

en

la

tabla

de

referencia

(la

tabla

padre).

La palabra FOREIGN KEY no es obligatoria cuando estamos a nivel de columna, el utilizarla o no tiene el mismo
efecto.
Nbesquema es el nombre del esquema al que pertenece la tabla padre y nbTablaPadre es el nombre de la tabla
padre.

Col_padre es la columna de la tabla padre que se relaciona con la columna que estamos definiendo. Esta columna
debe

tener

el

mismo

tipo

de

datos

que

la

columna

en

la

que

se

define

la

restriccin.

La col_padre debe tener en la tabla padre una restriccin de PRIMARY KEY o UNIQUE, si no se indica una columna
padre

(columna

de

referencia)

se

utiliza

la

clave

primaria

de

la

tabla

padre.

Las reglas de integridad referencial obligan a que si se especifica un valor distinto de NULL en una columna con una
restriccin FOREIGN KEY, ese valor debe existir en la columna referenciada de la tabla padre; de lo contrario, se
devolver

un

error

de

infraccin

de

clave

externa.

Las restricciones FOREIGN KEY slo pueden hacer referencia a las tablas de la misma base de datos en el mismo
servidor. La integridad referencial entre bases de datos debe implementarse a travs de desencadenadores.
Las restricciones FOREIGN KEY pueden hacer referencia a otras columnas de la misma tabla. Esto se denomina
autorreferencia.

180

create table personas (codigo integer primary Key,

dni integer UNIQUE,

madre integer references personas,

padre integer references personas (col1),

dniTutor integer references personas (col4));


En esta tabla de personas, identificamos a cada persona por un cdigo, tambin tenemos el dni de la persona y el
cdigo de su padre y de su madre, adems nos guardamos el dni del tutor de la persona. Las madres, padres y
tutores son personas que deben de existir en la tabla Personas y en este caso utilizamos el cdigo para referenciar
padres y madres y el dni para referencial el tutor, esto ltimo lo podemos hacer porque el campo dni tiene una
restriccin

UNIQUE.

Por ltimo nos queda completar las reglas de integridad referencial en cuanto a qu hacer cuando se eliminan o
modifican valores que intervienen en una relacin referencial.

ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT }


Indica qu ocurre cuando se intenta eliminar un registro padre en la relacin que estamos definiendo. El valor
predeterminado

es

NO

ACTION.

NO ACTION El Motor de base de datos genera un error y no es posible eliminar la fila de la tabla primaria (el
padre).
CASCADE Si se borra una fila de la tabla primaria, se eliminan automticamente todas las filas correspondientes de
la tabla que estamos definiendo, en otras palabras, si se elimina un padre, se eliminan todos sus hijos.
SET NULL Si se borra una fila de la tabla primaria, todas las filas correspondientes de la tabla que estamos
definiendo tomarn el valor NULL en el campo clave ajena. En otras palabras, si se elimina un padre, sus hijos se
quedan
Para

sin
ejecutar

esta

restriccin,

la

columna

padre.
clave

ajena

debe

admitir

valores

NULL.

SET DEFAULT Es como la anterior pero en vez del valor NULL toman el valor que tienen predeterminado. Si no hay
ningn valor predeterminado establecido de forma explcita, tomarn el valor NULL. Hay que tener en cuenta que el
valor predeterminado debe de existir en la tabla primaria.

Veamos

estas

opciones

con

un

ejemplo:

Tenemos una tabla Proveedores y una tabla artculos, en la tabla artculos nos guardamos el cdigo del proveedor
del artculo, por lo tanto definiremos la tabla artculos de la siguiente forma:

CREATE TABLE articulos (

Codigo INTEGER PRIMARY KEY,

Denominacion VARCHAR(30),

181

.,

Proveedor INTEGER REFERENCES Proveedores,

)
El campo Proveedor es clave ajena y hace referencia a un cdigo de proveedor de la tabla Proveedores.
Aqu no hemos aadido ninguna clusula ON DELETE por lo que se toma NO ACTION.

.,

Proveedor INTEGER REFERENCES Proveedores ON DELETE NO ACTION,

)
Estas dos sentencias son equivalentes e indican que si se intenta borrar de la tabla Proveedores un proveedor
asignado a un artculo, el sistema da un error y no deja eliminar el proveedor.

.,

Proveedor INTEGER REFERENCES Proveedores ON DELETE CASCADE,

)
Se eliminar el proveedor y todos los artculos asignados a l.

.,

Proveedor INTEGER REFERENCES Proveedores ON DELETE SET NULL,

)
Se eliminar el proveedor de la tabla Proveedores y en la tabla Artculos, todas las filas que tenan ese nmero de
proveedor pasarn a tener el valor nulo en el campo proveedor.

ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT }


Indica qu ocurre cuando se intenta cambiar un valor del campo relacionado de la tabla padre en la relacin que
estamos definiendo. El valor predeterminado es NO ACTION.

Las

opciones

son

las

mismas

que

para

ON

DELETE.

NO ACTION El Motor de base de datos genera un error y no es posible modificar la fila de la tabla primaria (el
padre).
CASCADE Si se modifica un valor de la columna padre en la tabla primaria, se modificarn automticamente todas

182

las filas correspondientes de la tabla que estamos definiendo, en otras palabras, si se modifica el identificativo de un
padre,

se

actualizan

todos

sus

hijos.

SET NULL Si se modifica un valor de la columna padre en la tabla primaria, todas las filas correspondientes de la
tabla que estamos definiendo tomarn el valor NULL en el campo clave ajena. En otras palabras, si se modifica el
identificativo
Para

ejecutar

de

un

esta

padre,

restriccin,

la

sus

hijos

columna

clave

se
ajena

quedan
debe

admitir

sin

padre.

valores

NULL.

SET DEFAULT Es como la anterior pero en vez del valor NULL toman el valor que tienen predeterminado. Si no hay
ningn valor predeterminado establecido de forma explcita, tomarn el valor NULL. Hay que tener en cuenta que el
valor predeterminado debe de existir en la tabla primaria.

Volviendo al ejemplo anterior:

.,

Proveedor INTEGER REFERENCES Proveedores ON UPDATE NO ACTION,

)
Si cambiamos el cdigo del proveedor 3 a 3000 y hay artculos asignados al proveedor 3, el sistema da un error y
no deja modificar el proveedor.

.,

Proveedor INTEGER REFERENCES Proveedores ON UPDATE CASCADE,

)
Se modifica el proveedor y todos los artculos asignados a l pasan a tener el valor 3000 en el campo Proveedor.

.,

Proveedor INTEGER REFERENCES Proveedores ON UPDATE SET NULL,

)
Se modifica el proveedor y todos los artculos asignados a l pasan a tener el valor NULL en el campo Proveedor.

Definir restricciones de tabla


Hasta el momento hemos aprendido a definir restricciones sobre una columna, mientras la estamos definiendo aadimos a
su

definicin

la

restriccin

restricciones

que

queramos.

Tambin existen restricciones de tabla, son restricciones que se definen despus de definir todas las columnas de la tabla y
que pueden afectar a una o varias columnas de la tabla. Como veremos la sintaxis para definir una restriccin de tabla es
muy parecida a la sintaxis de la misma restriccin de columna, lo que vara es que ahora tenemos que indicar las columnas

183

afectadas

por

la

restriccin.

< restriccion_tabla > ::=

[ CONSTRAINT nbRestriccion]

{PRIMARY KEY | UNIQUE } [ CLUSTERED | NONCLUSTERED ]

(nbCol[ASC|DESC][ ,...n ] )

[ WITH FILLFACTOR = factorRelleno

|WITH ( < opcion_indice > [ , ...n ] )

[ ON { partition_scheme_name (partition_column_name)

| filegroup | "default" } ]

FOREIGN KEY(nbCol[,...n])REFERENCES nbTablaPadre

[(col_padre)[,...n] )]

[ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]

184

[ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]

[ NOT FOR REPLICATION ]

| CHECK [NOT FOR REPLICATION] (expresion_validacion )

}
Como las clusulas son las mismas que para las restricciones de columna, no repetiremos la explicacin de cada clusula,
lo

que

veremos

es

un

ejemplo

la

explicacin

de

ese

ejemplo.

Volviendo al ejemplo anterior de la tabla de Personas, podemos definir la misma utilizando restricciones de tabla:

CREATE TABLE personas (

codigo int,

dni int,

madre int,

padre int,

dniTutor int,

PRIMARY KEY (codigo),

UNIQUE (dni),

FOREIGN KEY (madre) REFERENCES Personas,

FOREIGN KEY (padre) REFERENCES Personas (codigo),

185

FOREIGN KEY (dniTutor) REFERENCES Personas (dni));


Tambin podamos haber mezclado restricciones de columna con restricciones de tabla, lo que no podemos hacer es definir
dos veces la misma restriccin, o la definimos a nivel de columna o a nivel de tabla pero no dos veces!
Utilizando la restricciones de tabla parece que la definicin queda ms clara, por un lado tenemos la definicin de cada
columna, y luego las restricciones.
Las restricciones de tabla se hacen imprescindibles cuando la restriccin afecta a una combinacin de columnas. Por
ejemplo imaginemos una tabla de productos en la que la clave principal est formada por el cdigo de fabricante y cdigo de
producto (porque dos productos diferentes pueden tener el mismo cdigo de producto con proveedores diferentes).
No podemos definir la clave de esta manera:

CREATE TABLE Productos (

Codproducto int PRIMARY KEY,

Codproveedor int PRIMARY KEY,

El Motor de la base de datos entendera que queremos definir dos claves primarias y eso es imposible. En este caso habra
que utilizar una restriccin de tabla:

CREATE TABLE Productos (

Codproducto int,

Codproveedor int,

las dems columnas,

PRIMARY KEY (Codproducto, Codproveedor));


Ocurre lo mismo con las dems restricciones. Imaginemos ahora una tabla de lneas de pedido en la que tenemos en una
lnea el producto pedido, y la cantidad pedida.

186

CREATE TABLE LineasPed (

pedido INT,

nlin INT,

codprod INT,

codprov INT,

cantidad INT,

PRIMARY KEY (pedido, nlin),

FOREIGN KEY (codprod,codprov) REFERENCES Productos,

UNIQUE (pedido,codprod,codprov));
La combinacin (codprod,codprov) forma una clave ajena que hace referencia a la tabla Productos, en este caso como la
clave principal de la tabla Productos est compuesta por los dos campos, la clave ajena tiene que tener el mismo nmero de
campo

del

mismo

tipo.

Con la restriccin UNIQUE indicamos que la combinacin formada por un nmero de pedido un cdigo de producto y cdigo
de proveedor no se puede repetir, esto hace que no se puedan insertar en un mismo pedido dos lneas del mismo
producto. No se puede duplicar la combinacin pero s las columnas individualmente (pueden haber varias filas con el
mismo nmero de pedido, varias filas con el mismo cdigo de producto y varias filas con el mismo codigo de proveedor.
Aqu termina la explicacin de la sintaxis bsica de las instrucciones CREATE TABLE. Nos queda hablar de las columnas
calculadas y de las tablas temporales, otras clusulas de la instruccin se pueden consultar en la ayuda de la instruccin
SQL CREATE TABLE.
Definir columnas calculadas.
Una columna calculada es una columna cuyo valor no se introduce, sino que se obtiene como resultado de un clculo.

< definicion_columna > ::=

187

nbCol AS expresion

[ PERSISTED

[NOT NULL]

[ <restriccion_columna> [...n ] ]

]
expresion es la expresin que define el valor de una columna calculada y est basada en otras columnas de la tabla.
Por ejemplo, una columna calculada puede ser definida as:

importe AS precio * cantidad


La expresin puede ser un nombre de columna no calculada, una constante, una funcin, una variable o cualquier
combinacin de estos elementos conectados mediante uno o ms operadores. La expresin no puede ser una subconsulta
ni

contener

tipos

de

datos

de

alias.

Una columna calculada es, por defecto, una columna virtual no almacenada fsicamente en la tabla. PERSISTED indica que
la columna calculada se almacena en la tabla y automticamente se actualizan los valores almacenados en ella cuando se
actualizan

las

columnas

de

las

que

depende.

Para que la columna pueda ser definida con PERSISTED la expresin que la calcula debe ser determinista. Una expresin
es determinista a menos que utilice una funcin no determinista.
Una columna calculada se puede utilizar en la lista de seleccin, clusula WHERE, clusula ORDER BY u otras ubicaciones
en que se puedan utilizar expresiones regulares, con las siguientes excepciones:

Una columna calculada no puede utilizarse como definicin de restriccin DEFAULT o FOREIGN KEY ni como NOT
NULL.

Una columna calculada no puede ser el destino de una instruccin INSERT o UPDATE. No tiene sentido querer
asignar un determinado

Definir tablas temporales


Una tabla temporal es una tabla creada por un determinado proceso y desaparece cuando termina ste.
Se pueden crear tablas temporales locales y globales. Las tablas temporales locales son visibles slo en la sesin actual y
las

tablas

temporales

globales

son

visibles

para

todas

las

sesiones.

Para indicar que la tabla que queremos crear es temporal aadimos a su nombre el prefijo # (#nbTabla) para tablas

188

temporales

locales

el

prefijo

##

(##nbTabla)

tablas

temporales

globales.

Por ejemplo:

CREATE TABLE #trabajo (col1 INT PRIMARY KEY);


Esta instruccin crea una tabla temporal local llamada trabajo con una sola columna.
Las tablas temporales funcionan casi como las tablas normales con algunas diferencias.
No se pueden crear particiones en las tablas temporales.
nbTabla no puede tener ms de 116 caracteres. Esto se debe a que si se crea una tabla temporal local en un procedimiento
almacenado o una aplicacin que varios usuarios pueden ejecutar al mismo tiempo, el Motor de base de datos tiene que ser
capaz de distinguir las tablas creadas por los distintos usuarios, lo consigue aadiendo internamente un sufijo numrico a
cada nombre de tabla temporal local. El nombre completo de una tabla temporal tal como se almacena en la tabla
sysobjects de tempdb consta del nombre de la tabla especificado en la instruccin CREATE TABLE y el sufijo numrico
generado por el sistema.
Las tablas temporales se quitan automticamente cuando estn fuera de mbito, a menos que ya se hayan quitado
explcitamente

mediante

DROP

TABLE:

Una tabla temporal local creada en un procedimiento almacenado se quita automticamente cuando se completa el
procedimiento almacenado. Cualquiera de los procedimientos almacenados anidados ejecutados por el procedimiento
almacenado que cre la tabla, puede hacer referencia a la tabla. El proceso que llam al procedimiento almacenado que
cre
Las

la
tablas

tabla
temporales

no
se

puede
quitan

hacer

referencia

automticamente

al

final

a
de

la

la

tabla.

sesin

actual.

Las tablas temporales globales se quitan automticamente cuando la sesin que cre la tabla finaliza y las tareas restantes
han dejado de hacer referencia a ellas. La asociacin entre una tarea y una tabla se mantiene slo durante la vida de una
nica instruccin Transact-SQL. Esto significa que la tabla temporal global se quita al finalizar la ltima instruccin TransactSQL

que

estuviera

haciendo

referencia

activamente

la

tabla

cuando

finaliz

la

sesin

que

la

cre.

Una tabla temporal local creada en un procedimiento almacenado o desencadenador, puede tener el mismo nombre que una
tabla temporal creada antes de que se llame al procedimiento almacenado o al desencadenador. No obstante, si una
consulta hace referencia a una tabla temporal y hay dos tablas temporales con el mismo nombre, no est definido en cul de
las dos tablas debe resolverse la consulta. Los procedimientos almacenados anidados pueden crear tambin tablas
temporales con el mismo nombre que la tabla temporal creada por el procedimiento almacenado que la llam. Sin embargo,
en el caso de las modificaciones que se van a resolver en la tabla creada en el procedimiento anidado, la tabla debe tener la
misma estructura, con los mismos nombres de columnas, que la tabla creada en el procedimiento que realiza la llamada.
Esto se muestra en el ejemplo siguiente.
Con tablas temporales globales o locales, la sintaxis CREATE TABLE admite la definicin de restricciones, excepto las
restricciones FOREIGN KEY. Si se especifica una restriccin FOREIGN KEY en una tabla temporal, la instruccin devuelve
un mensaje de advertencia que indica que la restriccin se ha omitido. La tabla se crea sin las restricciones FOREIGN KEY.
En las restricciones FOREIGN KEY no se puede hacer referencia a tablas temporales.

189

Se recomienda utilizar variables de tabla en lugar de tablas temporales. Las tablas temporales son tiles cuando es
necesario crear en ellas ndices de forma explcita o bien cuando los valores de tabla deben ser visibles en varios
procedimientos almacenados o funciones. En general, las variables de tabla contribuyen a que el procesamiento de las
consultas sea ms eficaz.
8.6. Eliminar una tabla DROP TABLE
Para eliminar una tabla de una base de datos tenemos la sentencia DROP TABLE. Con ella quitamos una o varias
definiciones de tabla y todos los datos, ndices, desencadenadores, restricciones y especificaciones de permisos que tengan
esas

tablas.

Las vistas o procedimientos almacenados que hagan referencia a la tabla quitada se deben quitar explcitamente con DROP
VIEW

DROP

PROCEDURE.

Su sintaxis es:

DROP TABLE [nbBaseDatos.[nbEsquema].|nbEsquema.]nbTabla[ ,...n ] [ ; ]


Para que las reglas de integridad referencial se cumplan, no se puede eliminar una tabla sealada por una restriccin
FOREIGN KEY. Primero se debe quitar la restriccin FOREIGN KEY o la tabla que tiene la clave ajena.
Se pueden quitar varias tablas de cualquier base de datos en una misma sentencia DROP TABLE. Se irn eliminando en el
mismo orden en que aparecen en la lista por lo que podremos eliminar dos tablas relacionadas con una sola sentencia pero
escribiendo la tabla que contiene la clave ajena primero y despus la tabla principal.
Requiere el permiso CONTROL en la tabla o pertenecer a la funcin fija de base de datos db_ddladmin.
Ejemplo:
DROP TABLE mitabla;
Elimina la tabla miTabla tanto su definicin como los datos, ndices definidos sobre ella y permisos.
8.7. Modificar la definicin de una tabla ALTER TABLE

ALTER TABLE [nbBaseDatos.[nbEsquema].| nbEsquema.]nbTabla

{ ALTER COLUMN nbColumna

<tipo_dato>

[ NULL | NOT NULL ]

190

[ COLLATE nbIntercalacion ]

| {ADD | DROP } { ROWGUIDCOL | PERSISTED }

| [WITH{ CHECK | NOCHECK}] ADD

<definicion_columna>

| <definicion_colCalc>

| <restriccion_tabla>

} [ ,...n ]

| DROP

[CONSTRAINT] nbRestriccion

|COLUMN nbColumna

} [,...n ]

| {CHECK|NOCHECK} CONSTRAINT {ALL|nbRestriccion[ ,...n ]}

191

| {ENABLE|DISABLE} TRIGGER {ALL | nbTrigger [ ,...n ] }

[;]
Aunque la sintaxis parece un poco complicada, realmente no lo es. La sentencia nos permite variar la definicin de una tabla
ya creada, en qu consiste esta variacin: modificar la definicin de columnas ya existentes (ALTER COLUMN), aadir ms
columnas o restricciones (ADD), eliminar columnas y restricciones (DROP), habilitar/deshabilitar restricciones (CHECK
CONSTRAINT)

habilitar/deshabilitar

triggers.

Como muchas de las clusulas las hemos estudiado con CREATE TABBLE, slo incidiremos en lo nuevo.
Para modificar una columna escribiremos la clusula ALTER COLUMN seguida del nombre de la columna que queremos
modificar y la nueva definicin, podemos cambiar su tipo de datos indicando uno nuevo, hacer que la columna acepte o no
valores

nulos

(NULL|NOTNULL),

cambiar

la

intercalacin

(COLLATE).

Con ADD ROWGUIDCOL hacemos que la columna sea GUID de filas y DROP ROWGUIDCOL hacemos que ya no lo sea.
Si la columna es una columna calculada podemos cambiar su condicin de columna almacenada con ADD/DROP
PERSISTED.
Ejemplo:

ALTER TABLE Clientes ALTER COLUMN direccion VARCHAR(40);


Hace

que

la

columna

direccion

de

la

tabla

Clientes,

ahora

admita

40

caracteres

alfanumricos.

Cuando cambiamos el tipo de una columna hay que tener en cuenta que el nuevo tipo debe ser compatible con el antiguo
para

que

no

se

pierdan

los

datos

almacenados.

Adems la columna no se puede modificar si es ROWGUIDCOL, calculada o si se utiliza en una columna calculada, si se
utiliza en un ndice (a menos que la columna sea del tipo de datos varchar, nvarchar o varbinary, el tipo de datos no se
cambie y el nuevo tamao sea igual al tamao anterior o mayor que ste), si se utiliza en estadsticas, en una restriccin
PRIMARY KEY, FOREIGN KEY, CHECK o UNIQUE. Sin embargo, se permite el cambio de longitud de una columna de
longitud variable en una restriccin CHECK o UNIQUE.
Para aadir una nueva columna o restriccin utilizamos la clusula ADD seguida de la definicin de lo que queremos aadir,
para eso seguimos la misma sintaxis que para definir las columnas y restricciones de tabla del CREATE TABLE.
Por ejemplo:

ALTER TABLE Clientes ADD email varchar(50);


Aade una nueva columna email.

192

ALTER TABLE Clientes ADD CONSTRAINT Pk PRIMARY KEY (codcli);


Aade una restriccin de clave primaria sobre la columna codcli que ya existe en la tabla.
La clusula WITH CHECK|NOCHECK permite establecer si la restriccin que estamos aadiendo se tiene que comprobar en
las filas que ya existen en la tabla.
Con la clusula DROP podemos eliminar de la tabla una restriccin (DROP CONSTRAINT), o una columna (DROP
COLUMN).
Con

las

Una

restriccin

PRIMARY

siguientes

KEY

no

puede

quitarse

si

existe

limitaciones:
un

ndice

XML

en

la

tabla.

Una columna no puede quitarse si se utiliza en un ndice, en una restriccin CHECK, FOREIGN KEY, UNIQUE o PRIMARY
KEY,

DEFAULT.

Ejemplo:
ALTER

TABLE

Clientes

DROP

COLUMN

email;

Elimina de la tabla Clientes la columna email que habamos creado anteriormente.


ALTER

TABLE

Clientes

DROP

CONSTRAINT

pk ;

Elimina de la tabla Clientes la restriccin de PRIMARY KEY, la columna sigue en la tabla pero ya no es clave principal.
Para finalizar, las dos ltimas clusulas nos permiten indicar si se tienen que comprobar o no determinadas restricciones y
habilitar
CHECK
DISABLE

y
CONSTRAINT
TRIGGER

ALL

activa

ALL

deshabilitar
la

comprobacin

deshabilita

todos

de

todas
los

las

triggers.

restricciones

triggers

definidas

definidos

sobre

sobre
la

la

tabla.
tabla.

Cuando deshabilitamos un trigger, ste sigue definido, pero no entra en accin cuando se produce el evento que debera
activarlo. En cualquier momento lo podremos habilitar con otra instruccin ALTER TABLE.
8.8. 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 ) [ ; ]

193

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

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

194

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.
8.9. Eliminar una vista DROP VIEW

195

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.
8.10. 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.
8.11. 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

196

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

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.
8.12. 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

197

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.

8.13. 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.

198

nbBaseDatos
nbEsquema
nbTablaVista

Es
Es
Es

el
el

el

nombre_indice

nombre

nombre

nombre

Es

de

el

la

de

del

esquema

tabla

vista

nombre

la
al
sobre

del

base

que
la

ndice

pertenece

que

se

quiere

que

de

datos.

la

tabla/vista.

crear

estamos

el

ndice.
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

CLUSTERED

un
el

ndice

nico

(no

admite

ndice

ser

valores

repetidos).
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.
8.14. Eliminar un ndice DROP INDEX

199

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

nbEsquema
nbTablaVista

Es
Es

el
el

el

nombre

nombre

nombre

de

la

de

del

esquema

tabla

vista

la
al
de

base

que
la

que

pertenece
se

quiere

de

datos.

la

tabla/vista.

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.
Unidad 9. Programacin en TRANSACT SQL (I)
9.1. 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.

200

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
Nosotros

(o

triggers)

estudiaremos

funciones

definidas

los

por
dos

el

usuario.
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.
9.2. 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.

201

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.
9.3. 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.
9.4. Crear y ejecutar un procedimiento

202

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

203

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:

Dice_Hola
Con un parmetro de entrada (la palabra que queremos que escriba)

CREATE PROCEDURE Dice_Palabra @palabra CHAR(30)

AS

204

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

205

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

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;

206

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'


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

207

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:

DECLARE @ultima AS DATETIME;

EXEC ultimo_contrato 12,@ultima OUTPUT;

PRINT @ultima;
RETURN
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

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

208

advertencia

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

209

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.
9.5. Instrucciones de control de flujo
Disponemos de diferentes elementos para el control de flujo, como pueden ser RETURN, IF... ELSE, WHILE, BREAK,
CONTINUE, GO TO, EXECUTE, etc. En los siguientes apartados aprenderemos cmo utilizarlos.
9.6. IF ELSE
Proporciona una ejecucin condicional, permite ejecutar o no ciertas instrucciones dependiendo de si se cumple o no una
determinada condicin.

IF condicion

{ sentencia_sql | bloque_sql }

[ ELSE

{ sentencia_sql | bloque_sql } ]
Si la condicin se cumple (da como resultado TRUE) se ejecuta la instruccin SQL o bloque de instrucciones que aparecen
a continuacin de la condicin, si la condicin no se cumple se ejecutan las sentencias que aparecen despus de la palabra
ELSE. El bloque ELSE es opcional.
Ejemplo: Si nos queremos guardar en una consulta todos los ejemplos para probarlos en cualquier momento, es conveniente
antes de los CREATE PROCEDURE colocar un DROP PROCEDURE para que la instruccin CREATE no d error si el
procedimiento ya existe, pero la primera vez la instruccin DROP PROC nos dar error porque el procedimiento todava no

210

existe,

as

que

lo

mejor

es

ejecutar

el

DROP

slo

si

el

procedimiento

existe,

utilizando

la

funcin

object_id(nombre_de_objeto,tipo de objeto) que nos devuelve el id del objeto y NULL si el objeto no existe.

IF object_id('trabajadores', 'P') IS NOT NULL

DROP PROCEDURE trabajadores;

GO

CREATE PROC trabajadores.


Otro ejemplo. Ahora queremos el procedimiento y si no existe se mandar un mensaje "el procedimiento no existe":

IF object_id('trabajadores', 'P') IS NOT NULL

BEGIN

PRINT 'Borramos el procedimiento'

DROP PROC trabajadores

END

ELSE PRINT 'El procedimiento ya existe'


Cuando queremos definir un bloque de instrucciones utilizamos los delimitadores BEGIN..END
Se pueden anidar varias sentencias IF hasta el lmite que permita la memoria.
9.7. WHILE BREAK- CONTINUE
Esta instruccin permite definir un bucle que repite una sentencia o bloque de sentencias mientras se cumpla una
determinada condicin.

WHILE condicion

211

{ sentencia_sql | bloque_sql }

| BREAK

| CONTINUE
Podemos

anidar

bucles,

colocar

un

bucle

WHILE

dentro

de

otro

BREAK Produce la salida del bucle WHILE ms interno. La instruccin BREAK interna sale al siguiente bucle ms externo.
Todas las instrucciones que se encuentren despus del final del bucle interno se ejecutan primero y despus se reinicia el
siguiente

bucle

ms

externo.

CONTINUE Hace que se reinicie el bucle WHILE y omite las instrucciones que haya despus de la palabra clave
CONTINUE.
Por ejemplo, tenemos los siguientes bucles anidados:

WHILE condicion1

-- Bucle 1

Instrucciones_1_1

WHILE condicion2

-- Bucle 2

Intrucciones2_1

If condicion3 BREAK

Instrucciones2_2

IF condicion4 CONTINUE

Instrucciones2_3

Instrucciones1_2
Las
Preguntamos

instrucciones

se

ejecutaran
por

en

este

orden:
condicion1:

212

Si

condicion1

Se

ejecuta

el

Preguntamos
se
ejecuta

cumple:

bloque

Instrucciones1_1

por

Si
Se

se

el

cumple

bloque

Si

condicon2:

de

condicion2:

instrucciones

condicin3

se

Salimos
Se
Y
Si

vuelve

bloque

preguntar

Si

vuelve
no

Se
se

Si

Instrucciones2_3

preguntar

por

no

ejecuta

el

bloque

Se

vuelve

preguntar

condicion1

condicion2
condicion4:

bloque

Se

Si

por

cumple

el

condicion2

Instrucciones2_3

preguntar

se

vuelve

condicion4:

bloque

ejecuta

instrucciones2_2

cumple
el

se

condicion1.
cumple:

bloque

se

por
se

el

Saltamos

2,
Instrucciones1_2

no

ejecuta
Si

bucle

el

condicin3
Se

cumple:

del

ejecuta
se

Instrucciones_2_1.

no

se

condicion2
cumple:

Instrucciones
por

1_2
condicion1

se

cumple:

Hemos terminado
9.8. WAITFOR
Bloquea la ejecucin de un lote, un procedimiento almacenado o una transaccin hasta alcanzar la hora o el intervalo de
tiempo especificado, o hasta que una instruccin especificada modifique o devuelva al menos una fila. Nosotros
estudiaremos los dos primeros casos.

WAITFOR {DELAY 'tiempo_a_transcurrir'

|TIME 'fechaHora_de_ejecucion'}
DELAY permite indicar un perodo de tiempo especificado (hasta un mximo de 24 horas) que debe transcurrir antes de la
ejecucin

de

un

lote,

un

procedimiento

almacenado

una

transaccin.

'tiempo_a_transcurrir' Es el perodo de tiempo que hay que esperar, se puede especificar en uno de los formatos aceptados
para el tipo de datos datetime o como una variable local. No se pueden especificar fechas; por lo tanto, no se permite la
parte

de

fecha

del

valor

datetime.

TIME permite indicar la hora especifica a la que se ejecuta el lote, el procedimiento almacenado o la transaccin.
'fechaHora_de_ejecucion' Es la hora a la que termina la instruccin WAITFOR por tanto a la que empieza la ejecucin de las
instrucciones siguientes a WAITFOR. Se puede especificar en uno de los formatos aceptados para el tipo de datos datetime

213

o como una variable local. No se pueden especificar fechas; por lo tanto, no se permite la parte de fecha del valor datetime.
Cada instruccin WAITFOR tiene un subproceso asociado. Si se especifica un gran nmero de instrucciones WAITFOR en
el mismo servidor, se pueden acumular muchos subprocesos a la espera de que se ejecuten estas instrucciones. SQL
Server supervisa el nmero de subprocesos asociados con las instrucciones WAITFOR y selecciona aleatoriamente algunos
de estos subprocesos para salir si el servidor empieza a experimentar la falta de subprocesos.
Ejemplo:

PRINT CONVERT(CHAR(8),Getdate(),108);

WAITFOR DELAY '00:00:03'

PRINT CONVERT(CHAR(8),Getdate(), 108);

WAITFOR DELAY '00:03'

PRINT CONVERT(CHAR(8),Getdate(), 108);


Visualiza la hora actual, espera 3 segundos y vuelve a visualizar la hora actual, despus espera 3 minutos y vuelve a
visualizar la hora actual. Se ha utilizado la funcin CONVERT con el estilo 108 para que aparezca slo la hora y con
segundos.
9.9. GOTO
Altera

el

flujo

de

ejecucin

lo

dirige

una

etiqueta.

Las etiquetas se indican mediante un nombre seguido del carcter:


GOTO NombreEtiqueta
Ejemplo:
IF Condicion GOTO etiq

----

Etiq:

----

214

---Es una instruccin a evitar porque puede llevar a redactar programas no estructurados.
9.10. TRY... CATCH
Definicin
La estructura TRYCATCH implementa un mecanismo de control de errores para Transact-SQL, permite incluir un grupo de
instrucciones Transact-SQL en un bloque TRY. Si se produce un error en el bloque TRY, el control se transfiere a otro grupo
de instrucciones que est incluido en un bloque CATCH.

BEGIN TRY

{sentencia_sql|bloque_sql}

END TRY

BEGIN CATCH

[{sentencia_sql|bloque_sql}]

END CATCH [ ; ]
Una construccin TRYCATCH no puede abarcar varios bloques de instrucciones Transact-SQL (varios bloques
BEGINEND de instrucciones Transact-SQL) ni una construccin IFELSE.
Si no hay errores en el cdigo incluido en un bloque TRY, cuando la ltima instruccin de este bloque ha terminado de
ejecutarse, el control se transfiere a la instruccin inmediatamente posterior a la instruccin END CATCH asociada. Si hay
un error en el cdigo incluido en el bloque TRY, el control se transfiere a la primera instruccin del bloque CATCH asociado.
Si la instruccin END CATCH es la ltima instruccin de un procedimiento almacenado o desencadenador, el control se
devuelve
Las

la

instruccin

que

construcciones

llam

al

procedimiento

TRYCATCH

almacenado
se

activ

el

pueden

desencadenador.
anidar.

Las construcciones TRYCATCH capturan los errores no controlados de los procedimientos almacenados o
desencadenadores ejecutados por el cdigo del bloque TRY. Alternativamente, los procedimientos almacenados o
desencadenadores pueden contener sus propias construcciones TRYCATCH para controlar los errores generados por su
cdigo. Por ejemplo, cuando un bloque TRY ejecuta un procedimiento almacenado y se produce un error en ste, el error se
puede controlar de las formas siguientes:

Si el procedimiento almacenado no contiene su propia construccin TRYCATCH, el error devuelve el control al


bloque CATCH asociado al bloque TRY que contiene la instruccin EXECUTE.

215

Si el procedimiento almacenado contiene una construccin TRYCATCH, el error transfiere el control al bloque
CATCH del procedimiento almacenado. Cuando finaliza el cdigo del bloque CATCH, el control se devuelve a la
instruccin inmediatamente posterior a la instruccin EXECUTE que llam al procedimiento almacenado.

No se pueden utilizar instrucciones GOTO para entrar en un bloque TRY o CATCH pero se puede utilizar para saltar a una
etiqueta

dentro

del

mismo

bloque

TRY

CATCH,

bien

para

salir

de

un

bloque

TRY

CATCH.

TRYCATCH no se puede utilizar en una funcin definida por el usuario.


Recuperar informacin sobre errores
En el mbito de un bloque CATCH, se pueden utilizar las siguientes funciones del sistema para obtener informacin acerca
del error que provoc la ejecucin del bloque CATCH:

ERROR_NUMBER() devuelve el nmero del error.

ERROR_SEVERITY() devuelve la gravedad.

ERROR_STATE() devuelve el nmero de estado del error.

ERROR_PROCEDURE() devuelve el nombre del procedimiento almacenado o desencadenador donde se produjo el


error.

ERROR_LINE() devuelve el nmero de lnea de la rutina que provoc el error.

ERROR_MESSAGE() devuelve el texto completo del mensaje de error. Este texto incluye los valores suministrados
para los parmetros reemplazables, como longitudes, nombres de objetos u horas.

Estas funciones devuelven NULL si se las llama desde fuera del mbito del bloque CATCH. Con ellas se puede recuperar
informacin sobre los errores desde cualquier lugar dentro del mbito del bloque CATCH. Por ejemplo, en la siguiente
secuencia de comandos se muestra un procedimiento almacenado que contiene funciones de control de errores. Se llama al
procedimiento almacenado en el bloque CATCH de una construccin TRYCATCH y se devuelve informacin sobre el
error.
Ejemplo, vamos a definir un procedimiento para calcular el precio unitario a partir de un importe y una cantidad:

-- Verificamos que el procedimiento que vamos a crear no existe.

IF OBJECT_ID ('CalculaPrecio', 'P' ) IS NOT NULL

DROP PROCEDURE CalculaPrecio;

GO

-- Creamos el procedimiento

216

CREATE PROCEDURE CalculaPrecio @importe MONEY,@cant INT,@precio MONEY OUTPUT

AS

BEGIN TRY

SELECT @precio=@importe/@cant;

END TRY

BEGIN CATCH

IF ERROR_NUMBER() = 8134 SELECT @precio=0

ELSE SELECT ERROR_NUMBER() as ErrorNumero,ERROR_MESSAGE() as MensajeDeError;

END CATCH;

GO

-- Lo utilizamos

DECLARE @resultado MONEY

EXEC CalculaPrecio 1000, 0, @resultado OUTPUT

SELECT 'resul', @resultado


Si al llamar al procedimiento le pasamos una cantidad igual a cero, la divisin provocar un error, se pasar el control al
bloque CATCH, en este bloque se evala si el error corresponde al error de divisin por cero (8134), si es as el
procedimiento devuelve un precio igual a cero, sino se enva un mensaje para avisar del error.

217

Errores controlados por TRYCATCH


TRYCATCH detecta todos los errores de ejecucin que tienen una gravedad mayor de 10 y que no cierran la conexin de
la

base

de

datos.

TRYCATCH no detecta:

Advertencias o mensajes informativos que tienen gravedad 10 o inferior.

Errores que tienen gravedad 20 o superior que detienen el procesamiento de las tareas de SQL Server Database
Engine en la sesin. Si se produce un error con una gravedad 20 o superior y no se interrumpe la conexin con la
base de datos, TRYCATCH controlar el error.

Atenciones, como solicitudes de interrupcin de clientes o conexiones de cliente interrumpidas.

Cuando el administrador del sistema finaliza la sesin mediante la instruccin KILL.

Un bloque CATCH no controla los siguientes tipos de errores cuando se producen en el mismo nivel de ejecucin
que la construccin TRYCATCH:

Errores de compilacin, como errores de sintaxis, que impiden la ejecucin de un lote.

Errores que se producen durante la recompilacin de instrucciones, como errores de resolucin de nombres de
objeto que se producen despus de la compilacin debido a una resolucin de nombres diferida.

Estos errores se devuelven al nivel de ejecucin del lote, procedimiento almacenado o desencadenador.
En el ejemplo siguiente se muestra cmo la construccin TRYCATCH no captura un error de resolucin de nombre de
objeto generado por una instruccin SELECT, sino que es el bloque CATCH el que lo captura cuando la misma instruccin
SELECT se ejecuta dentro de un procedimiento almacenado (a un nivel inferior).

USE Gestion;

GO

BEGIN TRY

SELECT * FROM TablaQueNoExiste;

END TRY

BEGIN CATCH

218

SELECT ERROR_NUMBER() as ErrorNumero,ERROR_MESSAGE() as MensajeDeError;

END CATCH
Intentamos ejecutar una SELECT de una tabla que no existe en la base de datos. El error no se captura y el control se
transfiere fuera de la construccin TRYCATCH, al siguiente nivel superior, en este caso salta el mensaje de error del
sistema.
Al ejecutar la misma instruccin SELECT dentro de un procedimiento almacenado, el error se producir en un nivel inferior al
bloque TRY y la construccin TRYCATCH controlar el error.

IF OBJECT_ID ('TablaInexistente','P') IS NOT NULL

DROP PROCEDURE TablaInexistente;

GO

-- Creamos el procedimiento.

CREATE PROCEDURE TablaInexistente

AS

SELECT * FROM TablaQueNoExiste;

GO

-- Utilizamos el procedimiento

BEGIN TRY

EXECUTE TablaInexistente

219

END TRY

BEGIN CATCH

SELECT ERROR_NUMBER() as ErrorNumero,ERROR_MESSAGE() as MensajeDeError;

END CATCH;
En este caso como el error se produce dentro del procedimiento, el control del error se devuelve al nivel superior (el que ha
realizado el EXECUTE) por lo que es capturado por el TRY y entra en el bloque CATCH, en vez de que salte el mensaje de
error del sistema saldr el nuestro.
9.11. Desencadenadores o TRIGGERS
Un desencadenador (o Trigger) es una clase especial de procedimiento almacenado que se ejecuta automticamente
cuando
SQL
Segn

se
Server
el

produce
permite
tipo

un

evento

crear
de

varios
evento

en

el

servidor

desencadenadores
que

los

para

de

bases

una

instruccin

desencadena

se

de

datos.
especfica.

clasifican

en:

Desencadenadores

DML

Desencadenadores

DDL

Desencadenadores

LOGON

Los desencadenadores DML se ejecutan cuando un usuario intenta modificar datos mediante un evento de lenguaje de
manipulacin de datos (DML). Los eventos DML son instrucciones INSERT, UPDATE o DELETE de una tabla o vista.
Los desencadenadores DDL se ejecutan en respuesta a una variedad de eventos de lenguaje de definicin de datos (DDL).
Estos eventos corresponden principalmente a instrucciones CREATE, ALTER y DROP de Transact-SQL, y a determinados
procedimientos

almacenados

del

sistema

que

ejecutan

operaciones

de

tipo

DDL.

Los desencadenadores logon se activan en respuesta al evento LOGON que se genera cuando se establece la sesin de un
usuario.
Nosotros limitaremos nuestro estudio a los desencadenadores DML.
9.12. CREATE TRIGGER
Esta instruccin nos permite definir un trigger:

CREATE TRIGGER [NombreEsquema.]NombreTrigger

ON {tabla | vista } [,...n] ]

{FOR|AFTER|INSTEAD OF} {[INSERT][,][UPDATE][,][DELETE]}

220

AS sentencia_sql [;] [,...n ]


NombreEsquema es el nombre del esquema al que pertenece el desencadenador DML. Los desencadenadores DML se
limitan

al

esquema

de

la

tabla

vista

en

la

que

se

crearon.

NombreTrigger es el nombre que le queremos dar al desencadenador. No puede comenzar con los smbolos # o ##.
Tabla | vista es el nombre de la tabla o vista en la que se ejecuta el desencadenador. Slo se puede hacer referencia a una
vista mediante un desencadenador INSTEAD OF. No es posible definir desencadenadores DML en tablas temporales
locales

globales.

DELETE INSERT UPDATE Especifica las instrucciones de modificacin de datos que activan el desencadenador cuando se
intenta ejecutarlas en esta tabla o vista. Se debe especificar al menos una opcin. En la definicin del desencadenador se
permite

cualquier

combinacin

de

estas

opciones,

en

cualquier

orden.

AFTER indica que el desencadenador slo se activa cuando todas las operaciones especificadas en la instruccin SQL
desencadenadora se han ejecutado correctamente. Adems, todas las acciones referenciales en cascada y las
comprobaciones

de
el

restricciones

AFTER

es

valor

Los

desencadenadores

deben

ser

predeterminado

correctas

cuando

AFTER

no

para

slo

que

se

se

este

desencadenador

especifica

pueden

la

definir

palabra
en

se

ejecute.

clave
las

FOR.
vistas.

INSTEAD OF indica que se ejecuta el desencadenador en vez de la instruccin SQL desencadenadora, por lo que se
suplantan

las

acciones

de

las

instrucciones

desencadenadoras.

Como mximo, se puede definir un desencadenador INSTEAD OF por cada instruccin INSERT, UPDATE o DELETE en
cada tabla o vista. No obstante, en las vistas es posible definir otras vistas que tengan su propio desencadenador INSTEAD
OF.
Los desencadenadores INSTEAD OF no se pueden utilizar en vistas actualizables que usan WITH CHECK OPTION.
Los desencadenadores INSTEAD OF DELETE/UPDATE no se permiten en tablas que tengan una clave ajena definida con
ON

DELETE/UPDATE

CREATE

TRIGGER

debe

ser

la

primera

CASCADE.

instruccin

en

el

proceso

por

lotes.

Un desencadenador se crea solamente en la base de datos actual; sin embargo, puede hacer referencia a objetos que estn
fuera

de

la

base

de

datos

actual.

Si se especifica el nombre del esquema del desencadenador hay que calificar tambin el nombre de la tabla o vista.
En un desencadenador se puede especificar cualquier instruccin SET. La opcin SET seleccionada permanece en efecto
durante la ejecucin del desencadenador

y, despus, vuelve automticamente a su configuracin anterior.

Un desencadenador est diseado para comprobar o cambiar los datos en base a una instruccin de modificacin o
definicin de datos; no debe devolver datos al usuario por lo que se aconseja no incluir en un desencadenador instrucciones
SELECT que devuelven resultados ni las instrucciones que realizan una asignacin variable. Si es preciso que existan
asignaciones de variable en un desencadenador, tenemos que utilizar la instruccin SET NOCOUNT al principio del mismo
para

impedir

la

devolucin

de

cualquier

conjunto

de

resultados.

Los desencadenadores DML usan las tablas lgicas deleted e inserted. Son de estructura similar a la tabla en que se
define el desencadenador, es decir, la tabla en que se intenta la accin del usuario. Las tablas deleted e inserted guardan
los

valores

antiguos

nuevos

de

las

filas

que

la

accin

del

usuario

puede

cambiar.

Si un desencadenador INSTEAD OF definido en una tabla ejecuta una instruccin en la tabla que normalmente volvera a
activarlo, al desencadenador no se lo llama de forma recursiva. En su lugar, la instruccin se procesa como si la tabla no

221

tuviera un desencadenador INSTEAD OF e inicia la cadena de operaciones de restriccin y ejecuciones de


desencadenadores AFTER. Por ejemplo, si para una tabla se define un desencadenador como INSTEAD OF INSERT, y ste
ejecuta una instruccin INSERT en la misma tabla, la instruccin INSERT ejecutada por el desencadenador INSTEAD OF no
vuelve a llamar al desencadenador. La instruccin INSERT ejecutada por el desencadenador inicia el proceso que realiza las
acciones

de

restriccin

activa

cualquier

desencadenador

AFTER

INSERT

definido

para

la

tabla.

Si un desencadenador INSTEAD OF definido en una vista ejecuta una instruccin en la vista que normalmente volvera a
activarlo, no se llamar el desencadenador de forma recursiva. En su lugar, la instruccin se resuelve a modo de
modificaciones en las tablas base subyacentes de la vista. En este caso, la definicin de la vista debe cumplir todas las
restricciones

para

una

vista

actualizable.

Aunque una instruccin TRUNCATE TABLE es en realidad un desencadenador DELETE, no puede activar un
desencadenador

porque

Las

instrucciones

siguientes

ALTER

la

operacin

no

Transact-SQL

DATABASE

registra
no

CREATE

estn

las

eliminaciones

permitidas

en

DATABASE

un

de

fila

individuales.

desencadenador
DROP

DML:

DATABASE

Adems, las siguientes instrucciones Transact-SQL no se permiten en el cuerpo de un desencadenador DML cuando ste
se

utiliza

CREATE

en

la

INDEX

tabla

o
ALTER

vista

que

INDEX

es

objeto
DROP

de

la

INDEX

accin

desencadenadora:
DROP

TABLE

ALTER TABLE cuando se utiliza para hacer lo siguiente:

Agregar, modificar o quitar columnas.

Cambiar particiones.

Agregar o quitar restricciones de tipo PRIMARY KEY o UNIQUE.

Ejemplo:

USE Gestion8

GO

CREATE TRIGGER ActualizaVentasEmpleados

ON pedidos FOR INSERT

AS

UPDATE empleados SET ventas=ventas+inserted.importe

222

FROM empleados, inserted

WHERE numemp=inserted.rep;

GO
Cuando se INSERTe un pedido, entrar en funcionamiento el trigger ActualizaVentasEmpleado y se ejecutarn las
instrucciones que aparecen despus de AS, en este caso actualizar (UPDATE) la tabla empleados sumar a las ventas del
empleado (ventas) el importe del pedido insertado (inserted.importe), y slo actualizar el empleado cuyo numemp coincida
con el campo rep del pedido insertado (WHERE numemp=inserted.rep).

-- Ahora comprobamos que funciona

SELECT * FROM empleados WHERE numemp=108;

INSERT INTO pedidos (numpedido,fechapedido,rep,clie,cant,importe,fab,producto)

VALUES (123456789,getdate(),108,2103,10,100,'Aci',41001)

SELECT * FROM empleados WHERE numemp=108;


Vemos que al insertar

un pedido de 100 del empleado

108, sus ventas han aumentado en 100.

ALTER TRIGGER
Permite modificar la definicin del desencadenador, no permite cambiar su nombre, para cambiar el nombre de un
desencadenador hay que eliminarlo (DROP TRIGGER) y volver a crearlo (CREATE TRIGGER).

ALTER TRIGGER [NombreEsquema.]NombreTrigger

ON {tabla|vista}

{FOR|AFTER|INSTEAD OF} {[INSERT][,][UPDATE][,][DELETE]} [WITH APPEND]

AS sentencia_sql [;] [,...n ]

223

La

sintaxis

es

similar

la

instruccin

CREATE

TRIGGER.

Ejemplo:

ALTER TRIGGER ActualizaVentasEmpleados

ON pedidos FOR INSERT

AS

UPDATE empleados SET ventas=ventas+inserted.importe

FROM empleados, inserted

WHERE numemp=inserted.rep AND inserted.importe IS NOT NULL;


Hemos modificado el desencadenador para que si el importe del pedido es nulo, no haga nada, no actualice con un valor
nulo.
Realiza el siguiente Ejercicio Triggers para practicar la creacin de desencadenadores.
9.13. DISABLE TRIGGER
En ocasiones puede ser til inhabilitar temporalmente un desencadenador sin que por ello suponga eliminarlo, para estos
casos podemos utilizar la sentencia DISABLE TRIGGER.

DISABLE TRIGGER {[NombreEsquema.]NombreTrigger [,...n] | ALL }

ON {NombreTablaVista | DATABASE | ALL SERVER} [;]


Ejemplo:

DISABLE TRIGGER ActualizaVentasEmpleado ON pedidos;


Deshabilita el desencadenador que hemos creado anteriormente, si despus de ejecutar esta sentencia se introduce un
nuevo

pedido,

el

empleado

correspondiente

no

se

actualizar.

Lo podemos comprobar con:

224

SELECT * FROM empleados WHERE numemp=108;

INSERT INTO pedidos (numpedido,fechapedido,rep,clie,cant,importe,fab,producto)

VALUES (123456791,getdate(),108,2103,10,300,'Aci',41001)

SELECT * FROM empleados WHERE numemp=108;

DISABLE TRIGGER ALL ON pedidos;


Deshabilita todos los desencadenadores asociados a la tabla pedidos.

DISABLE TRIGGER ALL ON DATABASE;


Deshabilita todos los desencadenadores definidos en la base de datos actual.

DISABLE TRIGGER ALL ON ALL SERVER;


Deshabilita todos los desencadenadores definidos en el servidor.
9.14. ENABLE TRIGGER
Con esta instruccin volvemos a habilitar los desencadenadores desactivados por la instruccin anterior.

ENABLE TRIGGER {[NombreEsquema.]NombreTrigger [,...n] | ALL }

ON {NombreTablaVista | DATABASE | ALL SERVER} [ ; ]


Funciona de la misma manera que DISABLE TRIGGER pero habilita en vez de deshabilitar.
Con este ejemplo lo podemos comprobar:

ENABLE TRIGGER ActualizaVentasEmpleados ON pedidos;

SELECT * FROM empleados WHERE numemp=108;

INSERT INTO pedidos (numpedido,fechapedido,rep,clie,cant,importe,fab,producto)

225

VALUES (123456792,getdate(),108,2103,10,400,'Aci',41001)

SELECT * FROM empleados WHERE numemp=108;


9.15. DROP TRIGGER
Para eliminar un desencadenador tenemos la instruccin DROP TRIGGER elimina la definicin del desencadenador.

DROP TRIGGER NombreEsquema.NombreTrigger [,...n] [;]


Ejemplo:

DROP TRIGGER ActualizaVentasEmpleados


Elimina el desencadenador ActualizaVentasEmpleados.

226

Вам также может понравиться