ENI - SQL Server 2008, SQL y Transact SQL PDF
ENI - SQL Server 2008, SQL y Transact SQL PDF
ENI - SQL Server 2008, SQL y Transact SQL PDF
Este libro sobre SQL Server está dirigido tanto a estudiantes de informática que deseen
aprender el lenguaje SQL con SQL Server como a informáticos que deseen actualizar sus
competencias en SQL Server 2008 para comprender y controlar las funciones que
complementan a esta nueva versión.El libro detalla el conjunto de instrucciones necesarias
para definir tablas y manejar datos: las diferentes instrucciones SQL y Transact SQL se
presentan e ilustran para comprender bien el cometido de las diferentes funciones
expuestas.
Se explican las ayudas de SQL Server 2008 en relación con el desarrollo, como el tipo
FILESTREAM o las estructuras jerárquicas. También se detallan las principales funciones
que permiten obtener una gestión de los datos más eficaz, tales como el XML y la
integración del código CLR (Common Language Runtime).
La base de datos que se va creando a lo largo del libro se puede descargar desde esta página
(enlace Descargar).
Jérôme GABILLAUD
Ingeniero informático industrial y consultor, Jérôme Gabillaud también es responsable
pedagógico en un gran centro de formación informática. Especialista de los sistemas de
acceso a los datos de Microsoft y Oracle, posee la certificación MVP (Most Valuable
Professional) en SQL Server. Jérôme Gabillaud también es autor de numerosas obras,
reconocidas por sus cualidades técnicas y pedagógicas, que tratan sobre administración o
puesta en marcha de bases de datos.
Preámbulo
Este libro se dirige principalmente a los programadores de aplicaciones y a quienes desean
serlo. En la primera parte se habla del modelo relacional y del álgebra relacional. Esta
álgebra es el origen del SQL. Comprender esta álgebra permite por tanto trabajar
eficazmente con el lenguaje SQL, sea cual sea el servidor de base de datos elegido. A
continuación, se aborda la parte de la gestión de la estructura o SQL DDL y la gestión de
los datos con SQL DML. Finalmente se explica Transact SQL, lenguaje de programación
sobre SQL Server. Los capítulos siguientes se dedican a descubrir y enseñar diferentes
funcionalidades que ofrece SQL Server a los programadores de aplicaciones para
facilitarles el trabajo: integración de código .Net en SQL Server, gestión de datos de tipo
XML…
El conjunto de tareas relativas a la administración del servidor, como la gestión del espacio
en disco, la gestión de la seguridad, los backup, la restauración, la replicación, etc. se
detallan en otro libro de Ediciones ENI.
SQL Server 2008 supone una evolución consecuente del gestor de base de datos de
Microsoft.
En lo referente a la programación, SQL Server propone un conjunto de herramientas y de
funcionalidades que permiten codificar con mayor rapidez. SQL Server permite asimismo
reducir la distancia existente entre los aspectos de programación y de administración de la
base de datos y del servidor.
Introducción
La implementación de las bases de datos implica la adopción de un cierto número de
responsabilidades específicas, que deben distinguirse de las de la administración.
En el marco de una aplicación de gestión, no todas las categorías de datos se ven afectadas
de la misma manera por estos problemas de organización.
En primer lugar, conviene definir la categoría de los datos. Esta categorización se realiza a
partir de algunas sencillas preguntas:
Este tipo de datos es la base de todo sistema de información. Se trata de datos a partir de los
cuales es posible trabajar. Así, en el marco de una gestión comercial, los datos básicos son
los datos sobre los clientes y los productos. Los datos de este tipo son lo más voluminosos
posible y evidentemente tienen una vida útil muy larga. Como son datos básicos, deberán
ser accesibles fácil y rápidamente.
Estos datos se generan a partir de datos básicos. Al contrario que estos últimos, su vida útil
será limitada, pero su volumen será mucho más importante. Por ejemplo, siempre en el
contexto de una gestión comercial, la información relativa a cada pedido se considera datos
de movimiento. El volumen es importante porque la empresa cuenta con que cada cliente
realice varios pedidos a lo largo de un mismo año contable. Por el contrario, la vida útil de
estos datos es bastante inferior. Efectivamente, no es necesario conservar este tipo de
información durante varios años en línea, sino que hace falta otro tipo de archivado más
económico.
Se trata de datos muy voluminosos y con una vida útil muy larga pero que presentan la
característica de no ser accesibles directamente. Cuando lo son, lo son únicamente para su
lectura. Por ejemplo, en el contexto de una aplicación de gestión comercial, puede tratarse
de datos relativos a los años contables pasados.
Esta organización es sin duda la más sencilla de utilizar. Los datos se graban unos tras otros
en un archivo. Cada conjunto de datos posee una longitud fija y los registros se almacenan
unos tras otros. De esta manera, el conocimiento de la longitud de un registro permite
mediante un simple cálculo acceder directamente al 10º registro.
Este tipo de organización es costosa en términos de espacio en disco y no permite extraer
fácilmente la información mediante otros criterios que no sean su posición en el orden de
grabación.
b. Secuencial
Con la organización secuencial los datos se graban unos tras otros. Se utiliza un carácter
especial para marcar la separación entre los diferentes campos y otro para marcar el final de
cada grabación. Los caracteres utilizados son generalmente la coma (,) y el retorno de carro
(CR). Los archivos que contienen estos separadores se describen como archivos CSV
(Comma Separated Values).
c. Secuencial indexada
Los datos siguen siendo almacenados en formato secuencial pero para permitir un acceso
más rápido a la información se pueden definir índices para cada archivo. Dentro de estos
índices se clasifican los datos por orden alfanumérico. El recorrido del índice se realiza de
manera secuencial y permite el acceso directo a la información almacenada en el archivo de
datos.
El recorrido del índice, aunque secuencial, es rápido porque el volumen de datos manejado
es reducido. Además, puesto que los datos se seleccionan, no es necesario leer todo el
índice.
Finalmente es posible definir varios índices en un mismo archivo de datos. Por ejemplo, en
un archivo que almacena información relativa a clientes, es posible definir un índice sobre
los nombres y otros sobre las ciudades.
Con este tipo de organización, la dificultad consiste en mantener actualizados los índices en
las operaciones de inserción, de eliminación y de actualización. Además, al igual que las
organizaciones directa y secuencial, los archivos no están vinculados unos a otros y no
existe contexto de seguridad en el nivel de los datos. Por ejemplo, nada impide, en el nivel
de los datos, la eliminación de un cliente aunque tenga pedidos en curso. De igual manera,
toda persona que pueda trabajar con los datos puede acceder a la totalidad de los datos en
lectura y en escritura. Estos inconvenientes plantean más problemas con la organización
secuencial indexada porque se pueden gestionar grandes volúmenes de datos con muchos
usuarios conectados.
Esta solución secuencial indexada ha sido adoptada de manera generalizada para
aplicaciones pequeñas y medianas porque para facilitar la programación, muchos lenguajes
de programación proponen un motor de gestión de este tipo de organización.
Con estas bases de datos, se resuelven los problemas de seguridad de acceso a los datos y la
conexión entre los datos. En cambio, cada editor ha desarrollado su motor de manera
independiente. Por lo tanto, hay que volver a aprender el funcionamiento de cada motor
cada vez que se programe con uno nuevo (el lenguaje de consulta, el API de acceso a los
datos). A esto hay que añadir una compleja organización de los datos. Estas soluciones de
propiedad son muy costosas para la empresa que las escoja.
Basadas en una representación lógica de los datos que respeta el modelo relacional, las
bases de datos relacionales han sabido imponerse porque todas se basan en el mismo
lenguaje normalizado que es SQL.
Cuando se define el esquema relacional para responder a todas las necesidades de los
usuarios, es necesario normalizarlo para evitar redundancias de información y estructuras
no conformes con el modelo relacional. Cuando se ha realizado esta operación, se puede
entonces desnormalizar el esquema aunque rara vez es la mejor opción. Si el programador
desnormaliza el esquema, deberá igualmente poner en marcha el conjunto de mecanismos
que permiten mantener la coherencia de los datos. Efectivamente, el modelo relacional, y
por tanto los SGBDR (Sistema de Gestión de Base de datos Relacional), sólo puede
garantizar la coherencia de los datos en los modelos normalizados.
Las formas normales permiten garantizar que el esquema es conforme con el modelo
relacional. En teoría existen cinco formas normales, pero en la práctica sólo se aplican las
tres primeras.
Primera forma normal: se dice que una tabla está en primera forma normal si todas las
columnas contienen valores simples.
Por ejemplo, si una tabla de clientes contiene un campo Teléfonos en el que se guardan los
diferentes números de teléfono de un cliente, esta tabla no está en primera forma normal
porque habrá que definir las columnas Trabajo y Móvil para estructurar mejor los datos.
Clientes Número Apellido Nombre Teléfonos Pedido Fecha
9234548576
1 Fuentes Pablo 1350 01/01/2008
683465789
9234548576
1 Fuentes Pablo 1352 15/01/2008
683465789
2 López Rosa 9245939847 1351 02/01/2008
Segunda forma normal: se dice que una tabla está en segunda forma normal si está en
primera forma normal y todas las columnas no claves dependen funcionalmente de la clave
primaria.
Siguiendo con el ejemplo anterior, es posible deducir en primer lugar que la clave de la
tabla de los clientes está compuesta por las columnas Número y Pedido.
En este caso, los valores de las columnas Apellido, Nombre, Trabajo y Móvil dependen
únicamente del número, mientras que la columna Fecha está relacionada con el número del
pedido. Por lo tanto, la tabla no está en segunda forma normal. Hay que definir dos tablas:
clientes y pedidos.
Tercera forma normal: se dice que una tabla está en tercera forma normal si está en segunda
forma normal y no existe dependencia funcional entre dos columnas no claves.
Por ejemplo, si se añaden las columnas Tratamiento y Sexo a la tabla de los clientes:
En este caso se puede decir que existe una dependencia funcional entre el sexo y el
tratamiento. Efectivamente, el hecho de conocer el tratamiento (Sr. Sra. o Srta.) permite
deducir el sexo. La tabla de los clientes no respeta por tanto la tercera forma normal. Se
define la tabla de los tratamientos para obtener el esquema siguiente:
El modelo relacional
La organización de los datos en el Sistema de Gestión de Bases de Datos Relacionales
(SGBDR o RBDMS en inglés) se basa completamente en el modelo relacional. Este
modelo fue desarrollado por Edgar Franck Codd con el apoyo de IBM en los años 70.
Además de este modelo, se creó también un álgebra (el álgebra relacional) para extraer los
datos almacenados en este modelo. La comprensión de este modelo y de su álgebra permite
abordar el aprendizaje de SQL de forma cómoda, porque se trata simplemente de trasladar
los conceptos teóricos a líneas de comandos. Este trabajo permitirá además adaptarse con
mucha mayor facilidad a los diferentes perfeccionamientos que puede sufrir SQL en las
distintas versiones.
El hecho de que los SGBDR respeten el modelo relacional lleva a trabajar con una
estructura lógica de organización de los datos (tablas, vistas, índices…) que es
independiente de la estructura física (ficheros…). Es tarea de cada SGBDR proporcionar
una visión lógica al usuario mientras garantiza el almacenamiento físico de los datos.
Esta limitación es también la ventaja de los SGBDR, porque la administración de los datos
desde un punto de vista lógico es una gran facilidad de utilización. De esta forma, los
usuarios poco o nada acostumbrados a programar aplicaciones pueden iniciarse sin
dificultades en el SQL.
1. Conceptos y definiciones
Dominio
Cardinal
Ejemplo
El diccionario de los datos del análisis de una gestión comercial puede comportar, entre
otras cosas, especificaciones sobre la gestión de los estados de los pedidos o la
visualización de números de orden.
Ejemplo
Si se quiere gestionar dos dominios (codigos y tasas), se podrá obtener pares compuestos
por un código y una tasa.
Códigos = {1,2,3,4}
Tasa de IVA = {0,7,16}
Códigos X Tasa de IVA ={(1,0),(1,7),(1,16),
(2,0),(2,7),(2,16),(3,0),(3,7),(3,16),
(4,0),(4,7),(4,16)}
Relación
Una relación definida en los dominios D1, D2,... , Dn es un subconjunto del producto
cartesiano de esos dominios caracterizado por un nombre.
Atributo
Grado
Ejemplo
Para asociar una sola tasa por código, sólo se requieren tres pares.
o en detalle:
2. Reglas principales
Se aplican reglas a esta relación para respetar las restricciones vinculadas al análisis.
Coherencia
Todo valor tomado por un atributo debe pertenecer al dominio en el cual está definido.
Unicidad
Identificador
Atributo o conjunto de atributos que permiten caracterizar de manera única cada elemento
de la relación.
Clave principal
Claves secundarias
Integridad referencial
Esta regla impone que un atributo o un grupo de atributos de una tabla aparezca como clave
principal en otra relación.
Clave externa
Ejemplo
El análisis de una gestión comercial implica gestionar clientes que tengan unas
características (Nombre, Dirección) y los pedidos que efectúan dichos clientes.
CLIENTES (NUMCLI,NOMCLI,DIRCLI)
NUMCLI identificador clave principal de CLIENTES
NOMCLI,DIRCLI identificador clave secundaria de CLIENTES
PEDIDOS (NUMPDO,FECHAPDO,NUMCLI,ESTADOPDO)
NUMPDO identificador clave principal de PEDIDOS
NUMCLI clave externa de PEDIDOS, que referencia
NUMCLI de CLIENTES
Valor nulo
Restricción de entidad
Todo valor que corresponde a una clave principal debe ser no NULL.
Ejemplo
En la relación artículo, se puede admitir que el precio o la tasa de IVA sean desconocidos,
pero debe consignarse la referencia del artículo (clave principal).
El álgebra relacional
Es un método de extracción que permite la manipulación de las tablas y de las columnas.
Su principio se basa en la creación de nuevas tablas (tablas resultantes) a partir de las tablas
existentes; estas nuevas tablas se convierten en objetos inmediatamente utilizables.
Los operadores del álgebra relacional que permiten crear las tablas resultantes se basan en
la teoría de conjuntos.
1. Operadores
Unión
La unión entre dos relaciones de misma estructura (grado y dominios) proporciona una
tabla resultante de misma estructura que tiene como elementos el conjunto de los elementos
distintos de dos relaciones iniciales.
Notación: Rx = R1 ∪ R2
Ejemplos
CLIENTES=CLIESTE ∪ CLICENTRO
Intersección
La intersección entre dos relaciones de misma estructura (grado y dominios) da una tabla
resultante de misma estructura que tiene como elementos el conjunto de los elementos
comunes a ambas relaciones iniciales.
Notación: Rx = R1 ∩ R2
Ejemplo
CLICOMUN=CLIESTE ∩ CLICENTRO
Diferencia
La diferencia entre dos relaciones de misma estructura (grado y dominios) da una tabla
resultante de misma estructura que tiene como elementos el conjunto de los elementos de la
primera relación que no están en la segunda.
Notación: Rx = R1 - R2
Ejemplo
CLIESTESOLO=CLIESTE - CLICENTRO
División
La división entre dos relaciones es posible a condición de que la relación divisora esté
totalmente incluida en la relación dividendo. El cociente de la división corresponde a la
información que esté presente en el dividendo y no en el divisor. Otra forma de definir la
división es la siguiente: Sean R1 y R2 dos relaciones tales que R2 se encuentra totalmente
incluida en R1.
El cociente R1†R2 está constituido por tuplas t tales que para todas las tuplas t‟ definidas
en R2 existe una tupla t.t‟ definida en R1.
Notación: Rx=R1÷R2
Ejemplo:
La restricción según una condición produce, a partir de una relación, una relación de mismo
esquema que sólo contiene los elementos de la relación inicial que cumplen la condición.
Notación: Rx = σ (condición) R1
operador
valor
Ejemplos
Clientes de BARCELONA:
CLI08=σ(DIRECCION="BARCELONA")CLIESTE
ART1=σ(REFART>="AB" Y REFART<"AC")ARTICULOS
ART2=σ(PRECIO<20000)ART1
Proyección
La proyección de una relación sobre un grupo de atributos da una relación resultante que
tiene como esquema solamente esos atributos, y como elementos los n-uplos distintos
compuestos por los valores asociados a esos atributos.
Ejemplo
Pedidos y estados del pedido:
PDO= π PEDIDOS(NUMPDO,NUMCLI,ESTADOPDO)
CLIPDO1= π PEDIDOS(NUMCLI)
CLIPDO2= π PEDIDOS(NUMCLI,ESTADOPDO)
Producto cartesiano
El producto cartesiano entre dos relaciones produce una relación que tiene como esquema
todos los atributos de ambas relaciones existentes y como elementos, la asociación de cada
fila de la primera tabla con cada fila de la segunda.
Notación: Rx = S1 X S2
Ejemplo
Combinaciones
La combinación (join) de dos relaciones según una condición se produce por la restricción
sobre el producto cartesiano.
Ejemplo
Join natural
Cálculos elementales
Proyección sobre una relación asociada a un cálculo sobre cada fila para crear uno o varios
atributos nuevos. Notación: Rx = π S (A1...N1 = expresión calculada...)
Ejemplo
LINPDOVALO = π LINPDO(NUMPDO,NUMLIN,REFART,
VALOLIN=CTDADPDO*PRECIOUNIT)
Cálculo de agregados
Proyección sobre una relación asociada a uno o varios cálculos estadísticos basados en un
atributo para todos los elementos de la relación o del agrupamiento vinculado a la
proyección, con el fin de crear uno o varios atributos nuevos.
número de filas.
COUNT (atributo)
SUM (atributo)
AVG (atributo)
MAX (atributo)
MIN (atributo)
Ejemplo
TOTCLI=π CLIENTES(N=COUNT(*))
PDOVALO=π LINPDOVALO(NUMPDO,TOTPDO=SUM(VALOLIN))
Los precios más elevados, los menos elevados y promedio de los precios por categoría de
artículos:
STATART=π ARTICULOS(CATEGORIA,MASCARO=
MAX(PRECIO),MENOSCARO=MIN(PRECIO),
PROMEDIO=AVG(PRECIO))
2. Etapas de la resolución de un problema
Establecer la "vista"
La vista es una relación intermedia que contiene todos los atributos que permiten realizar la
extracción, con sus relaciones de origen, sus clases de utilidad y las operaciones que se
deben aplicar.
Clases de atributo
Caso general
1.
Relaciones pertinentes.
2.
3.
Combinaciones, Productos cartesianos, Uniones, Intersecciones, Diferencias (para asociar las filas
restantes).
4.
Cálculos elementales (para crear las nuevas columnas).
5.
6.
Join entre la tabla obtenida en Cálculos de agregados y la tabla inicial en Cálculos elementales
(para añadir las columnas estadísticas a las demás).
7.
Repetir las etapas del Cálculos de agregados para los otros agrupamientos.
8.
9.
10.
La tabla CLIENTES contiene una fila por cliente, con todas las características para poder
contactar con el cliente o mandarle correo.
Restricciones:
Restricciones:
Esta tabla debe contener una fila por artículo, sus características, especialmente su precio, y
la categoría a la que pertenece.
Restricciones:
PRECIOUNIT_ART positivo.
La empresa dispone de varios almacenes en España, que pueden distribuir el material. Debe
poder administrarse la cantidad de artículos por almacén, al igual que los valores límite de
las cantidades almacenadas.
Restricciones:
Restricciones:
NUMERO_PDO clave principal, los números deben asignarse por orden de creación.
ESTADO_PDO sólo puede tomar los valores: EC (en curso), PE (parcialmente entregado),
EN (entregado), SA (saldado).
Cada pedido tiene al menos una fila artículo con la cantidad solicitada.
Restricciones:
Restricciones:
T1= (NUMERO_PDO=1301)PEDIDOS
NUMERO_PD FECHA_PD TASA_DESCUENT NUMERO_CL ESTADO_PD
T1
O O O I O
1301 08/02/2001 0 15 EC
PRECI
NUME REFERE CTDA DESIGNAC
O
T RO FECHA_ APELLID DIRECC NCIA D_ ION_ IMPO
5 PDO O ION RTE
UNIT_
_PDO _ART PDO ART
ART
08/02/20 FERNAN MOSTO BICICLET
1301 AB03 3 70000 210000
01 DEZ LES A
08/02/20 FERNAN MOSTO
1301 AB22 1 CASCO 4000 4000
01 DEZ LES
T6=π T5(BASEIMP=SUM(IMPORTE))
T6 BASEIMP
214000
T7=T5xT6
CTD PRECI
NUM FEC REFEREN DESIGNA
AD O-
T ERO HA_ APELLI DIREC CIA_ CION IMPO BASEI
7 DO CION RTE MP
_PD UNIT_
_PDO PDO ART _ART
O ART
08/02 FERNA MOSTO BICICLET 21000 21400
1301 AB03 3 70000
/01 NDEZ LES A 0 0
08/02 FERNA MOSTO 21400
1301 AB22 1 CASCO 4000 4000
/01 NDEZ LES 0
Bases de datos OLTP (OnLine Transaction Processing), es decir, bases de datos que
soportan transacciones de usuarios. Este es el tipo de base de datos que se encuentra
en producción. Sus principales características son que, a pesar de su gran volumen
de datos y su elevado número de usuarios conectados, el tiempo de respuesta debe
ser óptimo. Por suerte, los usuarios trabajan con transacciones cortas, y cada
transacción manipula una cantidad de datos reducida.
Bases de datos OLAP (On-Line Analytical Processing), es decir, bases de datos que
permiten almacenar un número máximo de datos para atender consultas de ayuda a
la toma de decisiones. Este tipo de bases de datos no se aborda en este libro.
Bases de datos de tipo snapshot, que son duplicaciones más o menos completas de
la base de origen destinadas a acceder rápidamente a datos remotos, por ejemplo.
Este tipo de base de datos no se aborda en este libro.
Este libro solamente aborda las bases de datos de usuario. La gestión de bases de datos de sistema
no entra en el ámbito de esta obra.
SQL Server utiliza una serie de archivos para almacenar el conjunto de la información
relativa a una base de datos.
Archivo primario
Sólo existe uno por base de datos: es el punto de entrada. Este archivo lleva la extensión
*.mdf.
Archivos secundarios
Archivos de registro
Estos archivos (puede haber varios) contienen el registro de las transacciones y llevan la
extensión *.ldf.
Los grupos de archivos
Los archivos de datos se dividen en páginas de 8 KB. Los datos se almacenan en el interior
de las páginas; así, el tamaño máximo de una línea es de 8.060 bytes excepto los tipos text e
image. Este tamaño de 8 KB permite:
Estas páginas se agrupan en extensiones. Las extensiones están constituidas por ocho
páginas contiguas (64 KB). Representan la unidad de asignación de espacio para las tablas
y los índices. Para evitar la pérdida de espacio en disco, existen dos tipos de extensiones:
Uniforme
Mixta
Cuando se crea una tabla, las páginas se asignan en una extensión mixta. Cuando los datos
representan ocho páginas se asigna una extensión uniforme a la tabla.
La persona que crea la base de datos debe disponer de derechos suficientes y se convierte
en propietario de ella. SQL Server es capaz de administrar 32.767 bases de datos.
Los archivos que constituyen una base de datos no deben situarse en un sistema de archivos
comprimido o en un directorio compartido en red.
Al crearlos, los archivos se inicializan con ceros para borrar todos los datos existentes. Esta
operación conlleva una sobrecarga de trabajo pero permite optimizar los tiempos de
respuesta cuando la base de datos está trabajando.
Es posible asignar espacio en disco a la base sin que sea inicializada. Esta operación se
identifica mediante el término inicialización instantánea. Los datos anteriormente
presentados en el disco son borrados en función de las necesidades de la base.
SQL Server es capaz de utilizar particiones sin procesar para la creación de los archivos de
bases de datos. Sin embargo, en la gran mayoría de casos, el método preferible es el de
crear los archivos en una partición NTFS o FAT.
Los archivos creados en particiones NTFS soportan sin problemas la compresión NTFS y
eventualmente algunos grupos de archivos pueden ser posicionados en modo sólo lectura.
Estas consideraciones sólo se aplican a las bases de datos de usuario y no se pueden aplicar
a los archivos relativos a las bases de datos de sistema.
a. Creación de la base de datos
Para crear una base de datos, es necesario estar conectado como administrador del sistema
o tener el permiso para utilizar CREATE DATABASE y situarse en la base de datos de
sistema master .
El objeto DATABASE debe crearse en primer lugar. Una base de datos contiene todos los
demás objetos.
El nombre de la base de datos debe ser único en una instancia SQL Server. Este nombre
está limitado a 128 caracteres, respetando las reglas de construcción de identificadores. Esta
longitud máxima está reducida a 123 caracteres si el nombre del registro de transacciones
no se especifica en el momento de crear la base.
Sintaxis
NAME
FILENAME
SIZE
MAXSIZE
Tamaño máximo del archivo indicado en kilobytes o megabytes (por defecto, megabytes).
Si no se indica ningún valor, el tamaño del archivo estará limitado por el espacio libre en
disco.
UNLIMITED
FILEGROWTH
Precisa la tasa de incremento para el tamaño del archivo, que no podrá sobrepasar nunca el
valor máximo. Este paso puede precisarse en porcentaje o de forma estática, en kilobytes o
megabytes. Las extensiones poseen un tamaño de 64 KB; éste es, pues, el valor mínimo de
la tasa de incremento que se puede indicar.
LOG ON
COLLATE
FOR ATTACH
Para crear una base utilizando archivos ya creados. Esta petición es útil cuando la base se
crea con más de 16 archivos.
FOR ATTACH_REBUILD_LOG
Con esta opción se puede crear la base de datos adjuntando a ella los archivos de datos
(mdf y ndf), pero no necesariamente los de registro. Éstos últimos se reconstruirán con
valor nulo. Si una base de se adjunta de esta forma, es importante efectuar lo antes posible
una copia de seguridad completa y planificar todos los procesos de backup. No se puede
confiar en las copias de seguridad realizadas antes de adjuntar la base de datos, ya que las
secuencias de registro no corresponderán a la realidad.
Ejemplo
En esta ventana de diálogo podrá definir las distintas opciones de creación de la base de
datos.
b. Modificación de tamaño
Ejemplo
Ejemplo
Adición de un segundo archivo a la base GESCOM:
El comando ALTER DATABASE permite una acción mucho más importante sobre la base
de datos que la simple modificación del tamaño de los archivos. También es posible añadir
o eliminar archivos y grupos de archivos, cambiar el nombre de la base de datos,
especificar el modo de finalización predeterminado de las transacciones en curso y cambiar
la intercalación de la base de datos.
Para conocer las distintas intercalaciones disponibles en el servidor, debe ejecutar la consulta
siguiente: SELECT * FROM ::fn_helpcollations ()
El ajuste del tamaño de los archivos siempre comienza a partir del final. Por ejemplo, si la
base de datos dispone de un archivo de 500 MB que se desea reducir a un tamaño de 400
MB, serán los últimos 100 MB del fichero los que serán reorganizados antes de la
liberación del espacio para evitar el bloqueo de datos.
La cantidad de espacio que en realidad se libera está en función del tamaño ideal fijado por
el parámetro en DBCC SHRINKFILE y los datos reales. Si el archivo del ejemplo anterior
contiene 450 MB utilizados, sólo se liberarán 50 MB.
Sintaxis
DBCC SHRINKFILE
Reduce el tamaño del archivo de datos o del registro de transacciones para la base de datos
especificada.
DBCC SHRINKDATABASE
Reduce el tamaño de los archivos de datos en la base de datos especificada.
nuevo_tamaño
nuevo_tamaño%
Indica el porcentaje de espacio libre que deseamos obtener en el archivo de datos después
de la reducción de la base.
EMPTYFILE
Permite solicitar al comando DBCC_SHRINKFILE que transfiera todos los datos presentes
en ese archivo de datos a otro archivo del mismo grupo. Una vez vacío, el archivo podrá
eliminarse por medio de un comando ALTER DATABASE.
NOTRUNCATE
Reorganiza el archivo situando las páginas ocupadas en la parte superior del mismo, pero
no disminuye su tamaño.
TRUNCATEONLY
El comando DROP DATABASE permite eliminar la base de datos. Los archivos físicos
también se suprimen.
La instrucción DROP DATABASE sólo puede ser ejecutada si está activado el modo
autocommit (está activado de forma predeterminada). No es posible eliminar las bases de
datos del sistema.
Se puede renombrar una base de datos por medio de la instrucción ALTER DATABASE.
Sintaxis
Se puede configurar una base de datos para fijar cierto número de opciones y así lograr que
el comportamiento de la base de datos cubra las necesidades de los usuarios. Para ello se
debe acceder a las opciones en cuestión a través de la interfaz gráfica de SQL Server
Management Studio , seleccionar la base de datos y abriendo la ventana de propiedades con
la tecla [F4]; también se puede hacer a través del menú contextual asociado a la base de
datos, o bien por el menú Ver - Ventana propiedades en el menú general de SQL Server
Management Studio.
Hasta ahora, SQL Server utilizaba el procedimiento almacenado sp_dboption para definir las
opciones de configuración de la base. Este procedimiento todavía existe en SQL Server 2008, pero
solamente para conservar la compatibilidad de los scripts existentes. El procedimiento
sp_dboption dejará de existir en las versiones futuras de SQL Server. Es necesario utilizar la
instrucción ALTER DATABASE o bien el procedimiento almacenado sp_replicationdboption cuando
las opciones están asociadas a la replicación.
Sintaxis
ONLINE
OFFLINE
Permite hacer inaccesible la base de datos, que queda detenida y cerrada correctamente. No
es posible realizar operaciones de mantenimiento en una base de datos offline.
EMERGENCY
La base de datos está en modo de sólo lectura, los registros están deshabilitados y su acceso
queda limitado a los administradores del servidor.
Acceso
SINGLE_USER
RESTRICTED_USER
Solo los miembros con función fija db_owner, dbcreator o sysadmin pueden conectarse a la
base de datos.
MULTI_USER
Es el modo predeterminado, que permite que todos los usuarios con privilegios suficientes
accedan a la información.
Operaciones posibles
READ_ONLY
READ_WRITE
Acceso
Configuración
ANSI_NULL_DEFAULT
Define el valor por defecto de la restricción de nulidad de columna. Según la norma ANSI,
una columna puede ser NULL por defecto.
RECURSIVE_TRIGGERS
TORN_PAGE_DETECTION
La base se detiene y los recursos se liberan tras la desconexión del último usuario.
AUTO_SHRINK
AUTO_CREATE_STATISTICS
Todas las estadísticas que falten en la optimización de una consulta se crean. Esta opción
está habilitada (en ON) de forma predeterminada.
AUTO_UPDATE_STATISTICS
Todas las estadísticas obsoletas para la correcta optimización de una consulta se recalculan.
AUTO_UPDATE_STATISTICS_ASYNC
QUOTED_IDENTIFIERS
ANSI_NULLS
Si el parámetro es verdadero (true), todas las comparaciones con un valor NULL se evalúan
como NULL. Si el parámetro es falso (false), todas las comparaciones con los valores
NULL y los valores no unicode se evalúan como TRUE si ambos valores son NULL.
ANSI_WARNINGS
ARITHABORT
CONTACT_NULL_YIELDS_NULL
El resultado es NULL si uno de los dos operandos de una operación de concatenación es
NULL.
CURSOR_CLOSE_ON_COMMIT
Permite cerrar todos los cursores cuando se define una transacción o al finalizar una
transacción.
CURSOR_DEFAULT
NUMERIC_ROUNDABORT
RECOVERY
PAGE_VERIFY
Esta opción permite validar la calidad de los datos almacenados a nivel de cada página. La
opción predeterminada CHECKSUM es la recomendada por SQL Server.
SUPPLEMENTAL_LOGGING
Al ajustar esta opción en ON (de forma predeterminada está en OFF), se agregarán datos
complementarios al registro de transacciones. Se puede conocer el estado de esta opción
examinando su valor en la columna is_supplemental_logging_enabled de la vista
sys.databases.
PARAMETERIZATION
Gestión de transacciones
NO_WAIT
ANSI_PADDING
Permite especificar si los espacios situados a la derecha sobre los datos de tipo carácter
deben ser eliminados o no.
COMPATIBILITY
Permite fijar el nivel de compatibilidad de la base de datos: 80 para SQL Server 2000, 90
para SQL Server 2005 y 100 para SQL Server 2008.
DATE_CORRELATION_OPTIMISATION
Con esta opción SQL se encarga de mantener la correlación de las estadísticas entre dos
tablas vinculadas por una limitación de clave externa y que poseen una columna de tipo
datetime.
Acceso externo
DB_CHAINING
TRUSTWORTHY
Service Broker
ENABLE_BROKER
DISABLE_BROKER
Permite precisar que la base necesita recibir un nuevo identificador Service Broker.
ERROR_BROKER_CONVERSATIONS
ALLOW_SNAPSHOT_ISOLATION
Cuando está activado este modo, todas las transacciones pueden trabajar con una captura
instantánea (snapshot) de la base tal como estaba al comienzo de la transacción.
READ_COMMITTED_SNAPSHOT
Cuando está activado este modo, todas las instrucciones ven los datos tal como estaban al
comienzo de la instrucción.
Todos los elementos creados en SQL Server se identifican perfectamente por su nombre,
que se utiliza como identificador. Efectivamente, dos objetos del mismo tipo no pueden
tener el mismo nombre si están definidos en el mismo nivel. Por ejemplo, en una instancia
de SQL Server, no es posible tener dos bases de datos con el mismo nombre, pero sí es
posible si las bases están definidas en dos instancias distintas de SQL Server. De igual
manera, en una base de datos, no es posible tener dos tablas con el mismo nombre. El
identificador es el que permite manejar los objetos a través de SQL. Por eso es importante
definir correctamente estos identificadores.
Los identificadores se componen de entre 1 y 128 caracteres. Comienzan siempre por una
letra o uno de los caracteres siguientes: _, @, #.
Los caracteres siguientes tienen que ser caracteres alfanuméricos. Obviamente no puede
haber identificadores que sean palabras clave de Transact SQL.
Ejemplo:
ENIEdiciones, RecursosInformáticos
Los identificadores delimitados
Ejemplo:
En el momento de definir una columna, se precisará el formato de uso del dato y el modo
de almacenamiento por el tipo de la columna.
Estos tipos están disponibles para todas las bases de datos de modo estándar.
Caracteres
char[(n)]
varchar(n|max)
nchar[(n)]
nvarchar (n|max)
Cadena de un máximo de 4.000 caracteres unicode. Si se precisa max, la variable puede
contener hasta 231 bytes de datos de tipo texto.
El tipo sysname , que aparece cuando trabajamos con las tablas del sistema, se utiliza para
referenciar los nombres de objetos. Este tipo es idéntico a un nvarchar(128) con la particularidad
de que están prohibidos los valores null.
Numéricos
decimal [(p[,d])]
numeric [(p[,d])]
Idéntico a decimal. Para el tipo decimal, la precisión podrá ser a veces más grande que la
requerida.
Bigint
Tipo de datos entero codificado en 8 bytes. Los valores almacenados en este tipo de datos
están comprendidos entre -263(-9.223.372.036.854. 775.808) y 263-
1(9.223.372.036.854.775. 807).
int
Número entero entre -231 (-2147783648) y +231 (+2147483647). El tipo de datos int es
específico de SQL Server y su sinónimo integer es compatible con ISO.
smallint
tinyint
Número entero positivo entre 0 y 255.
float[(n)]
real
Idéntico a float(24).
money
smallmoney
Binarios
binary[(n)]
varbinary (n|max)
Dato binario de longitud variable de n bytes (1 a 8000). La opción max permite reservar un
espacio máximo de 231 bytes.
binary varying
Idéntico a varbinary.
Fecha
Para la administración de los datos de tipo fecha y hora SQL Server 2008 propone nuevos
tipos de datos para optimizar el almacenamiento de los datos. Estos nuevos tipos de datos
se introducen para mejorar la administración de los datos de los tipos fecha y hora. En
primer lugar, existen tipos específicos para almacenar los datos de tipo hora y otros para
almacenar los datos de tipo fecha. Esta separación es beneficiosa porque permite dar más
precisión a la vez que se limita el espacio utilizado por los datos de uno u otro tipo. Por
ejemplo, ¿es necesario conservar datos de tipo horas, minutos y segundos cuando sólo hace
falta conservar la fecha de nacimiento de un cliente? Sin duda, no. El simple hecho de
conservar estos datos puede producir errores porque se van a realizar cálculos. Por tanto, es
más razonable y más rentable adoptar para este dato un tipo que sólo conserve la fecha.
Estos nuevos tipos de datos, para los datos de tipo fecha y de tipo hora, permiten
igualmente una mejor compatibilidad con el resto de sistemas de gestión de datos y facilitan
las operaciones de recuperación de datos.
SQL Server ofrece la posibilidad con los tipos datetime2 y datetimeoffset de conservar
datos de tipo fecha y hora de manera simultánea.
El tipo datetimeoffset permite no sólo almacenar datos de tipo fecha y hora con una
precisión de hasta 100 nanosegundos, sino que además conserva la hora en formato UTC y
la diferencia (en número de horas) entre esta hora UTC y la zona horaria desde la que
trabaja el usuario que introduce los datos en la base.
Los tipos datetime y smalldatetime están siempre presentes en SQL Server, pero es preferible
utilizar los tipos time, date, datetime2 y datetimeoffset en las nuevas programaciones, ya que
ofrecen mayor precisión y un mejor respeto de los estándares SQL.
datetime
smalldatetime
Fecha y hora almacenados en 4 bytes. Las fechas se gestionan del 1 de enero de 1900 al 6
de junio de 2079, con una precisión de un minuto.
datetime2
Más preciso que el tipo datetime, permite almacenar un dato de tipo fecha y hora
comprendido entre el 01/01/0001 y el 31/12/9999 con una precisión de 100 nanosegundos.
datetimeoffset
date
Permite almacenar una fecha comprendida entre el 01/01/0001 y el 31/12/9999 con una
precisión de un día.
time
Permite almacenar un dato positivo de tipo hora inferior a 24:00 h con una precisión de 100
nanosegundos.
Especiales
bit
timestamp
uniqueidentifier
sql_variant
El tipo de datos sql_variant permite almacenar cualquier tipo de datos, exceptuando datos
de tipo text, ntext, timestamp y sql_variant. Si una columna utiliza este tipo de datos, las
distintas filas de la tabla pueden almacenar, en dicha columna, datos de tipos diferentes.
Una columna de tipo sql_variant puede poseer una longitud máxima de 8.016 bytes. Antes
de utilizar un valor almacenado en formato sql_variant en una operación, es necesario
convertir los datos a su formato original. Las columnas que utilizan el tipo sql_variant
pueden participar en restricciones de claves primarias, de claves externas o de unicidad,
pero los datos contenidos en la clave de una fila no pueden exceder los 900 bytes (límite
impuesto por los índices). sql_variant no puede ser utilizado por las funciones
CONTAINSTABLE y FREETEXTABLE.
table
Es un tipo de dato particular, que permite almacenar y reenviar un conjunto de valores con
vistas a una utilización futura. El modo principal de uso de este tipo de datos es la creación
de una tabla temporal.
xml
Este tipo permite almacenar un documento xml en una columna de una tabla relacional.
Los tipos text, ntext e images se mantienen por motivos de compatibilidad. Es muy preferible
utilizar varchar(max) y varbinary(max).
SQL Server propone asimismo un cierto número de sinónimos de sus propios tipos de base.
Los sinónimos existen con frecuencia para asegurar la compatibilidad con la norma ISO.
Se pueden definir tipos de datos propios a través de Management Studio o del comando
CREATE TYPE.
Los procedimientos almacenados sp_addtype y sp_droptype se mantienen por motivos de
compatibilidad. Microsoft recomienda no utilizarlos más, ya que indudablemente no estarán
presentes en las siguientes versiones de SQL Server.
Sintaxis (creación)
Se puede definir un tipo de datos a partir de la definición de una clase. Esta opción está
ligada a la integración de CLR en SQL Server. Veremos esta integración más adelante en
este libro.
Sintaxis (eliminación)
Para definir un tipo de datos que basado en un tipo de CLR, hay que habilitar CLR por medio de
sp_dboption.
Será imposible suprimir un tipo si éste se utiliza en una tabla de la base de datos en la que
ha sido creado.
Ejemplos
Creación de un tipo para columnas como nombre cliente, nombre proveedor, etc.:
Pedir la creación de un nuevo tipo de datos desde el SQL Server Management Studio:
La instrucción CREATE TYPE permite así crear tipos denominados muy característicos,
porque las restricciones de integridad permiten una definición más precisa del formato
posible de los datos.
Sintaxis
nombreTipo
columna
tipoColumna
Tipo de datos Transact SQL sobre el cual está definida la columna. No todas las columnas
de un mismo tipo de tabla están necesariamente definidas sobre el mismo tipo ni con la
misma precisión.
restinteColumna
Ejemplo
En el ejemplo siguiente se define un tipo que representa a un individuo. Este tipo está
compuesto por los campos estado civil, apellido y nombre. Para el campo estado civil sólo
están permitidos ciertos valores.
Una tabla representa una estructura lógica donde se ordenan los datos. Para permitir una
buena organización de la información, cada tabla está compuesta por columnas para poder
estructurar los datos. Cada columna está perfectamente identificada por su nombre, que es
único dentro de cada tabla, y por su tipo de datos. Los datos se distribuyen entre varias
tablas. Las limitaciones de integridad permiten garantizar la coherencia de los datos.
a. Creación de tabla
La etapa de creación de las tablas es una etapa importante del diseño de la base porque los
datos se organizan en relación a las tablas. Esta operación es puntual y en general la realiza
el administrador (DBA: DataBase Administrator) o por lo menos la persona encargada de
administrar la base.
La creación de una tabla permite definir las columnas (nombre y tipo de datos) que la
componen, así como las restricciones de integridad. También es posible definir columnas
calculadas, un criterio de ordenación específico y el destino de los datos de tipo text, ntext o
image.
Sintaxis
nombreEsquema
nombre_tabla
Nombre de la columna, que debe ser único en la tabla. Puede haber 250 columnas por tabla.
tipocolumna
restricciones
grupoarchivo
AS expresión_calculada
Es posible definir una regla de cálculo para las columnas que contienen datos calculados.
Por supuesto, únicamente podrá accederse a estas columnas en modo sólo lectura, y no es
posible insertar datos o actualizar los datos de una columna de este tipo.
TEXTIMAGE_ON
Permite especificar el grupo de archivos de destino para los datos de tipo text, ntext e
image.
El número máximo de columnas por tabla es 1.024. La longitud máxima de una línea es de 8.060
bytes (sin contar los datos texto o imagen).
Ejemplos
Presentación de los datos de la tabla por medio del procedimiento almacenador sp_help:
Sintaxis
nombreEsquema
WITH NOCHECK
Permite establecer una restricción de integridad en la tabla sin que dicha restricción se
compruebe para las filas ya existentes en la misma.
COLLATE
CHECK, NOCHECK
ENABLE, DISABLE
Permiten activar y desactivar la ejecución de desencadenadores asociados a la tabla.
Ejemplo
La eliminación de una base implica la eliminación de todos los datos existentes en la tabla.
También se eliminan los desencadenadores y los índices asociados a la tabla. Ocurre lo
mismo para los permisos de utilización de la tabla. Por el contrario, la eliminación de la
tabla no afecta a las vistas, los procedimientos y las funciones que hacen referencia a la
tabla. Si hacen referencia a la tabla eliminada, aparecerá un error en la próxima ejecución.
Sintaxis
La eliminación de una tabla eliminará los datos y los índices asociados. La eliminación no
será posible si la tabla es referenciada por una clave externa .
nombreBase.nombreEsquema.nombreObjeto
Sin embargo, como habitualmente los objetos referenciados están presentes en la base
actual, es posible omitir el nombre de la base.
También es posible no especificar el nombre del esquema. En este caso, el motor de base de
datos buscará el objeto en el esquema asociado al usuario y si esta búsqueda resulta
infructuosa buscará en el esquema dbo.
La integridad de los datos traduce las reglas del modelo relacional, regla de coherencia
(integridad de dominio), existencia de valores nulos, regla de unicidad (integridad de
entidad) y claves externas (integridad referencial).
Desde SQL Server 2005, los objetos DEFAULT ya no tienen validez y no deben ser
utilizados en nuevos desarrollos. En efecto, este tipo de objeto no cumple la norma SQL.
2. Reglas
Para que la gestión de los distintos elementos de la base sea más uniforme (con la
generalización de las instrucciones CREATE, ALTER y DROP) y para acercarse más a la
norma, SQL Server 2008 ya no ofrece gestión de reglas como objeto independiente. Las
restricciones de integridad que antes podían expresarse en forma de regla deben definirse
cuando se crea la tabla con la instrucción CREATE TABLE. También se pueden agregar o
quitar de una tabla existente con la instrucción ALTER TABLE.
Esta propiedad puede ser asignada a una columna numérica entera, durante la creación o la
modificación de la tabla, y permite que el sistema genere valores para esta columna. Los
valores serán generados en la creación de la fila, sucesivamente y partiendo del valor inicial
especificado (por defecto, 1), y aumentando o disminuyendo fila tras fila en un incremento
(por defecto, 1).
Sintaxis
La propiedad IDENTITY debe ser definida al mismo tiempo que la columna a la que está vinculada.
La definición de una columna identity puede realizarse en un comando CREATE TABLE o también
en un comando ALTER TABLE.
Ejemplo
La palabra clave IDENTITYCOL podrá utilizarse en una cláusula WHERE en lugar del
nombre de columna.
La variable global @@IDENTITY almacena el último valor afectado por una identidad a lo
largo de la sesión actual. La función SCOPE_IDENTITY permite realizar el mismo tipo de
trabajo pero limita el alcance de la visibilidad en el único lote de instrucciones actual. La
función IDENT_CURRENT permite conocer el último valor identidad generado para la
tabla especificada en el parámetro, sean cuales sean las sesiones.
Ejemplo
En el siguiente ejemplo agregaremos una categoría nueva. La primera inserción se salda
con un error, ya que la propiedad IDENTITY está activa. Después de su desactivación por
la instrucción SET IDENTITY_INSERT categorias ON, se puede insertar la fila de datos.
Es posible definir la propiedad identity desde SQL Server Management Studio a través de
las pantallas de modificación o creación de una tabla (Diseño desde el menú contextual
asociado a la tabla).
Se pueden utilizar las siguientes funciones para obtener más información sobre los tipos de
identidad:
Todas estas funciones tienen el objetivo de permitir al programador que controle mejor el
valor generado y, así, poder recuperarlo cuando se trate de la clave principal.
Sintaxis
Se puede obtener información sobre las restricciones de integridad definidas: hay que
consultar sys.key_constraints o utilizar los procedimientos almacenados sp_help y
sp_helpconstraint.
a. NOT NULL
SQL Server considera la restricción de nulidad como una propiedad de columna; la sintaxis
es, pues:
NOT NULL
Es preferible especificar sistemáticamente NULL o NOT NULL , porque los valores por
defecto de esta propiedad dependen de muchos factores:
Desde SQL Server 2005 es posible modificar la restricción de NULL/NOT NULL con un
comando ALTER TABLE para una columna ya existente. Por supuesto, los datos ya
existentes en la tabla deben respetar las restricciones.
b. PRIMARYKEY
Esta restricción permite definir un identificador de clave principal, es decir, una o más
columnas que sólo aceptan valores únicos en la tabla (regla de unicidad o restricción de
entidad).
Sintaxis
nombrerestricción
Nombre que permite identificar la restricción en las tablas de sistema. Por defecto, SQL
Server dará un nombre difícil de manipular.
Esta restricción automáticamente creará un índice único, agrupado por defecto, con el nombre de
la restricción; de ahí las opciones NONCLUSTERED y FILLFACTOR. Una clave principal puede
contener hasta 16 columnas. No puede haber más de una clave principal por tabla. Las columnas
que la definen deben ser NOT NULL.
Ejemplos
Adición de la clave principal a la tabla LINEAS_PDO (un índice agrupado existe ya sobre
NUMERO_PDO):
c. UNIQUE
Esta restricción permite también traducir la regla de unicidad para las otras claves únicas de
la tabla o identificadores claves secundarios .
Esta restricción posee las mismas características que PRIMARY KEY, con dos
excepciones:
Cuando se agrega una restricción de unicidad a una tabla existente, SQL Server comprueba
que las filas ya presentes respeten esta restricción antes de validar su agregación.
La gestión de esta restricción queda garantizada por un índice de tipo UNIQUE. Este índice
no puede eliminarse con el comando DROP INDEX. Hay que eliminar la restricción por
medio de ALTER TABLE.
Sintaxis
[CONSTRAINT nombrerestricción] UNIQUE [CLUSTERED |NONCLUSTERED]
(nombrecolumna [,...]) [WITH FILLFACTOR=x] [ON grupo_archivos]
Ejemplo
d. REFERENCIAS
Esta restricción traduce la integridad referencial entre una clave externa de una tabla y una
clave primaria o secundaria de otra tabla.
Sintaxis
CONSTRAINT nombre_restricción
[FOREIGN KEY (columna[,_])]
REFERENCES tabla [ ( columna [ ,... ] ) ]
[ ON DELETE { CASCADE | NO ACTION | SET NULL | SET DEFAULT} ]
[ ON UPDATE { CASCADE | NO ACTION | SET NULL | SET DEFAULT} ]
La cláusula FOREIGN KEY es obligatoria cuando se utiliza una sintaxis de restricción de tabla para
agregar la restricción.
La opción de cascade permite especificar el comportamiento que debe adoptar SQL Server
cuando el usuario actualiza o intenta eliminar una columna a la que se hace referencia. Al
definir una restricción de referencia a través de las instrucciones CREATE TABLE o
ALTER TABLE, es posible especificar las cláusulas ON DELETE y ON UPDATE.
NO ACTION
Valor por defecto de estas opciones. Permite obtener un comportamiento idéntico al de las
versiones anteriores de SQL Server.
ON DELETE CASCADE
Permite especificar que, en caso de eliminación de una fila a cuya clave principal hagan
referencia una o varias filas, también se supriman todas las filas que contengan la clave
externa que hace referencia a la clave principal. Por ejemplo, con esta opción, la
eliminación de una fila de datos en la tabla de pedidos provoca la eliminación de todas las
filas de datos de la tabla lineas_pedido.
ON UPDATE CASCADE
Permite pedir a SQL Server que actualice los valores contenidos en las columnas de claves
externas cuando el valor de clave principal al que se hace referencia se actualiza.
SET NULL
SET DEFAULT
Aunque SQL Server no limite el número máximo de restricciones de clave externa que
puedan definirse para cada tabla, Microsoft recomienda no sobrepasar las 253. Este límite
debe respetarse en lo referente al número de claves externas definidas para la tabla y el
número de claves externas que hacen referencia a la tabla. Más allá de este límite puede ser
interesante revisar el diseño de la base de datos para conseguir un esquema más óptimo.
Ejemplo
e. DEFAULT
Se puede definir un valor predeterminado para todas las columnas con excepción de las
columnas de tipo timestamp o de las que poseen un tipo identity.
Sintaxis
Valor
El valor debe ser exactamente del mismo tipo que el valor sobre el cual está definida la
columna. Este valor puede ser una constante, una función escalar (como por ejemplo:
USER, CURRENT_USER, SESSION_USER, SYSTEM_USER...) o bien el valor NULL.
Ejemplo
f. CHECK
Sintaxis
Ejemplo
El objetivo de los índices es permitir un acceso más rápido a la información tanto para las
extracciones (SELECT) como para las actualizaciones (INSERT, UPDATE, DELETE), al
reducir el tiempo necesario para localizar la fila. No obstante, los índices resultarán
costosos en caso de actualización del valor contenido en la columna indexada.
Una buena estrategia de indexación debe tener en cuenta estas cuestiones, de las que se
pueden deducir dos reglas:
Es preferible tener demasiado poco índice que demasiados índices. En caso de que
haya múltiples índices, las ventanas de acceso a la información quedan anuladas por
el tiempo necesario para actualizar los índices.
Los índices deben ser lo más "grandes" posible para que puedan servir para
múltiples consultas.
En definitiva, hay que asegurarse de que las consultas utilicen bien los índices que están
definidos.
Las consultas también deben estar escritas para manipular la cantidad mínima de datos
posible de la forma más explícita posible. Por ejemplo, en caso de una proyección es
preferible listar las columnas para las que deba presentarse la información en lugar del
carácter genérico *. Para las restricciones es preferible hacer comparaciones entre
constantes y el valor contenido en una columna.
Por ejemplo, si la tabla de Artículos contiene el precio sin IVA de cada artículo, para
extraer la lista de artículos cuyo precio con IVA sea inferior o igual a 100 € será preferible
escribir la condición preciosiniva<= 100/1.16 en lugar de preciosiniva*1.16<=100. Con la
segunda, el cálculo se efectúa para cada artículo, mientras que en el primero se realiza una
sola vez para todos.
En el ejemplo anterior, todos los artículos utilizan un IVA del 16%.
También hay que tener en cuenta el hecho de que los datos se almacenan en los índices y,
por tanto, van a ocupar un espacio en disco no desdeñable. El nodo hoja del índice
agrupado contiene todos los datos. Para un índice no agrupado, el nodo hoja del índice
contiene una referencia directa a la fila de información asociada a la clave del índice. Los
demás nodos del índice se utilizan para navegar por éste y llegar de forma muy rápida a la
información.
Es posible agregar información a nivel de los nodos hoja del índice sin que éste tenga en
cuenta estas columnas. Esta técnica resulta práctica cuando la definición del índice cubre
las consultas. Pongamos, por ejemplo, que hay que extraer la lista de poblaciones y códigos
postales de la tabla de clientes. Para ella se ha definido un índice no agrupado en relación
con la columna de códigos postales, y la columna que representa el nombre de la población
se ha agregado a nivel de nodo hoja. Así, el índice cubre la consulta capaz de producir el
resultado sin necesidad de acceder a la tabla.
¿Qué es un índice?
El concepto de índice no es nada nuevo para nadie. Todos hemos utilizado el índice de un
libro para llegar directamente a la página o páginas donde se encuentra la información que
buscamos. Tal vez haya acudido usted al índice de este libro para localizar la explicación
que está leyendo en estos momentos sobre la palabra clave "índice".
Si para el índice sólo aparece un número de página detrás de cada palabra clave, se habla de
índice único.
Los índices que ofrece SQL Server son muy parecidos al de un libro.
Se puede recorrer todo el índice para encontrar todas las informaciones, de la misma forma
que se puede leer un libro a partir del índice, en lugar de seguir el orden que ofrece la tabla
de contenidos.
También es posible utilizar el índice para acceder directamente a una información concreta.
Con el fin de garantizar un tiempo homogéneo de acceso a la información, SQL Server
estructura la información en forma de árbol alrededor de la propiedad indexada. De esta
forma, para encontrar un dato en el índice se localiza primero el primer carácter y después
se continúa de forma secuencial hasta hallar la palabra clave buscada.
Imagine ahora un libro en el que pueda definir varios índices en función de palabras clave,
de temas, de tipos de manipulación que puedan desearse realizar... Esta multiplicidad de
índices es la que ofrece SQL Server con la posibilidad de crear distintos índices para una
misma tabla.
Entre todos los índices del libro, hay uno que estructura al volumen: la tabla de contenidos,
que puede verse como una especie de índice temático. De la misma forma, SQL Server
permite estructurar físicamente los datos con respecto a un índice: el índice CLUSTERED
o agrupado.
SQL Server ofrece dos tipos de índice: los agrupados (de los que cada tabla puede tener
sólo uno como máximo), que reorganizan físicamente la tabla, y los no agrupados.
Si una tabla posee únicamente este tipo de índice, todos los datos se almacenan sin seguir
ningún tipo de organización.
Esta solución da buenos resultados para indexar una tabla que no se encuentre presente en
un servidor OLTP (por ejemplo, uno que se dedique al análisis de información).
Índices agrupados
En cada tabla se puede definir un índice agrupado y sólo uno. Este tipo de índice permite
agrupar físicamente los datos de la tabla según un criterio concreto. Por ejemplo, puede
definirse un índice agrupado en función de la clave principal. La creación y la
reconstrucción de este tipo de índice resultan costosas para el servidor en tiempo y espacio
en disco. Si un índice de este tipo se define para una tabla que ya está llena de valores, su
construcción costará tiempo. Además, se tardará aún más en construirlo si ya existen
índices no agrupados. Idealmente, y a fin de evitar que el índice agrupado provoque un
mantenimiento excesivo, el índice estará definido según una columna que contenga datos
estáticos y ocupe un espacio limitado, como, por ejemplo, la clave principal.
La definición de un índice agrupado sobre una columna no estable, como el nombre de una
persona o su dirección, conduce irremediablemente a una degradación significativa del
rendimiento.
Índices no agrupados
Al trabajar con tablas voluminosas deben crearse índices para que las consultas se
resuelvan a través del índice y no de un barrido de toda la tabla. Este punto es
especialmente importante para los cálculos de agregado que requieren una operación de
selección antes de efectuar el cálculo. Si un índice permite limitar la selección a efectuar, se
obtiene una ganancia de rendimiento. Siguiendo esta óptica de optimización del
rendimiento en el acceso a datos, se pueden definir índices sobre las columnas de una vista,
aun si el resultado presente en la columna es el resultado de un cálculo de agregado.
El índice definido sobre una vista está limitado a 16 columnas y 900 bytes de datos para
cada entrada del índice. A diferencia de la inclusión de columnas no indexadas en las hojas
del índice, los índices definidos sobre una vista pueden contener el resultado de un cálculo
de agregado.
a. Creación de un índice
Sin embargo, en caso de que haya que importar los datos, es preferible importar los datos
en primer lugar y luego definir los índices. En el caso contrario (se definen los índices antes
de una importación masiva de datos), es necesario reconstruir los índices con el fin de
garantizar una distribución equilibrada de los datos en el índice.
Sintaxis
CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX nom_índice
ON { nombre_tabla | nombre_vista } ( columna [ ASC | DESC ] [ ,...n ])
[INCLUDE (columna[ ,...n])]
[ WITH [ PAD_INDEX = {ON | OFF} ]
[,FILLFACTOR = x]
[,IGNORE_DUP_KEY = {ON | OFF} ]
[,DROP_EXISTING = {ON | OFF} ]
[,ONLINE = {ON | OFF} ]
[,STATISTICS_NORECOMPUTE = {ON | OFF} ]
[,SORT_IN_TEMPDB = {ON | OFF} ]
[ ON grupo_archivo ]
UNIQUE
Especifica que la o las columnas indexadas no podrán tener el mismo valor en diversas filas
de la tabla.
CLUSTERED o NONCLUSTERED
Con un índice CLUSTERED (agrupado), el orden físico de las filas en las páginas de datos
es idéntico al orden del índice. Sólo puede haber uno por tabla y debe crearse en primer
lugar. El valor predeterminado es NONCLUSTERED.
INCLUDE
Con esta opción, se puede duplicar la información para incluir una copia de las columnas
especificada directamente dentro del índice en forma de parámetro. Esta posibilidad está
limitada a los índices no agrupados y los datos se almacenan en el nivel de hoja. En el
índice se pueden incluir desde 1 hasta 1.026 columnas de cualquier tipo excepto
varchar(max), varbinary(max) y nvarchar(max). La opción INCLUDE permite elaborar
índices que cubran la consulta, es decir que la consulta sólo deberá recorrer el índice para
encontrar todas sus necesidades.
FILLFACTOR = x
Especifica el porcentaje de relleno de las páginas del índice a nivel de hoja. Esto permite
mejorar el rendimiento, pues evita tener valores de índice consecutivos que ya no serían
físicamente contiguos. El valor predeterminado es 0 o determinado por sp_configure .
Para x = 0, el nivel hoja se rellena al 100%, se reserva espacio a nivel no hoja. Para x entre
1 y 99, el porcentaje de relleno a nivel hoja es x%; se reserva espacio a nivel no hoja. Para
x = 100, se rellenan los niveles hoja y no hoja.
PAD_INDEX
Especifica la tasa de relleno de las páginas a nivel no hoja del índice. Esta opción sólo se
puede utilizar con FILLFACTOR, cuyo valor se recupera.
grupo_archivo
En este nivel no se tienen en cuenta los índices particionados. Los elementos de sintaxis sólo
conciernen a los índices definidos en su totalidad sobre un único grupo de archivos.
IGNORE_DUP_KEY
Esta opción autoriza entradas duplicadas en los índices únicos. Si se activa esta opción, se
generará una advertencia al insertar un duplicado y SQL Server ignorará la inserción de
fila. En el caso contrario se genera un error.
DROP_EXISTING
ONLINE
Cuando está activada (ON) esta opción durante la construcción del índice, los datos de la
tabla permanecen accesibles en lectura y en modificación durante la construcción del
índice. Esta opción está disponible a partir de SQL Server 2005 y está desactivada de
manera predeterminada.
STATISTICS_NORECOMPUTE
Si el servidor sobre el que se ejecuta SQL Server 2005 posee varios procesadores, la
creación de índices puede efectuarse de forma paralela con el fin de ganar tiempo en la
construcción de índices en tablas de grandes dimensiones. La implantación de un plan de
ejecución paralela para la construcción de un índice tiene en cuenta el número de
procesadores del servidor, la opción de configuración max degree of parallelism
(sp_configure) y el número de procesadores que no están ya demasiado cargados por
threads de SQL Server.
Ejemplo
b. Eliminación de un índice
Únicamente los índices definidos con la instrucción CREATE INDEX pueden ser
eliminados con DROP INDEX. Un índice puede ser suprimido cuando su presencia no
permita mejorar el rendimiento significativo en comparación con el coste de
mantenimiento.
Sintaxis
c. Reconstruir un índice
El comando ALTER INDEX permite reconstruir un índice concreto o todos los índices
asociados a una tabla. En el momento de la reconstrucción, se puede especificar el factor de
relleno de las hojas.
Syntaxis
FILLFACTOR
Permite especificar el porcentaje de relleno de las páginas a nivel de hoja del índice.
PAD_INDEX
Permite aplicar a las páginas del índice a nivel de no hoja el mismo factor de relleno que se
ha especificado a través de FILLFACTOR.
Las otras opciones de la instrucción ALTER INDEX poseen el mismo significado que las
utilizadas con la instrucción CREATE INDEX. Hay que destacar que la opción ONLINE
adquiere todo su sentido en este caso concreto porque permite reconstruir el índice mientras
los usuarios trabajan con los datos de la tabla subyacente. Es cierto que las operaciones
serán más lentas pero no se bloquearán. Si la reconstrucción del índice se planifica para un
momento de poca utilización del servidor puede incluso pasar desapercibida para los
usuarios que trabajen en la base en ese momento.
SQL Server utiliza datos sobre la distribución de los valores de claves, para optimizar las
consultas. Estos datos deben ser actualizados después de las modificaciones importantes de
datos.
Sintaxis
FULLSCAN
Las estadísticas se crean a partir de un barrido completo de un 100% de las filas de la tabla.
SAMPLE n{PERCENT|ROWS}
Las estadísticas se establecen a partir de una muestra representativa de los datos de la tabla.
Esta muestra puede expresarse en forma de porcentaje o de número de filas. Si el tamaño de
la muestra no es suficiente, SQL Server corrige por sí mismo el tamaño para garantizar que
ha recorrido alrededor de mil páginas de datos. Éste es el modo predeterminado de
muestreo de estadísticas.
RESAMPLE
Las estadísticas también pueden actualizarse de forma automática. Esta opción debe ser
definida en el momento de la construcción de la base, por medio del comando ALTER
DATABASE, o bien utilizando el procedimiento almacenado sp_autostats.
El procedimiento sp_createstats permite definir estadísticas sobre todos los índices de datos de
usuario de la base en una sola operación.
En modo automático, es el motor el que se encarga de calcular las estadísticas que faltan, de
mantener al día las estadísticas en función de las operaciones realizadas sobre los datos y
también de suprimir las estadísticas inútiles.
Es posible saber si una base está configurada en generación automática de las estadísticas
consultando la columna is_auto_update_stats_on de la tabla sys.databases o bien
visualizando el valor de la propiedad IsAutoUpdateStatistics de la función
databasepropertyex.
Creación de las estadísticas de todos los índices sobre todos los datos no de sistema de la
base de datos GESCOM:
Se pueden obtener datos sobre el tamaño y la fragmentación de las tablas e índices por
medio de la función sys.dm_db_index_physical_stats.
Syntaxis
dm_db_index_physical_stats(id_base | NULL,
id_Objeto | NULL,
id_índice | NULL | 0,
número_partición | NULL ,
modo | NULL | DEFAULT)
id_base
id_Objeto
Identificador del objeto (tabla o vista) sobre el que se desea obtener información. Este
identificador puede obtenerse llamando a la función object_id(). El uso del valor NULL
permite indicar que se desea información sobre todas las tablas y vistas de la base de datos
actual. Ello también implica que se usará el valor NULL para la opción id_índice y
número_partición.
id_índice
número_partición
modo
Tras la creación y el uso de las tablas y de los índices, en ocasiones es útil verificar la
coherencia de los datos y de las páginas.
Verifica en todas las tablas de la base el enlace entre páginas de datos y de índice, los
criterios de ordenación y el puntero. También se aportan datos sobre el espacio en disco del
registro de transacciones.
Esta instrucción realiza un trabajo similar a DBCC CHECKDB pero para una sola tabla. Si
se proporciona el identificador de índice, sólo se verifica éste; si se especifica NOINDEX,
los índices no se verifican.
Generalidades
Microsoft Transact-SQL es un lenguaje de consultas mejorado respecto al SQL, en el cual
se basa. El SQL (Structured Query Language) es el lenguaje estándar, creado por IBM en
los años setenta para la gestión de los SGBDR (Sistemas de Gestión de Bases de Datos
Relacionales).
Con ayuda de Transact SQL, es posible definir funciones y procedimientos que se ejecutan
directamente sobre el servidor de la base de datos. Este tipo de procedimientos y funciones
son particularmente interesantes cuando el tratamiento necesita de la manipulación de un
volumen de datos elevado para obtener el resultado. De igual manera, el desarrollo en
Transact SQL está perfectamente adaptado a un contexto de funcionalidades compartidas
porque los procedimientos y las funciones alojadas en el servidor pueden ser ejecutadas
desde cualquier entorno cliente (.Net, Java...).
Desde SQL Server 2008 es posible, pero no obligatorio, utilizar el punto y coma como
marcador de final de instrucción.
1. Expresiones
Constantes
Ejemplo
Funciones
Ejemplo
expresión valor
SQRT(9) 3
substring(’ABCDEF’,2,3) ’BCD’
Variables
Las variables pueden emplearse como expresión o, en una expresión, con la forma
@nombre_de_variable o @@nombre_de_variable. El valor de la expresión es el valor de la
variable.
Ejemplo
Subconsultas
Una consulta SELECT entre paréntesis puede emplearse como expresión y tener como
valor el resultado de la consulta, ya sea un valor único o un conjunto de valores.
Ejemplo
Expresiones booleanas
Están destinadas a comprobar condiciones (IF, WHILE, WHERE, etc.). Estas expresiones
se componen de la manera siguiente:
2. Operadores
Operadores aritméticos
+ Suma
- Resta
* Multiplicación
/ División
% Módulo (resto de la división entera)
(...) Paréntesis
Ejemplo
La concatenación permite crear una sola cadena de caracteres a partir de varias expresiones
de tipo carácter. El operador de concatenación es el signo más (+).
Ejemplo
Operadores de bit
& Y
| O
^ O exclusivo
~ NO
Operadores de comparación
_ Un carácter cualquiera.
% n caracteres cualesquiera.
[ab...] Un carácter en la lista ab...
[a-z] Un carácter en el intervalo az.
[^ab...] Un carácter fuera de la lista o del intervalo especificado.
ab... El propio carácter.
Ejemplo
Busca en el intervalo compuesto por los valores min y max (límites incluidos).
EXISTS (subconsulta)
Operadores lógicos
3. Funciones
Las funciones estándar de SQL Server pueden agruparse por tipos: rowset, agregación,
ranking, escalar. Como este último tipo contiene un gran número de funciones, debe
subdividirse por categorías: matemáticas, cadena de caracteres, fecha, etc.
Ciertas funciones, sobre todo las que trabajan con datos de tipo carácter, toman en cuenta la
clasificación definida a nivel del servidor.
Funciones de agregación
Estas funciones devuelven un valor único resultado de un cálculo estadístico sobre una
selección de líneas.
Las funciones de agregado son deterministas, es decir que aplicadas a un mismo conjunto
de datos devuelven siempre el mismo resultado.
COUNT(*)
COUNT([ALL|DISTINCT] expr)
Cuenta todas las expresiones no nulas (ALL) o las expresiones no nulas únicas
(DISTINCT).
COUNT_BIG
SUM([ALL|DISTINCT] exprn)
Suma de todas las expresiones no nulas (ALL) o de las expresiones no nulas únicas
(DISTINCT).
AVG([ALL|DISTINCT] exprn)
Promedio de todas las expresiones no nulas (ALL) o las expresiones no nulas únicas
(DISTINCT).
MIN(exp) o MAX(exp)
VAR([ALL|DISTINCT] exprn)
VARP([ALL|DISTINCT] exprn)
GROUPING
Se utiliza conjuntamente con ROLLUP y CUBE . Indica el valor 1 cuando la fila ha sido
generada por una instrucción ROLLUP o CUBE; si no, indica el valor 0.
CHECKSUM (*|exp[,...])
Permite calcular un código de control a partir de una fila de la tabla o a una lista de
expresiones (por ejemplo, varias columnas). Esta función permite producir un código de
hash.
CHECKSUM_AGG([ALL|DISTINCT]exp)
Permite calcular un valor de hash a partir de un grupo de datos. Este código de control
permite saber rápidamente si un grupo de datos ha sufrido modificaciones; si las ha habido,
el resultado de la función ya no será el mismo.
Funciones matemáticas
ABS(expn)
CEILING(expn)
FLOOR(expn)
SQRT(expn)
POWER(expn,n)
expn elevado a n.
SQUARE(expn)
Funciones trigonométricas
PI()
DEGREES (expn)
RADIANS(expn)
ATN2(expn1,expn2)
Funciones logarítmicas
EXP(expn)
Exponencial de expn.
LOG(expn)
LOG10(expn)
Funciones diversas
RAND([expn])
ROUND(expn,n[,f])
Ejemplo
expn n f resultado
1.256 2 1.260
1.256 4 1.256
1.256 0 1.000
11.25 -1 10
11.25 -2 .00
11.25 -3 .00
150.75 0 151
150.75 0 1 150
Funciones fecha
Las funciones de fecha manipulan expresiones de tipo DATETIME y utilizan formatos que
representan la parte de la fecha que se debe gestionar.
GETDATE()
DATENAME (formato,expd)
DATEPART (formato,expd)
Es posible configurar el primer día de la semana por medio de la función SET DATEFIRST
(número_día). Los días se numeran desde el 1 para el lunes hasta el 7 para el domingo. Se
puede conocer la configuración actual interrogando a la función @@datefirst .
DATEDIFF (formato,expd1,expd2)
DATEADD (formato,n,expd)
DAY(expd)
MONTH(expd)
YEAR(expd)
Devuelve el año.
Si el parámetro que se pasa a estas tres funciones es el valor 0, SQL Server efectúa sus cálculos
sobre el 1 de enero de 1900.
Convierte el dato de tipo DATETIMEOFFSET del parámetro hacia la zona horaria indicada
en el segundo parámetro.
SYSDATETIME
SYSDATETIMEOFFSET
Funcionamiento similar a SYSDATETIME pero el dato de tipo fecha y hora devuelto está
en formato datetimeoffset e incluye por tanto la diferencia con respecto a la hora GMT.
ASCII (expc)
UNICODE(expc)
CHAR(expn)
NCHAR(expn)
LTRIM(expc), RTRIM(expc)
STR(expn,[lg[,nbd]])
Convierte el número expn a cadena de longitud total lg con los nbd caracteres a la derecha
de la marca decimal.
SPACE(n)
Devuelve n espacios.
REPLICATE (expc,n)
CHARINDEX (‟máscara‟,expc),PATINDEX(‟%máscara%‟,expc)
LOWER(expc),UPPER(expc)
REVERSE(expc)
RIGHT(expc,n)
LEFT(expc,n)
SUBSTRING(expc,dp,lg)
STUFF(expc1,dp,lg,expc2)
Elimina lg caracteres de expc1 a partir de dp, y luego inserta expc2 en la posición dp.
SOUNDEX(expc)
Devuelve el código fonético de expc. Este código se compone de la primera letra de expc y
de tres cifras.
DIFFERENCE(expc1,expc2)
Compara los SOUNDEX de las dos expresiones. Devuelve un valor de 1 a 4; 4 significa
que las dos expresiones ofrecen la mayor similitud.
LEN(expc)
QUOTENAME(expc[,delimitador])
Funciones de sistema
COALESCE(exp1,exp2...)
COL_LENGTH (‟nombre_tabla‟,‟nombre_columna‟)
Longitud de la columna.
COL_NAME (id_tabla,id_col)
DATALENGTH (exp)
DB_ID ([‟nombre_base‟])
DB_NAME ([id_base])
Devuelve 1 si la opción "ANSI NULL DEFAULT" está activada para la base de datos.
HOST_ID()
HOST_NAME()
IDENT_INCR (‟nombre_tabla‟)
Valor del incremento definido para la columna IDENTITY de la tabla o de la vista que
afecta a una tabla con una columna IDENTITY.
IDENT_SEED (‟nombre_tabla‟)
Valor inicial definido para la columna IDENTITY de la tabla o de la vista sobre una tabla
con una columna IDENTITY.
IDENT_CURRENT (‟nombre_tabla‟)
ISDATE(exp)
ISNULL (exp,valor)
ISNUMERIC(exp)
NULLIF (exp1,exp2)
OBJECT_ID (‟nombre‟)
STATS_DATE (id_tabla,id_índice)
SUSER_ID([‟nombre_acceso‟])
SUSER_NAME ([id])
USER_NAME ([id])
Nombre del usuario identificado por id. Sólo se debe utilizar con la restricción DEFAULT
(funciones niládicas).
CURRENT_TIMESTAMP
SYSTEM_USER
Nombre de acceso.
OBJECT-PROPERTY(id,propiedad)
ROW_NUMBER
RANK
Permite conocer el rango de una fila de una partición de un conjunto de resultados. El rango
de una fila es superior en una unidad al rango de la fila de misma partición.
DENSE_RANK
Funciona como RANK, pero sólo se aplica a las filas presentes en el conjunto de
resultados.
HAS_DBACCESS („nombreBase‟)
Permite saber si, con el contexto de seguridad actual, es posible acceder a la base de datos
del parámetro. Devuelve valor 1 en caso afirmativo y 0 en caso negativo.
HAS_PERMS_BY_NAME
Permite saber por programación si se dispone de un privilegio o no. Este tipo de función
puede resultar interesante en el caso de un cambio de contexto.
KILL
Esta función, bien conocida por los usuarios de los sistemas Unix/Linux, permite poner fin
a una sesión de usuario. Para poner fin a una conexión, es necesario pasar el parámetro del
identificador de sesión (sessionID o SPID) o bien el identificador de lote actualmente en
ejecución (UOW - Unit of Work). Se puede saber el UOW consultando la columna
request_owner_grid de la vista sys.dm_tran_locks. El identificador de sesión se puede
obtener consultando el contenido de la variable @@SPID, ejecutando el procedimiento
sp_who o bien consultando la columna session_id de vistas como sys.dm_tran_locks o
sys_dm_exec_sessions. Si la cancelación se realiza sobre una transacción de gran
envergadura, entonces la operación puede ser relativamente larga.
NEWID()
NEWSEQUENTIALID()
Esta función, destinada a ser utilizada únicamente para generar un valor predeterminado,
permite generar el siguiente valor de tipo UniqueIdentifier. Puesto que el siguiente valor de
tipo UniqueIdentifier es predecible, esta función sólo debe ser utilizada en las estructuras
que necesiten un nivel de seguridad elevado.
PARSENAME („nombreObjeto‟,parteQueExtraer)
PUBLISHINGSERVERNAME
Devuelve el nombre del publicador que publica una base de datos.
Elimina una cantidad especificada de caracteres (lg) de la cadena1 e inserta otro conjunto
de caracteres (cadena2) en el punto inicial especificado (dp).
CONVERT (tipo_dato,exp[,estilo])
Sin el Con el
Estándar Salida
siglo siglo
- 0 o 100 defecto (mes/mmm)dd aaaa hh:mm AM (o PM)
1 101 USA mm/dd/aa
2 102 ANSI aa.mm.dd
3 103 inglés/francés dd/mm/aa
4 104 alemán dd.mm.aa
5 105 italiano dd-mm-aa
6 106 - dd mmm aa
7 107 - mmm dd,a
8 108 - hh:mm:ss
- 9 o 109 defecto (mes/mmm)dd aaaa hh:mm:ss:mmm AM
10 110 USA mm-dd-aa
11 111 Japón aa/mm/dd
12 112 ISO aammdd
dd(mes/mmm)aaaa
- 13 o 113 europeo
hh:mm:ss:mmm(24h)
14 114 - hh:mm:ss:mmm (24h)
ODBC
- 20 o 120 aaaa-mm-dd hh:mi:ss(24h)
canónico
ODBC
- 21 o 121 yyyy-mm-dd hh:mi:ss.mmm(24h)
canónico
- 126 ISO8601 aaaa-mm-jjThh:mi:ss.mmm
- 130 Hijri dd mes aaaa hh:mi:ss:mmmAM
- 131 Hijri dd/mm/aa hh:mi:ss:mmmAM
En caso de que se introduzca el año con dos caracteres, SQL utiliza 2049 como año de referencia,
es decir, que para todo valor comprendido entre 0 y 49 SQL Server considera que se trata de un
año del siglo XXI, mientras que para todo valor comprendido entre 50 y 99, SQL Server considera
que se trata de un
SQL-DML
El lenguaje de manipulación de datos (SQL-Data Manipulation Language) se compone de
instrucciones que permiten la gestión, visualización y extracción de las filas de las tablas y
de las vistas.
1. Creación de filas
La creación de filas en una tabla, o en una vista según ciertas condiciones (ver más
adelante), se lleva a cabo con el comando INSERT.
Las restricciones serán controladas, y los triggers serán activados en el momento en que se
ejecute el comando. La forma "INSERT ..... VALUES ....." crea una sola fila, mientras que
"INSERT ..... SELECT ....." permite crear eventualmente varias filas.
Sintaxis
nombre_objeto
(col,...)
Lista de las columnas a las que se asignarán valores. Las columnas no citadas tomarán el
valor NULL. Si se omite la lista, todas las columnas deberán estar asociadas a un valor.
DEFAULT VALUES
Todas las columnas citadas tomarán sus valores por defecto o NULL si no tienen.
(val,...)
Lista de valores compuesta de expresiones constantes, de las palabras clave NULL o
DEFAULT, o de variables. Debe haber tantos valores como columnas a las que dar valores,
del mismo tipo y en el mismo orden.
consulta
Instrucción SELECT que devuelve tantos valores, en el mismo orden y del mismo tipo que
las columnas a las que dar valor. Esta forma de sintaxis permite insertar varias filas en una
sola operación.
procedimiento
Nombre de un procedimiento almacenado local o remoto. Sólo los valores de las columnas
devueltas por una orden SELECT contenida en el procedimiento darán valores a las
columnas afectadas por el INSERT.
Ejemplo
Creación de un cliente (asignación de valor a todas las columnas, valor por defecto para
ciudad, NULL para el teléfono:
Aplicación de este procedimiento para dar valores a una tabla temporal, con la información
sobre las tablas cuyo propietario es "dbo":
La instrucción INSERT permite insertar varias filas de datos de manera simultánea cuando
está asociada a una cláusula SELECT, pero también es posible añadir varias filas
precisando directamente los valores de los datos que se desean insertar. Para ello, se
especifican entre paréntesis tras la cláusula VALUES los datos relativos a cada fila que se
inserta y cada conjunto de valores se separa mediante una coma.
Sintaxis
nombre_tabla
(col, ...)
Nombre de las distintas columnas de la tabla para las que se han provisto valores. El orden
de las columnas definido en este punto define asimismo el orden en que se deben
suministrar los valores.
(valorFila1, ...)
Valores de los datos que se desean añadir a la tabla. Cada conjunto de valores debe
suministrar un dato para cada columna especificada en la lista de columnas.
Ejemplo
En el ejemplo siguiente se han introducido dos valores en la tabla categorías mediante una
sola instrucción INSERT:
2. Modificación de filas
Sintaxis
nombre_objeto
col
exp
Cualquier tipo de expresión que devuelva un solo valor del mismo tipo que la columna. Se
permiten las palabras clave DEFAULT y NULL.
FROM nombre_objeto
Permite actualizar cada fila a partir de los datos de otras tablas o vistas.
cond
Expresión booleana que permite limitar las filas que se van a actualizar.
Ejemplo
3. Eliminación de filas
La instrucción DELETE permite eliminar una o más filas de una tabla o vista, en función
de una condición o de los datos de otra tabla.
Sintaxis
FROM nombre_objeto
cond
Expresión booleana que permite restringir las filas que se van a eliminar.
Ejemplos
4. Extracción de filas
La instrucción SELECT permite visualizar los datos almacenados en las bases de datos,
efectuar cálculos o transformaciones sobre estos datos, o dar valor a las tablas a partir de
otras tablas.
Esta instrucción tiene una sintaxis compleja que se puede estudiar en tres partes:
ALL
DISTINCT
lista_expresiones
lista_objeto
Lista de tablas, o de vistas separadas por comas, a partir de las cuales los datos se extraerán.
Cada nombre de objeto podrá ir seguido de un nombre de alias que permite citar la tabla o
la vista con otro nombre. Además, se puede orientar el funcionamiento interno de la
consulta colocando directivas de consultas para el optimizador, entre paréntesis, tras cada
nombre de objeto (ver anexos).
La palabra clave SELECT permite introducir una lista de columnas que se extraerán de las
tablas en el orden seleccionado o todas las columnas en el orden de creación con * (o
nombre_tabla.*). En caso de ambigüedad en los nombres de columnas, se puede utilizar la
forma: nombre_tabla.nombre_col. La columna resultante tendrá el mismo nombre que la
columna inicial, salvo si se emplea un título o un alias de columna.
Ejemplos
Alias de columna:
También es posible renombrar una columna utilizando la palabra clave AS entre el nombre
de la columna y su alias en la cláusula SELECT. El resultado observado será el mismo que
el presentado en el ejemplo anterior.
b. Restricción
La restricción consiste en extraer sólo un cierto número de líneas que respondan a una o
más condiciones. La cláusula WHERE permite la implementación de las restricciones. Las
condiciones son expresiones booleanas compuestas de nombres de columnas, de constantes,
de funciones, de operadores de comparación y de operadores lógicos.
Ejemplos
Clientes de Barcelona:
Ejemplos
d. Proyección
Ejemplo
Agrupación por ciudad y código postal (para ver las ciudades que tienen varios códigos
postales):
e. Cálculos de agregados
Los cálculos estadísticos sobre las agrupaciones de líneas o sobre toda una selección se
hacen utilizando las funciones estadísticas (COUNT, SUM, AVG, MIN, MAX) y
eventualmente la cláusula GROUP BY. La cláusula HAVING permite probar una
condición para limitar los grupos de resultados.
Ejemplos
f. Producto cartesiano
Sintaxis
Sintaxis común
Sintaxis ANSI
El producto cartesiano permite extraer datos de varias tablas asociando cada fila de cada
tabla citada. las tablas afectadas deben ir separadas por comas tras el FROM. Si se quiere
citar el mismo nombre de columna en dos tablas distintas, éste debe ir precedido por el
nombre de tabla o el nombre de alias.
Esta operación puede utilizarse para simulaciones de asociación de datos o para generar un
gran número de filas (el número de filas resultantes será el producto del número de filas de
cada tabla).
Ejemplos
g. Combinación
Sintaxis
Sintaxis común
Sintaxis ANSI
Ejemplos
h. Combinaciones externas
Según si se quiere ver las filas de la primera (LEFT) o de la segunda tabla (RIGHT).
La combinación externa completa (FULL OUTER JOIN) permite mostrar los datos
obtenidos de estas dos tablas aunque no sea posible establecer correspondencia.
Sintaxis
Ejemplo
Lista de los pedidos por cliente. Los clientes que no tienen también aparecen:
SQL Server 2008 ya no soporta la sintaxis SQL Server *= y =* para definir las
combinaciones externas, como muestra el ejemplo siguiente:
La lectura del mensaje de error permite comprender el origen del error y ofrece una
posibilidad para solucionar el problema.
Autocombinación
Es posible asociar filas de una tabla a otras filas de la misma tabla realizando un self-join.
Es obligatorio el uso de los alias de tabla para evitar las ambigüedades de sintaxis.
i. Order By
La cláusula Order By permite ordenar los datos resultantes de una consulta de tipo
SELECT, así como especificar qué columnas se ordenarán. Para cada criterio de
ordenación, se debe especificar si se utiliza un orden ascendente (predeterminado) o
descendente.
Las columnas se definen por su nombre o bien por su número de orden en la cláusula
SELECT.
Ejemplo
Los clientes se muestran por orden alfabético de su apellido y nombre y por códigos
postales.
j. Unión
Ejemplo
k. Except
Este operador permite poner en práctica en SQL Server 2005 el operador de diferencia
definido en álgebra relacional. Permite localizar las filas de información presentes en un
conjunto de resultados no en otro.
Esta diferencia sólo se puede encontrar entre dos conjuntos de resultados con la misma
estructura, es decir, el mismo número de columnas, definidas en el mismo orden y sobre los
mismos tipos de datos para los dos conjuntos de resultados.
Ejemplo
Presentar la lista de clientes cuyo nombre comience por San y que no estén en la provincia
de Barcelona (08).
l. Intersect
Ejemplo
Presentar la lista de clientes cuyo nombre comience por San y que estén en la provincia de
Barcelona (08).
Existen otros medios para llegar al mismo resultado, pero el objetivo aquí es sencillamente ilustrar
el operador INTERSECT.
La cláusula TOP permite extraer solamente las primeras filas de un conjunto de resultados.
Esta cláusula está disponible para las operaciones SELECT, INSERT, UPDATE y
DELETE.
Sintaxis
número
Representa el número de filas que se devuelven. Se trata de un número entero (bigint), o del
porcentaje de filas a recuperar. Este porcentaje puede expresarse en forma de float.
PERCENT
WITH TIES
La selección de filas a presentar se efectúa después de ordenar los datos con la cláusula
ORDER BY. Sólo se puede emplear esta opción si se especifica una cláusula ORDER BY
en la consulta.
Ejemplo
Los pedidos se ordenan por cifras de negocio en sentido descendente y sólo se desean
conocer los tres primeros.
En este primer ejemplo no se utiliza la cláusula WITH TIES, por lo que la selección de las
3 líneas se efectúa antes de ordenar los resultados.
En este segundo ejemplo, la cláusula PERCENT permite conocer el 5% del resultado final.
Es posible crear una nueva tabla a partir de una consulta utilizando la sintaxis:
Sólo se puede acceder a una tabla temporal local durante la sesión en que ha sido creada,
pues desaparece con la desconexión. A una tabla temporal global se puede acceder durante
todas las sesiones y se suprime al final de la última sesión que la ha utilizado.
Ejemplos
8. Tablas CTE
Las tablas CTE (Common Table Expresión) tienen como objetivo simplificar la escritura y
por consiguiente la comprensión de las consultas. Una tabla CTE puede ser considerada
como una tabla temporal y específica de una instrucción SQL DML. Una alternativa a la
utilización de tablas CTE puede ser definir una tabla temporal local (#MyTable) antes de la
consulta de SQL DML y suprimir esta tabla temporal local inmediatamente después de la
ejecución de la consulta. Evidentemente esta alternativa es mucho más compleja de
administrar y por tanto menos limpia en cuanto a programación.
Las tablas CTE permiten escribir de forma sencilla consultas complejas simplificando
considerablemente la escritura de consultas anidadas.
Las tablas CTE pueden ser utilizadas en el contexto de una consulta de extracción de datos
(SELECT), pero también para las consultas de modificación de datos (INSERT, UPDATE
y DELETE).
Sintaxis
La tabla CTE se crea utilizando la instrucción WITH seguida del nombre de la tabla
acompañado de la lista de columnas. La consulta SELECT que sirve de base para construir
la tabla CTE se define a partir de la palabra clave AS.
Les tablas CTE son más fáciles de crear que las tablas temporales, ya que el esfuerzo de
sintaxis es menor. En cambio, el número de restricciones es mayor:
La cláusula COMPUTE crea nuevas filas que contienen resultados estadísticos a partir de
funciones de agregación. Esta cláusula permite visualizar a la vez las filas de detalles y los
cálculos de agregados, a la inversa de lo que hace GROUP BY, que sólo presenta los
cálculos.
Sintaxis
función_estad_fila(col)
BY col
Muestra el resultado al cambiar de valor de columna. En ese caso, debe utilizarse una
cláusula ORDER BY sobre la columna o las columnas afectadas.
Ejemplo
La cláusula WITH CUBE permite crear líneas suplementarias para todas las combinaciones
de agrupación de las columnas del GROUP BY . Para el ejemplo anterior, se tendrá,
además, la suma para una agrupación sobre B, la suma para una agrupación sobre C y la
suma para una agrupación sobre A y C, así como la suma para una agrupación sobre B y C.
Se pueden utilizar, como máximo, 10 expresiones de agrupación para un tamaño total de 900
bytes.
Ejemplo
Cálculo de las cantidades en stock totales por almacén, categoría y artículo para dos
categorías y dos almacenes:
Operador OVER
Esta cláusula permite dividir los datos o bien clasificarlos antes, por ejemplo, de aplicar una
función de cálculo de agregado o una función de clasificación, es decir, ROW_NUMBER,
DENSE_RANK, RANK y NTILE.
Sintaxis
Operador NTILE
Esta función se utiliza conjuntamente con OVER y permite dividir cada partición en grupos
de datos equilibrados. Por ejemplo, con la instrucción NTILE(4) OVER... el resultado de
cada partición se dividirá en 4 grupos. Los datos serán repartidos de manera equitativa en
cada grupo. Si el número de filas presentes en la partición no es un múltiplo del número de
grupos que crear, entonces los primeros grupos contienen una fila más que los últimos
grupos. En el caso aquí presentado, si hay que crear 4 grupos y la partición contiene
15 filas, entonces los tres primeros grupos contendrán 4 filas y el cuarto grupo contendrá 3
filas.
Sintaxis
Ejemplo
Es posible anidar una consulta SELECT en otra consulta SELECT (o en una instrucción
UPDATE o DELETE) siempre que se utiliza una expresión. En general, la utilización se
lleva a cabo con las cláusulas WHERE o HAVING.
Subconsultas que devuelven un solo valor. Pueden utilizarse con los operadores =,
<>, < , <= >, > =.
Subconsultas que devuelven una lista de valores. Pueden utilizarse con el operador
IN, EXISTS, ANY, SOME o ALL.
Subconsultas correlacionadas (o subordinadas). La cláusula WHERE de la consulta
interna hace referencia a una de las tablas de la consulta externa. En ese caso, la
subconsulta interna se ejecuta para cada fila extraída por la consulta externa.
Ejemplos
Estas dos instrucciones, de Transact SQL, son muy potentes y fáciles de utilizar. El
objetivo de PIVOT es transformar en columnas distintas un resultado presente en forma de
filas distintas. UNPIVOT realiza la operación inversa. Para realizar la función de PIVOT
había que definir una instrucción case complicada o recurrir a otros operadores como la
combinación, la unión o el cálculo de agregados para presentar la información de la forma
deseada. En cualquier caso, una secuencia de programación larga es trabajosa y puede dar
lugar a problemas de funcionamiento.
Antes de utilizar esta función, hay que definir cuáles son los datos que va a afectar y qué
columna será el PIVOT. En general, el objetivo es realizar una tabla de síntesis para la que
el valor presente en la celda provenga de un cálculo de agregados que dependa de la fila y
la columna.
Para poder ejecutar estas instrucciones el servidor debe estar definido en nivel de compatibilidad
9.0 (sp_dbcmptlevel) o 00. En efecto, estas instrucciones han sido introducidas en Transact SQL
por SQL Server 2005.
Antes de utilizar la función PIVOT, hay que determinar el cálculo de agregados a efectuar y
los valores de la columna sobre los que se puede realizar este proceso. La columna debe
poseer un valor convertible en nvarchar porque los valores se transformarán en nombre de
columna. Por ello no es posible realizar una pivotación alrededor de un valor de formato
binario.
Resumen de sintaxis
SELECT
FROM [...]
PIVOT (cálculoAgregado FOR columnaPivot IN
(listaDeValor)) as aliasDeTabla
La lista de valor permite indicar los valores de la columna PIVOT que se transformarán en
columna. Todos los valores de la lista deben especificarse entre corchetes [ ] sin apóstrofe
para las cadenas de caracteres. Esta misma notación se emplea detrás de la cláusula
SELECT para indicar el título de la columna y el orden de las columnas.
Cuando se utiliza PIVOT con un cálculo de agregado, no se tienen en cuenta los valores nulos. Si se
desea procesar estos valores, hay que utilizar la función ISNULL de Transact SQL.
En el siguiente ejemplo, la tabla de stocks contiene una fila de información por artículo y
almacén. De momento existen tres almacenes (P1, P2 y N1); los dos primeros en
Barcelona, y el tercero en Murcia.
Para obtener una vista resumida de la disponibilidad de un artículo, hay que recorrer tres
filas de datos. No resulta fácil leer la información.
UNPIVOT
La función UNPIVOT realiza la función inversa a la de PIVOT. No obstante, es mucho
menos frecuente que surja la necesidad de transformar las columnas en filas. Si se presenta
el caso, esta funcionalidad se puede utilizar con la siguiente sintaxis:
Al igual que con PIVOT, es posible realizar combinaciones con una tabla que contenga la
columna UNPIVOT.
12. MERGE
Sintaxis
tablaDestino
Se trata de la tabla que contiene los datos sobre los cuales se basan las instrucciones
INSERT, UPDATE y DELETE.
origenDatos
A partir de este origen de datos se extraen los datos que permiten seleccionar el tipo de
operación que se ha de ejecutar y los datos que se han de utilizar.
condiciónSelección
Criterio de restricción que permite saber si es necesario seleccionar los datos o bien si debe
ser ejecutada la operación que sigue.
operación
Ejemplos
La tabla Síntesis_Clientes contiene las referencias de todos los clientes que han realizado al
menos un pedido, es decir, que poseen un volumen de negocio:
Creación de vistas
Se puede crear una vista con el lenguaje de definición de datos o con el SQL Server
Management Studio .
Sintaxis
CREATE VIEW nombre
[WITH ENCRYPTION | WITH SCHEMABINDING| WITH VIEW_METADATA]
AS consulta [WITH CHECK OPTION]
nombre
consulta
WITH ENCRYPTION
WITH SCHEMABINDING
Permite vincular la vista al esquema. Con esta opción, los objetos a los que se hace
referencia en la vista deben nombrarse del siguiente modo°:
nombre_esquema.nombre_objeto, y las tablas utilizadas en la vista no pueden ser
eliminadas. Además si una operación ALTER TABLE afecta a la definición de la vista, ésta
fallará.
WITH VIEW_METADATA
Eliminación de vistas
Sintaxis
DROP VIEW nombre
Ejemplo
Los desencadenadores de tipo INSTEAD OF están particularmente bien adaptados para las
vistas, ya que permiten desviar las acciones INSERT, UPDATE y DELETE hacia las tablas
que componen la vista. Estos desencadenadores ofrecen la posibilidad de obtener vistas
cuyo comportamiento sea completamente transparente para el usuario de la base de datos.
El SQL procedimental
SQL Server es un servidor de base de datos relacional y como tal proporciona todos los
elementos para almacenar de forma estructurada los datos, pero también las herramientas
necesarias para trabajar con los datos mediante SQL. Con Transact SQL también es posible
definir tratamientos procedimentales directamente en la base de datos. Estos tratamientos
podrán ser utilizados por todos los usuarios de la base siempre y cuando posean los
privilegios necesarios. Es posible conservar la definición de estos tratamientos y
convertirlos en parametrizables mediante la creación de funciones y procedimientos.
Una variable es una zona de memoria, caracterizada por un nombre y un tipo, que permite
almacenar un valor. Las variables Transact-SQL deben declararse obligatoriamente antes
de su utilización. A continuación pueden reemplazar cualquier expresión en las
instrucciones SQL.
Declaración de variables
tipo
Ejemplo
Modificación del nombre de los clientes que tienen el mismo apellido que el 954:
2. Variables de sistema
Estas variables son definidas por el sistema y se pueden utilizar sólo en lectura. Se
distinguen de las variables de usuario por la doble @.
@@CONNECTIONS
@@CPU_BUSY
Tiempo dedicado por la unidad central SQL Server desde el último inicio de éste. El
resultado se expresa en unidad CPU. Hay que multiplicar por @@TIMETICKS para tener
el resultado en microsegundos.
@@CURSOR_ROWS
@@DATEFIRST
@@DBTS
@@ERROR
Último número de error generado por el sistema para la conexión del usuario.
@@FETCH_STATUS
@@IDENTITY
@@IDLE
Tiempo, en milisegundos, durante el cual SQL Server ha estado inactivo desde su último
inicio.
@@IO_BUSY
@@LANGID
@@LANGUAGE
@@LOCK_TIMEOUT
@@MAX_CONNECTIONS
Número máximo de conexiones simultáneas que es posible establecer con SQL Server.
@@MAX_PRECISION
Devuelve el nivel de precisión utilizado por los tipos de datos decimal y numérico.
@@NESTLEVEL
@@OPTIONS
Datos sobre los valores actuales de las opciones SET.
@@PACK_RECEIVED
Número de paquetes entrantes leídos por SQL Server desde su último inicio.
@@PACK_SENT
Número de paquetes salientes escritos por SQL Server desde su último inicio.
@@PACKET_ERRORS
Número de errores que se han producido mientras SQL Server enviaba o recibía paquetes
desde su último inicio.
@@PROCID
@@REMSERVER
@@ROWCOUNT
@@SERVERNAME
@@SERVICENAME
@@SPID
@@TEXTSIZE
Longitud máxima, en bytes, de los datos de texto o imagen devueltos por una instrucción
SELECT.
@@TIMETICKS
@@TOTAL_ERRORS
Número de errores encontrados por SQL Server al leer o escribir datos desde su último
inicio.
@@TOTAL_READ
Número de lecturas de datos del disco efectuadas por SQL Server desde su último inicio.
@@TOTAL_WRITE
Número de veces que se han escrito datos en el disco efectuadas por SQL Server desde su
último inicio.
@@TRANCOUNT
@@VERSION
3. Las transacciones
Gestión de las transacciones
Lo primero que hay que tener en cuenta es el bloqueo de los datos. Cuando SQL Server lee
o modifica datos, bloquea las filas que está manipulando. Este bloqueo dura el mismo
tiempo que la ejecución de la instrucción o la transacción.
Sólo las instrucciones del DML ( SELECT, INSERT, UPDATE, DELETE) son tenidas en
cuenta en una transacción. Se excluyen todas las instrucciones que manipulan objetos
(CREATE, ALTER, DROP, SELECT INTO, GRANT, REVOKE, LOAD, DUMP...).
Las transacciones serán útiles para asegurar la integridad y la coherencia de los datos en
modificaciones múltiples, para mejorar el rendimiento, para probar los efectos de una
modificación, para gestionar los bloqueos.
Una transacción se caracteriza por la palabra clave ACID (Atomicity Consistency Isolation
Durability) es decir atomicidad, coherencia, aislamiento y durabilidad.
Sintaxis
Inicio de transacción
BEGIN TRAN[SACTION][nombretransacción]
Validación de transacción
COMMIT TRAN[SACTION][nombretransacción]
SAVE TRAN[SACTION][nombre_punto_control]
Anulación de transacción
ROLLBACK TRAN[SACTION][{nombretransacción/nombre_punto_control}]
Ejemplo
Bloqueos compartidos
Bloqueos de actualización
Bloqueos exclusivos
Destinados a las operaciones de escritura, no permiten ningún otro bloqueo y actúan a nivel
de tabla o página.
Permiten a SQL Server señalar que una transacción quiere adquirir un bloqueo de
actualización o compartido sobre el recurso. Es imposible la activación de bloqueos
exclusivos.
SET TRANSACTION
Se puede definir el sistema de bloqueo de las instrucciones SELECT para todas las
transacciones de la sesión.
Sintaxis
Read UNCOMMITTED
Este nivel permite leer las modificaciones todavía no validadas por otras transacciones.
Este tipo de lectura se denomina “en sucio” o "dirty read", ya que los datos visualizados no
necesariamente se conservarán en caso de que la transacción se anule (ROLLBACK). En
este modo de funcionamiento, las instrucciones de DML no necesitan un bloqueo
compartido para la lectura de los datos porque nada impide la modificación de los datos
leídos, aunque la modificación no esté aún validada.
READ COMMITTED
REPEATABLE READ
Con este modo de funcionamiento, los datos leídos o modificados por una transacción ya
no son accesibles para las otras transacciones, con el fin de garantizar que la lectura
repetida de una fila de datos devuelva siempre el mismo contenido. No obstante, los datos
leídos siguen siendo accesibles en lectura para las demás transacciones. Los bloques se
definen para la duración de la transacción. Con este tipo de bloqueo, se pueden agregar
datos a las tablas entre el principio y el fin de la transacción y, por tanto, el conjunto de
datos ya no es el mismo. Este tipo de problema puede tener una incidencia significativa
cuando, por ejemplo, una transacción efectúa un cálculo de descuento sobre una cifra y,
simultáneamente, otra transacción añade un pedido adicional. Este nuevo pedido modificará
el resultado del cálculo del descuento.
SERIALIZABLE
Con este modo de funcionamiento, los datos leídos o modificados por una transacción serán
accesibles únicamente para esta transacción. Los datos que sólo se lean seguirán siendo
accesibles en modo de lectura para las demás transacciones. Se definen bloqueos para toda
la duración de la transacción a nivel de las filas de datos. También se definen bloqueos de
nivel más alto, en los índices, para evitar que se agreguen datos al conjunto de resultados de
la transacción. Si no existe ningún índice que cubra la consulta de lectura, se impone un
bloqueo adicional a nivel de la tabla.
Opciones de bloqueo
Es posible especificar el bloqueo de una tabla para una instrucción SELECT particular.
Es muy aconsejable dejar la gestión de bloqueos en manos del motor relacional de SQL
Server para optimizar esta gestión. La gestión manual sólo permite muy raramente una
gestión óptima y puede provocar problemas de interbloqueo o retrasos para las otras
transacciones.
Sintaxis
NOLOCK
Sin bloqueos.
HOLDLOCK
UPDLOCK
TABLOCK
PAGLOCK
TABLOCKX
ROWLOCK
Permite especificar que se debe utilizar un bloqueo de nivel de filas cuando el optimizador
de consulta de la tabla tome la decisión de utilizar uno en el nivel de páginas o de tablas.
Ejemplo
Se puede activar el bloqueo a nivel de fila en las inserciones (IRL: Insert Row-level Locking)
ejecutando el procedimiento almacenado: sp_tableoption ’nombretabla’,’insert row lock’,’true’.
4. Gestión de los lotes y de los scripts
Los scripts son conjuntos de lotes que se ejecutarán sucesivamente a partir de un archivo de
texto. Estos archivos tienen, por convención, la extensión ‟.sql‟.
5. Control de flujo
a. RETURN
Sintaxis
RETURN [exprn]
Ejemplo
Utilización:
Ahora se podrá comprobar la variable @verif_procedure.
b. PRINT
Sintaxis
PRINT {’texto’|@variable|@@variablesistema}
Ejemplo
c. CASE
Sintaxis
CASE [expresión]
WHEN {valor|condición} THEN
valoratribuido1
[...]
[ELSE valoratribuido n]
END
Ejemplo
d. BEGIN... END
Es una estructura de control que permite delimitar una serie de instrucciones (bloque). Se
utiliza con los condicionales (IF) y los bucles (WHILE).
Sintaxis
BEGIN
{instrucción | bloque}
...
END
e. IF
Es la estructura de control alternativa que permite evaluar una condición y ejecutar una
instrucción o un bloque si la condición es VERDADERA.
Sintaxis
IF condición
{instrucción|bloque}
[ELSE]
{instrucción|bloque}
Ejemplo
f. WHILE
Sintaxis
WHILE condición
{instrucción|bloque}
Ejemplo
Se aumentan las tarifas hasta que el promedio del precio sobrepase los 50 € o hasta que un
artículo de la categoría ‟01‟ sea superior a 600 €.
g. OUTPUT
Esta cláusula, introducida por SQL Server 2005, permite conocer las filas afectadas por la
operación de DML INSERT, UPDATE o DELETE. Con esta información, la aplicación
que ha solicitado ejecutar la instrucción DML puede saber cuáles son las filas de datos
afectadas.
El valor de las columnas devueltas por medio de la cláusula OUTPUT es posterior a la
aplicación de restricciones de integridad y a la ejecución de la instrucción DML, pero
anterior a la ejecución de los desencadenadores asociados a la tabla y a la instrucción DML.
Sintaxis
listaColumna
@variable
La variable debe ser de tipo tabla y debe declararse antes de su utilización en la cláusula
OUTPUT.
DELETE tabla
OUTPUT[listaColumna] INTO @variable
WHERE condición
Ejemplo
Utilización de la cláusula OUTPUT para conocer el valor afectado por una columna de tipo
IDENTITY al agregar datos.
El uso de cursores es una técnica que permite tratar fila por fila el resultado de una
consulta, contrariamente a SQL (SELECT), que trata un conjunto de filas.
Los cursores pueden ser implementados por instrucciones Transact-SQL (cursores ANSI-
SQL) o por la API OLE-DB.
Se utilizarán los cursores ANSI cuando sea necesario tratar las filas individualmente en un
conjunto o cuando SQL no pueda actuar únicamente sobre las filas afectadas. Los cursores
de las API serán utilizados por las aplicaciones cliente para tratar volúmenes importantes o
para gestionar varios conjuntos de resultados.
Utilice los cursores sólo si no es posible el uso de SQL orientado a conjuntos. Suelen consumir
mucha memoria y tiempo de tratamiento.
a. DECLARE CURSOR
Sintaxis
DECLARE nombrecursor[INSENSITIVE][SCROLL]CURSOR
FOR SELECT ....
FOR {READ ONLY|UPDATE[OF lista columna]}]
INSENSITIVE
SCROLL
Los desplazamientos en las filas del cursor podrán hacerse en todos los sentidos.
UPDATE
Especifica que las actualizaciones se harán sobre la tabla de origen del cursor.
Además de esta sintaxis conforme con la norma ISO, Transact SQL propone una sintaxis
ampliada que ofrece más posibilidades en lo relativo a los cursores:
GLOBAL
El alcance del cursor es global a la conexión. La opción de base de datos default to local
cursor está definida en falso (false) de manera predeterminada. Esta opción permite definir
el alcance predeterminado del cursor.
FORWARD_ONLY
Los datos se extraen del cursor por orden de aparición (del primero al último).
STATIC
Se realiza una copia temporal de los datos en tempdb para que el cursor no se vea afectado
por las modificaciones que puedan realizarse sobre la base.
KEYSET
Las filas y su orden en el cursor se fijan en el momento de la apertura del cursor. Las
referencias hacia cada una de estas filas de información se conservan en una tabla temporal
en tempdb.
DYNAMIC
El cursor refleja exactamente los datos presentes en la base. Esto significa que el número de
filas, su orden y su valor pueden variar de forma dinámica.
FAST_FORWARD
SCROLL_LOCKS
Permite garantizar el éxito de las instrucciones UPDATE y DELETE que pueden ser
ejecutadas en relación al cursor. Con este tipo de cursor, se fija un bloqueo en la apertura
del cursor para evitar que otra transacción trate de modificar los datos.
OPTIMISTIC
Con esta opción, puede que una operación de actualización (UPDATE) o bien de
eliminación (DELETE) realizada en el cursor no pueda efectuarse correctamente porque
otra transacción haya modificado los datos en paralelo.
TYPE_WARNING
b. OPEN
Esta instrucción permite hacer operativo el cursor y crear eventualmente las tablas
temporales asociadas. La variable @@CURSOR_ROWS se asigna después de OPEN.
Sintaxis
c. FETCH
Es la instrucción que permite extraer una fila del cursor y asignar valores a variables con su
contenido. Tras fetch, la variable @@FETCH_STATUS está a 0 si fetch no ha dado
errores.
Sintaxis
FETCH[{NEXT|PRIOR|FIRST|LAST|ABSOLUTE n|RELATIVE n]
[FROM] [GLOBAL] nombrecursor[INTO Listavariable]
NEXT
Lee la fila siguiente (única opción posible para los INSENSITIVE CURSOR).
PRIOR
FIRST
LAST
Lee la última fila.
ABSOLUTE n
RELATIVE n
d. CLOSE
Esta operación debe interponerse lo antes posible con el fin de liberar los recursos cuanto
antes.
Sintaxis
CLOSE nombrecursor
e. DEALLOCATE
Sintaxis
DEALLOCATE nombrecursor
Ejemplo
Sólo se quieren los tres artículos más caros por categoría en una tabla de trabajo:
Si la misma secuencia de comandos Transact SQL trabaja con varios cursores, la variable
@@FETCH_STATUS corresponderá al estado del último cursor utilizado. Para conocer en
detalle el estado de cada cursor, hay que interrogar a la columna fetch_status de la vista
dinámica sys.dm_exec_ cursors.
7. Gestión de excepciones
a. Mensajes de error
Para cada error, SQL Server genera un mensaje de error que, de forma predeterminada, se
presenta en pantalla. Su lectura completa suele permitir resolver el problema.
La mayoría de estos mensajes están definidos en SQL Server, pero también es posible
definir mensajes propios por medio del procedimiento sp_addmessage.
Sea cual sea su origen, todos los mensajes de error poseen la misma estructura y los
siguientes campos de información:
número: Cada mensaje se identifica con un número único. Éste es independiente del
lenguaje elegido en la instalación de SQL Server. Así, el programa desencadena un
error identificado por su número. A continuación, SQL Server selecciona en la tabla
sys.messages de la base de datos master el mensaje que va a presentar en función
del número del error y del lenguaje elegido en la instalación del servidor.
mensaje en formato texto: El mensaje es específico de cada tipo de error. Muchos
mensajes poseen variables para adaptar el contenido genérico al caso concreto y
ofrecer más información.
gravedad: Es un indicador de la gravedad del error. Los mensajes de gravedad 1 o 2
se generan simplemente a título informativo.
estado: un mismo error puede tener distintos orígenes, es decir que puede haber
aparecido en distintos contextos. Cada tipo de contexto tiene asociado un estado
cuyo número puede resultar útil de cara a consultar la documentación.
nombre del procedimiento: Si el error se ha provocado desde un procedimiento
almacenado, se presenta el nombre de éste.
número de línea: Número de la línea en la que se ha originado el error, ya se
encuentre en una serie de instrucciones, una función, un procedimiento almacenado
o un desencadenador de la base de datos.
En SQL Server, cada mensaje de error posee una gravedad concreta. Esta permite clasificar
los mensajes en función del riesgo potencial que comporten. Existen 25 niveles de
gravedad.
La gravedad se representa con un número entero comprendido entre 0 y 24. Esta gravedad
se asocia a un mensaje de error cuando éste se crea, aunque se puede fijar una gravedad
ligeramente diferente cuando la causa del error sea la instrucción RAISERROR.
Inferior a 9
Igual a 10
Igual a 17
Recursos insuficientes. Señala, por ejemplo, que SQL Server se ha quedado sin espacio en
disco o que la instancia ha alcanzado ciertos límites fijados por el administrador.
Igual a 18
Igual a 19
Igual a 20
Error fatal en el proceso actual. El proceso en curso acaba de sufrir un error grave, pero la
instancia de SQL Server no ha quedado afectada.
Igual a 21
Error fatal en el proceso de la instancia, aunque es poco probable que la base de datos haya
quedado afectada por el problema.
Igual a 22
Igual a 23
Igual a 24
Existen dos posibilidades para trabajar con esta instrucción: generar un error definido por
su número o generar un error predefinido.
Sintaxis
identificador
mensaje
gravedad
Permite especificar la gravedad del mensaje de error. En general, los mensajes de usuario
tienen una gravedad estrictamente inferior a 20. Por encima de este valor, el error se
considera fatal y se interrumpe la conexión con la base de datos.
estado
argumento
Si el mensaje (predefinido o no) posee parámetros, hay que darles valores a partir de
constantes o de variables.
opción
Existen tres opciones posibles: LOG, NOWAIT y SETERROR. La opción LOG permite
especificar que el mensaje aparecerá en el Visor de sucesos de Windows.
La opción NOWAIT garantiza que el mensaje se enviará al cliente inmediatamente.
Ejemplos
Para definir un nuevo mensaje de error, hay que recurrir al procedimiento almacenado
sp_addmessage.
Sintaxis
@msgnum
Número entero (int) que permite especificar el número del mensaje. Los mensajes definidos
por el usuario pueden tener un identificador comprendido entre 50.001 y 2.147.483.647.
@severity
Número entero (smallint) que especifica la gravedad del mensaje. Debe estar comprendido
entre 1 y 25.
@msgtext
Cadena de caracteres que contiene el texto presentado cuando se produce el error.
@lang
Cadena de caracteres que indica el idioma del mensaje. En primer lugar, el mensaje debe
definirse en inglés ‟us_english‟, y después puede localizarse en español indicando
‟spanish‟.
@with_log
@replace
Permite solicitar la eliminación del mensaje que posea el mismo número que el que se está
generando, si es que existe.
Para conocer los diferentes códigos de idioma, basta ejecutar el procedimiento sp_helplanguage
sin ningún parámetro.
Es posible definir variables en el texto del mensaje para personalizar el texto del mensaje
en función del contexto del que surge. Por tanto es posible, por ejemplo, saber el nombre
del usuario o de la tabla afectada por la operación.
Para introducir valores obtenidos de variables en el texto del mensaje de error es necesario
precisar cómo se va a convertir e introducir el valor en el texto. El formato sigue siempre la
forma siguiente:
indicador
Este indicador, que puede ser +, -, 0, # o espacios, tiene como objetivo la justificación de
los datos de tipo numérico con relleno de ceros y determinar el comportamiento que se ha
de seguir para mostrar los valores señalados.
anchura
Permite definir el número de caracteres que requerirá la representación textual del valor
numérico.
precisión
tipo
Tipo Representa
doi Entero con signo
u Entero sin signo
s Cadena de caracteres
o Un número en octal (base 8)
xoX Un número en hexadecimal (base 16)
Al definir el mensaje en inglés, hay que utilizar parámetros %s para insertar un dato de tipo
carácter y %d si el valor es numérico. En las versiones localizadas del mensaje, hay que
utilizar %1 para hacer referencia al primer parámetro definido en el texto del mensaje en
inglés, %2 para el siguiente y así sucesivamente.
Sintaxis
Ejemplo
En Transact SQL, existen dos medios de gestionar los errores que pueden producirse
durante la ejecución de código.
Para SQL Server un procedimiento almacenado puede definirse como una serie de
instrucciones Transact SQL, almacenadas en la base de datos y perfectamente identificadas
por su nombre. Para permitir que esta serie de instrucciones se adapte al mayor número de
casos, algunos valores de las secuencias de comandos son parametrizables en el momento
de llamar al procedimiento. Como toda serie de instrucciones Transact SQL, es posible por
ejemplo encontrar una instrucción SELECT. La ejecución del procedimiento desencadenará
la ejecución de la consulta y el resultado será enviado al entorno que ha solicitado la
ejecución del procedimiento.
Encadenamiento de instrucciones.
Mejora del rendimiento.
Seguridad de ejecución.
Manipulación de los datos del sistema.
Implementación de las reglas de negocio.
Tratamientos en cascada.
Sintaxis
CREATE PROC[EDURE] nombre[;número][(param1[,...])][{FOR REPLICATION|WITH
RECOMPILE}][WITH ENCRYPTION]AS instrucciones.
nombre
número
param1,...
Parámetro en la forma:
FOR REPLICATION
WITH RECOMPILE
El procedimiento será recompilado en cada ejecución.
WITH ENCRYPTION
Ejemplos
Una función acepta entre 0 y 1.024 parámetros de entrada y devuelve un valor escalar o una
tabla.
Es posible definir un valor por defecto para cada uno de los parámetros de la función
utilizando la palabra clave DEFAULT. Pero, al llamar a la función, se debe especificar la
palabra clave DEFAULT para utilizar el valor por defecto. Este comportamiento difiere del
de los procedimientos almacenados, donde el valor por defecto se tiene en cuenta de forma
automática si el parámetro no se especifica en el momento de la llamada.
Las funciones de tipo escalar devuelven, gracias a la palabra reservada RETURN, un valor
escalar. Por supuesto, los datos de tipo timestamp, definidos por el usuario o cursor, no
pueden ser devueltos. Es el mismo caso para los tipos de datos text, ntext e image.
Las funciones de tablas devuelven como resultado una tabla. No contienen ningún cuerpo y
la tabla es el resultado de un solo comando SELECT. Si la función está compuesta de
varias instrucciones, las instrucciones están encuadradas por las palabras reservadas
BEGIN y END.
Las funciones disponen de un campo de acción limitado, y en ningún caso pueden cambiar
su entorno de ejecución. Desde una función no es, pues, posible cambiar el contenido de
una tabla de la base de datos. Dentro de una función, las únicas acciones posibles son las
que modificarán los objetos locales en dicha función.
Desde el momento en que la función ha sido creada por medio de la instrucción CREATE
FUNCTION , la cláusula WITH SCHEMABINDING permite vincular la función a todos
los objetos a los que ésta hace referencia. Desde ese momento, cualquier modificación
(ALTER) o eliminación (DROP) de esos objetos está destinada al fracaso. Esta cláusula, no
obligatoria, supone que todos los objetos a los que se hace referencia pertenezcan a la
misma base de datos y que el propietario de la función posea un derecho de REFERENCE
sobre los objetos a los que hace referencia la función.
1. Creación de funciones
Funciones escalares
Ejemplos
Creación de una función que devuelve una tabla y que permite conocer, la cantidad de
pedidos realizados por el cliente que se toma como parámetro y el importe medio de dichos
pedidos.
El operador Xxxxx APPLY permite relacionar los datos de una tabla/vista de la base de
datos con una función de tipo tabla.
Con CROSS APPLY, todas las filas de la tabla/vista están presentes en el conjunto de
resultados aun si la función de tipo tabla devuelve un valor nulo.
Con OUTER APPLY, sólo están presentes en el conjunto de resultados las filas de la
tabla/vista para las que la función tabla devuelva un valor no nulo.
Ejemplo
Relacionar los datos de los clientes (nombre y apellido) con el análisis que se ha realizado
de sus pedidos con la función AnalizarCli, que devuelve una tabla.
El contexto de ejecución
El contexto de ejecución está directamente relacionado con la conexión y con el usuario de
base de datos asociado. El contexto de ejecución permite establecer la lista de las acciones
posibles y las que no lo son. Esta lista se realiza a partir de los privilegios otorgados al
usuario, ya sea directamente o a través de roles.
En algunos casos, puede ser necesario y deseable modificar el contexto de ejecución para
beneficiarse de privilegios ampliados, pero únicamente en el marco de una secuencia de
comandos, de un procedimiento o de una función.
EXECUTE AS
Mediante esta instrucción es posible solicitar la conexión a la base mediante una conexión
diferente de la que está en curso. Esta instrucción puede ser ejecutada de forma autónoma
en una secuencia de comandos Transact SQL o bien ser utilizada como cláusula en la
creación de un procedimiento, una función o un trigger.
Para los procedimientos, las funciones y los trigger, la cláusula EXECUTE AS proporciona
mucha flexibilidad de programación y permite a un usuario realizar acciones para las que
no tiene privilegios. Para el desarrollador, el cambio de contexto de ejecución permite
asimismo garantizar que la buena ejecución del código no se verá obstaculizada por un
problema de derechos de acceso a los datos.
Durante la ejecución de una secuencia de comandos de Transact SQL, la instrucción
EXECUTE AS permite realizar por ejemplo de manera puntual operaciones que necesitan
privilegios elevados mientras que el resto de la secuencia de comandos no los necesita.
SETUSER
Original_Login
REVERT
Ejemplo
Desencadenadores (triggers)
SQL Server ofrece dos tipos de desencadenadores (triggers): los DML y los DDL.
Los desencadenadores DML existen desde hace tiempo en SQL Server y están presentes en
muchas bases de datos. Es el tipo de desencadenador que veremos aquí.
WITH ENCRYPTION
La definición del desencadenador está grabada de forma cifrada. Por lo tanto, no es posible
conocer el código del desencadenador a posteriori. Esta acción también evita que el
desencadenador se publique como parte de una duplicación.
FOR
Permite especificar a qué orden SQL DML está asociado el desencadenador. Por defecto, el
desencadenador es de tipo AFTER.
AFTER
INSTEAD OF
INSERT,UPDATE, DELETE
Un desencadenador puede reaccionar ante una o más acciones. En este caso se separan las
acciones mediante comas.
WITH APPEND
IF UPDATE (columna)
Sólo puede ser utilizado por los desencadenadores UPDATE o INSERT y únicamente se
ejecutará si afecta a la columna o las columna(s).
IF (COLUMNS_UPDATED ()operador_comparación_bits)
Esta función permite conocer los índices de la columna o columnas que han sido
actualizadas. Para cada columna afectada por la actualización, se activa un bit. Para saber
qué columnas han sido actualizadas, basta una simple comparación binaria.
Instrucciones_SQL
CREATE y DROP.
ALTER TABLE y
ALTER DATABASE.
TRUNCATE.
GRANT y REVOKE.
UPDATE STATISTICS.
RECONFIGURE.
LOAD DATABASE.
Los desencadenadores de tipo AFTER sólo pueden establecerse en las tablas; no es posible
establecer tales desencadenadores en las vistas. Es posible crear varios desencadenadores
after para una misma tabla y una misma orden SQL (insert, update o delete) de
desencadenamiento. Si existen varios desencadenadores, el procedimiento almacenado
sp_settriggerorder permite fijar el desencadenador que se ejecutará en primer lugar y el que
se ejecutará el último. Los demás desencadenadores se ejecutarán siguiendo un orden
aleatorio.
Si una tabla posee una acción en cascada, no es posible establecer un desencadenador
INSTEAD OF.
SQL Server puede autorizar la recursividad de los triggers si la opción de base de datos
‟recursive triggers‟ ha sido activada por medio de ALTER DATABASE. Esta opción
permite dar mayor potencia a los desencadenadores, pero a veces puede ser peligroso
utilizarla.
La recursión directa está gestionada por el parámetro recursive trigger. Autoriza, por
ejemplo, a un desencadenador establecido sobre la tabla CLIENTES y asociado a la orden
INSERT, a contener una orden INSERT sobre esta misma tabla CLIENTES. Esta segunda
orden INSERT provoca la ejecución del desencadenador.
La recursión indirecta está gestionada por el parámetro de servidor nested triggers del
procedimiento sp_configure. Para ilustrar la recursión indirecta, debemos considerar que un
desencadenador establecido sobre la tabla de PEDIDOS y asociado a la orden INSERT
provoca una orden INSERT en la tabla de CLIENTES, y que el desencadenador asociado
provoca a su vez una orden INSERT sobre la tabla de PEDIDOS.
Para evitar cualquier bloqueo definitivo, los desencadenadores no pueden contar con más
de 32 niveles de anidamiento (o anidación).
Al modificar datos, SQL Server crea filas en tablas de trabajo con la misma estructura que
la tabla modificada: las tablas inserted y deleted.
En una consulta INSERT, la tabla inserted contiene una copia lógica de las filas creadas.
En una consulta UPDATE, las filas con las modificaciones se colocan en la tabla inserted y
las filas que es preciso modificar, en la tabla deleted. Puede accederse a las tablas inserted y
deleted durante la ejecución del trigger.
Ejemplos
Introducción
La gestión de los datos se lleva a cabo cada vez más en entornos de red heterogéneos, es
decir, con varios servidores SQL Server que deben comunicarse entre sí, o con datos no
almacenados en SQL Server instalados en puestos clientes, o incluso con aplicaciones que
manejan datos de varios servidores SQL y de otros gestores de datos (Access, Oracle...).
Estos entornos pueden presentar muchos problemas, entre los cuales cabe destacar los
siguientes:
Las diferentes funciones del administrador y del implementador de bases de datos de SQL
Server consisten en:
la gestión de la integridad de los datos entre varios servidores a los que accede la
misma transacción,
el acceso de las aplicaciones a datos heterogéneos (SQL Server y otros sistemas de
gestión de datos).
SQL Server 2008 propone toda una gama de soluciones para asegurar estas diferentes
funciones:
Para el administrador:
Para el desarrollador:
el "commit" en dos fases, que permite asegurarse de que una transacción que utilice
varios servidores se valide correctamente en todos los servidores.
las API (Application Program Interface) del servidor y del cliente, que proporcionan
al desarrollador las funciones para las conexiones, el acceso a los datos o las
pasarelas hacia otros entornos.
SQL Server Integration Services se puede utilizar también para realizar tareas
administrativas como la salvaguarda de las tablas, de las vistas, de los procedimientos... De
esta manera es posible automatizar dichas tareas y planificar su ejecución.
SSIS también puede ser utilizado por el administrador para incorporar datos existentes en
archivos planos sobre la actual base de datos.
1. Principios de funcionamiento
El servicio SSIS propiamente dicho, con el que SQL Server Management Studio
puede seguir la ejecución de paquetes en curso y gestionar el almacenamiento de
paquetes.
El modelo de objetos (Object Model) de SSIS en forma de API permite acceder a
las herramientas SSIS, trabajar con utilidades de línea de comandos y personalizar
las aplicaciones.
El runtime SSIS permite la ejecución de paquetes y gestiona todos los elementos
asociados: registros, configuración de conexiones, transacciones...
El flujo de datos. Este componente integra el motor de gestión de datos que lee la
información desde la fuente y la almacena en búferes de memoria antes de escribirla
en su destino. Las transformaciones se aplican a los datos almacenados en búferes
antes de escribirlos en su destino.
El siguiente esquema ilustra la integración y las relaciones que pueden existir entre estos 4
componentes en la construcción de SSIS:
SSIS soporta igual de bien el código nativo que el generado por el Framework. Por
ejemplo, se pueden escribir tareas de transformación personalizadas en C++ y producir con
ellas un ejecutable, o bien en C# y producir código gestionado por el Framework .NET.
2. Herramientas gráficas
Ya que el servicio de integración de datos puede utilizarse tanto en bases OLAP como
OLTP, puede trabajarse con SSIS perfectamente desde SQL Server Management Studio
para bases OLTP y desde Business Intelligence Development Studio para las soluciones de
reporting.
Esta utilidad permite definir paquetes y personalizarlos. Desde esta consola se crean e
implementan los paquetes SSIS.
En el nivel de SSIS, SQL Server Management Studio representa una consola de gestión de
paquetes y de puesta en producción. Permite realizar las siguientes operaciones:
Para definir un paquete SSIS, el asistente deberá definir los siguientes elementos:
La fuente y el destino de los datos. Después del tipo de fuente y de destino, puede
pedir opciones de configuración como el delimitador de campo para la exportación
en un archivo plano.
Validar y eventualmente modificar las correspondencias entre la fuente y el destino.
Sólo queda guardar el paquete SSIS en la base de datos MSDB o en forma de archivo. Si el
asistente se ejecuta desde SQL Server Management Studio, se puede ejecutar de inmediato.
Para ejecutar el asistente desde SQL Server Management Studio, hay que realizar las
siguientes manipulaciones:
Para ejecutar el asistente desde Business Intelligence Development Studio, hay que realizar
las manipulaciones siguientes:
Ejemplo
El ejemplo siguiente ilustra el uso del asistente para importar datos desde un archivo de
texto. De entrada, aparece la pantalla de bienvenida:
Desde la vista Avanzadas, el botón Sugerir tipos permite analizar las primeras filas del archivo
origen para determinar con la mayor exactitud posible los tipos de datos de la tabla de destino. De
manera predeterminada, solamente se analizan las 100 primeras filas, pero es posible precisar el
número de filas que analizar.
El destino se selecciona en el paso siguiente. Después de seleccionar la instancia SQL
Server a la que hay que conectarse, se puede crear una nueva base de destino por medio del
botón Nueva.
Después hay que dar un nombre y una descripción al paquete, además de indicar la
instancia de SQL Server en la que se grabará.
Antes de salir del asistente, se presenta un resumen de las opciones elegidas y las tareas que
se van a realizar.
Con este diseñador de paquetes SSIS, se pueden definir paquetes complejos. Aunque se
pueda diseñar todo el paquete desde cero, parece razonable partir cuando sea posible de uno
creado con el asistente y personalizarlo.
SSIS Designer está disponible desde Business Intelligence Development Studio cuando se
trabaja en un proyecto de tipo Integration Services.
Para crear un proyecto de este tipo en Business Intelligence Development Studio, hay que
seleccionar Archivo - Nuevo - Proyecto en el menú. En la ventana de creación de nuevo
proyecto, hay que seleccionar un proyecto de tipo Integration Services y escribir su
nombre.
Una vez creado, el proyecto aparece directamente SSIS Designer con un paquete
predeterminado.
Flujo de control
Flujo de datos
Controladores de eventos
Explorador de paquetes
Durante la ejecución de un paquete aparece una quinta ficha para seguir el avance de la
ejecución y visualizar su resultado.
SSIS Designer dispone también de una ventana para gestionar las conexiones con los
distintos orígenes de datos a los que accede el paquete.
Para asignar una conexión a un componente, basta seleccionar la conexión desde la ventana
Administradores de conexión y arrastrarla sobre el componente.
También es fácil desarrollar un paquete como el que ilustra el ejemplo siguiente:
La tarea de transferencia de datos se detalla en la ficha Flujo de datos. En este caso, la barra
de herramientas de SSIS también presenta las opciones estándar para este nivel.
5. Otras utilidades
a. Ejecutar Paquete
Esta utilidad permite configurar y ejecutar paquetes en el ordenador, así como generar la
línea de comandos para una utilización con dtexec .
Para acceder a esta utilidad hay que conectarse desde SQL Server Management Studio a un
servidor de tipo Integration Services, como se indica en el ejemplo siguiente.
Se puede abrir una conexión nueva a través del menú Archivo - Conectar con Explorador de
objetos.
A continuación, la utilidad pedirá la ejecución del paquete a partir del menú contextual, tal
y como ilustra el ejemplo siguiente:
Esta utilidad permite ejecutar un paquete SSIS desde la línea de comandos. Se puede
configurar el uso del paquete por medio de las diferentes opciones de dtexec.
dtutil
Esta utilidad de línea de comandos permite gestionar los paquetes existentes que estén
almacenados en la base de datos msdb o en forma de archivos. También permite copiar,
eliminar, renombrar o sencillamente verificar la existencia de un paquete.
Aunque sea relativamente implícito para una utilidad de línea de comandos, es preferible
gestionar los paquetes SSIS desde SQL Server Management Studio siempre que sea
posible.
Es la solución más sencilla para separar una base de datos. Debe seleccionar la opción
Tareas - Separar desde el menú contextual asociado a la base de datos.
Quitar conexiones: si hay usuarios conectados, habilitando esta casilla se pondrá fin
a su conexión.
Actualizar estadísticas: se recomienda actualizar las estadísticas de las tablas antes
de utilizarlas.
Mantener catálogos de texto: esta opción, que está habilitada de forma
predeterminada, permite conservar los catálogos de texto integral en la base de
datos separada.
Después del proceso, la base de datos habrá quedado separada. Ya sólo faltará, si es
necesario, desplazar los archivos por medio de instrucciones de manipulación de archivos.
@dbname
@skipchecks
¿Hay que actualizar las estadísticas o no? La opción predeterminada es NULL. Si se
especifica false, se ejecutará el comando UPDATE STATISTICS; si se selecciona true, las
estadísticas no se actualizarán. De forma predeterminada, se actualizan las estadísticas de
tablas e índices. Esta opción es especialmente importante para las bases de datos.
@KeepFullTextIndexFile
Ejemplo
Esta operación puede realizarse con una base de datos que se haya separado correctamente
a través del procedimiento que ofrece SQL Server Management Studio o mediante
sp_detach_db.
Desde la ventana de transacciones Adjuntar bases de datos, hay que localizar los archivos
de datos y registro de transacciones de la base de datos a adjuntar. A partir del archivo
MDF, el asistente localiza el archivo de registro de transacciones y los demás archivos de
datos.
Después de ejecutar la operación, la base de datos vuelve a ser accesible para los usuarios.
Hay que utilizar la instrucción CREATE DATABASE con la opción FOR ATTACH.
nombreBaseDeDatos
Nombre de la base de datos a adjuntar.
descripciónArchivo
FOR ATTACH
FOR ATTACH_REBUILD_LOG
Ejemplo
El programa BCP
BCP (Bulk Copy Program) es una utilidad de importación de datos desde un archivo del
sistema operativo hacia una tabla, existente o no, y de exportación de los datos desde una
tabla o una vista hacia un archivo del sistema operativo.
Es interesante combinar osql y bcp en un proceso por lotes. Osql puede eliminar y volver a
crear posteriormente los índices y las restricciones y validar los datos; bcp asegura la
transferencia.
Aunque BCP es una herramienta con un buen rendimiento, las soluciones de importación y
exportación en línea de comandos pueden realizarse definiendo un paquete SSIS guardado
en un archivo e iniciado por medio de la utilidad dtsrun .
Sintaxis
nombretabla |"consulta"
archivos_datos
-m num_max_errores
Número máximo de errores posibles antes de que la copia de datos sea cancelada.
-f formato
Nombre completo del archivo que contiene las respuestas guardadas de una utilización
anterior de bcp.
-x
Utilizado conjuntamente con las opciones format y f, permite trabajar con un archivo de
datos de formato XML.
-e archivo_error
-F primera_fila
-L última_fila
Número de la última fila del archivo que se debe tener en cuenta al importar datos desde
dicho archivo. Por defecto, se trata del valor 0, que corresponde a la última fila del archivo.
-b tamaño_batch
-n
-c
-w
-N
Copia por bloque utilizando los tipos de datos por defecto para los datos que no son de tipo
carácter y el tipo unicode para los datos de tipo carácter.
-V (60 | 65 | 70 | 80 | 90)
Copia en bloque utilizando los tipos de datos de las versiones anteriores de SQL Server.
-6
-q
Este parámetro permite precisar el tipo de codificación utilizado para los caracteres. ACP
para utilizar la página ANSI/Windows n°1252. OEM permite utilizar la página
predeterminada del cliente. Es la opción predeterminada si no se especifica la opción -C.
RAW permite no realizar ninguna conversión entre la página de códigos del servidor y la
de destino. página_códigos representa el número de la página de códigos a utilizar.
-t fin_campo
-r fin_fila
-i archivo_entrada
Nombre del archivo que contiene las respuestas a las preguntas para cada campo, en el caso
de una copia por bloque en modo interactivo.
-o archivo_salida
-a tamaño_paquetes
-S nombre_servidor [\nombre_instancia]
-U nombre_usuario
Nombre que el usuario de SQL Server ha utilizado para conectarse.
-P contraseña
-T
-v
-R
Utilizar el formato regional para los datos de tipo fecha y hora y los datos monetarios.
-k
-E
-h "opción [,...n]"
Opciones que es preciso especificar con vistas a una exportación hacia una versión 6.5 o
anterior de SQL Server.
Ejemplo
Exportación hacia un archivo ASCII cuyo separador de campos es la coma y cuyo carácter
separador de registros es un retorno de carro:
Su interés radica en que gestiona las conexiones en modo local y al tiempo que permite a
los usuarios ejecutar procedimientos almacenados en el servidor remoto.
Estos usuarios se denominan "usuarios remotos" y deben contar con un nombre de acceso
en el servidor remoto.
Antes de poder utilizar esta funcionalidad, habrá que añadir los servidores remotos,
configurarlos y gestionar los usuarios remotos.
Esta configuración podrá hacerse en el SQL Server Management Studio, visualizando las
propiedades de un servidor (ficha Conexiones, área Conexiones a servidores remotos).
Para trabajar con servidores y datos remotos, el método más sencillo en SQL Server
consiste en establecer un vínculo con el servidor remoto. Esta conexión permite identificar
con exactitud al servidor remoto y cómo se abre la sesión de usuario.
La gestión de estos servidores puede realizarse tanto desde Transact SQL como desde SQL
Server Management Studio. Todas las informaciones relativas a estas inscripciones se
guardan en la tabla sys.servers. Se puede interrogar al procedimiento sp_linkedservers para
obtener todos los datos relativos a los servidores vinculados.
Para agregar un servidor vinculado a través de SQL Server Management Studio, seleccione
la opción Nuevo - Servidor vinculado en el menú contextual asociado a la carpeta Objetos
de servidor.
@server
Los datos ofrecidos aquí conciernen únicamente al vínculo entre servidores SQL Server.
b. Eliminar un servidor vinculado
Esta operación puede realizarse por medio del procedimiento almacenado sp_dropserver o
desde SQL Server Management Studio seleccionando la opción Eliminar en el menú
contextual asociado al servidor vinculado.
@server
@droplogins
Si ello no es posible, hay que definir cuentas de seguridad SQL Server para la
correspondencia entre conexiones locales y una cuenta de conexión remota.
Esta tarea puede llevarse a cabo desde SQL Server Management Studio o a través de los
procedimientos Transact SQL sp_addlinkedsrvlogin y sp_droplinkedsrvlogin.
Para trabajar con una tabla o un objeto remotos, hay que utilizar el nombre completo del
objeto (nombreBase.nombreEsquema.nombreObjeto) precedido por el nombre del servidor
remoto.
4. Los sinónimos
Los sinónimos SQL Server no se limitan a los objetos remotos, sino que también permiten
definir términos alternativos para las tablas, vistas, procedimientos, funciones... para
adaptar los objetos de la base de datos al vocabulario de los usuarios. Por ejemplo, hay
quienes hablan de artículos y otros de productos, igual que se habla de asalariados,
empleados y colaboradores. Al ofrecer la posibilidad de tener varios términos para hacer
referencia al mismo objeto, la estructura de la base de datos se vuelve totalmente adaptable.
Sintaxis
Ejemplo
Por supuesto, los sinónimos son eliminados por la instrucción DROP SYNONYM
nombreSinónimo.
Cuando se trabaja con un sinónimo, a veces es interesante saber el tipo de base del
sinónimo: es decir, identificar el objeto del cual es sinónimo. El primer reflejo para obtener
este tipo de información es sin ninguna duda recorrer las tablas del sistema y en particular
la vista sys.synonyms. Pero también es posible recurrir a la función
OBJECTPROPERTYEX , que permite identificar rápidamente el tipo de base para el
sinónimo indicado en el parámetro.
La administración de las transacciones
distribuidas
Una transacción distribuida es un conjunto de instrucciones de una aplicación que
actualizan los datos en, al menos, dos servidores. Para prevenir la aparición de problemas
de integridad y de coherencia de datos en caso de validación incompleta, deben
implementarse medios de prevención y corrección de errores. Con SQL Server, estos
medios son, por una parte, el servicio MS DTC (Distributed Transaction Coordinator), en
los servidores o los clientes WINDOWS, y por otra, el Transact-SQL y los procedimientos
almacenados remotos.
Por otro lado, se pueden distinguir tres tipos de participantes en la implementación de esta
funcionalidad, a saber:
1. MS DTC
2. Implementación en Transact-SQL
Ejemplo
Ejecución de una transacción en el servidor BRUNO, que actualiza un cliente en una base
local y efectúa inmediatamente la misma actualización en una base de SRV01 (el
procedimiento DIRECCLI recibe el número del cliente que se debe modificar y su nueva
dirección).
Se puede configurar el servidor o la sesión para llevar a cabo una ejecución sistemática de los
procedimientos almacenados remotos en transacción distribuida mediante sp_configure remote
proc trans o set remote_ proc_transactions.
Introducción
Los datos utilizados en el contexto de las aplicaciones no cesan de evolucionar. Por tanto es
normal que los servidores de bases de datos también evolucionen proponiendo tipos
adaptados a estos nuevos formatos. Es lo que hace SQL Server al ofrecer la posibilidad de
almacenar datos en formato xml y datos geográficos, además de una mejor gestión de los
documentos anexos (imagen, vídeo, sonido, documento digitalizado…) para no recargar el
proceso de administración de la base pero vinculando los datos relacionales a estas
informaciones almacenadas directamente en el sistema de archivos.
Se pueden almacenar datos en formato relacional o en formato XML. Cada uno de estos
dos formatos tiene sus ventajas y sus inconvenientes.
SQL Server alberga un motor relacional para almacenar y trabajar con datos guardados con
este formato. Sin embargo, SQL Server también ofrece la posibilidad de gestionar los datos
en formato XML. De esta forma, sea cual sea el modo de almacenamiento utilizado, SQL
Server puede guardar los datos en formato nativo.
El siguiente esquema ilustra el hecho de que las aplicaciones trabajan tanto con datos de
formato relacional como con formato XML.
Elección de un formato
Los dos formatos no compiten entre sí, sino que se complementan. El motor de base de
datos debe tener la capacidad de gestionar los datos de forma óptima con independencia de
su formato de almacenamiento.
No obstante, el formato relacional permite garantizar una mejor homogeneidad de los datos,
ya que las tablas están muy estructuradas. La estructura en tablas de datos permite
almacenar un gran volumen de información de forma fiable, y las consultas permiten
extraer datos de forma rápida y eficaz. Sin ninguna duda, éste es el mejor formato para
almacenar un gran volumen de información y trabajar con él.
La siguiente tabla indica cuál de los dos formatos es mejor en función de la estructura
inicial de los datos:
1. El tipo XML
SQL Server ofrece un tipo de datos XML para almacenar los datos en formato nativo XML.
Este tipo no es un campo de texto de grandes dimensiones, como nvarchar(max) por
ejemplo. Si no existen motivos puramente relacionados con el almacenamiento que lo
impidan, el tipo XML permite realizar consultas de información precisas. También se
pueden definir índices en las columnas XML para acelerar el procesamiento de las
consultas.
Se pueden crear tablas relacionales que, además de las columnas de los tipos habituales,
contengan una o más columnas de tipo XML.
Las columnas de tipo XML utilizan formato binario (blob) para almacenar la información
en la base de datos relacional, de forma que el documento XML se conserva en el estado
correcto. De hecho, el espacio para cada dato XML está limitado a 2 GB. Además, el
documento XML no debe estar estructurado con una jerarquía de más de 128 niveles.
Los datos XML están definidos en UTF-16 por SQL Server 2005.
Para almacenar datos directamente en formato XML, SQL Server 2005 evita tener que
hacer un trabajo largo y pesado para definir las correspondencias entre el formato XML y la
estructura relacional con la que están organizada la información en la base de datos. Este
tipo dispone de los métodos query(), exist(), value(), nodes() y modify() para trabajar con
los datos. Estos métodos se basan en XQuery, un subconjunto de XML específico para
consultas.
Para satisfacer las exigencias del consorcio W3C, se puede asociar una colección de
esquemas a una columna de tipo XML. Los datos almacenados en la columna deberán
respetar las restricciones del esquema. Esta columna se denominará entonces XML con
tipo; si no, se tratará de una columna XML sin tipo.
El tipo XML tal y como está definido en SQL Server 2005 respeta la definición
normalizada por el estándar ISO SQL-2003, es decir que trabaja con documentos XML 1.0
bien formados y con fragmentos XML.
Sin embargo, la columna que utilice un tipo XML sin tipo, es decir no basado en un
esquema XML, sólo contendrá datos conformes con un documento XML 1.0 bien formado
o un fragmento XML.
Debe utilizarse cuando no se disponga de esquema XML, o cuando haya varios esquemas
XML asociados a orígenes externos de datos.
Ejemplo
La tabla catálogo se crea con una columna XML sin tipo:
Si los datos que irán en una columna XML están descritos en una colección de esquemas
XML, se puede asociar esta colección de esquemas XML a la columna. Entablando esta
asociación en el nivel de la definición de la columna todos los datos escritos en ella deben
respetar un esquema XML asociado. Entonces se dice que la columna está definida en
XML con tipo.
Los esquemas XML actúan como una restricción de integridad potente que garantiza una
estructura claramente identificada para todos los datos presentes en esta columna. Las
actualizaciones de datos XML se controlan mejor y más rápido en el proceso de ejecución
de las consultas.
Al definir la columna se pueden usar las palabras clave DOCUMENT y CONTENT para
especificar que contendrá documentos XML bien formados, es decir con un solo elemento
en el nivel superior. En el caso de CONTENT, la columna contendrá datos de formato
XML. Si no se especifica nada más en la definición de la columna, se aplica de forma
predeterminada la opción CONTENT.
La colección de esquemas XML debe estar creada antes de que se pueda hacer referencia a
ella en una columna XML. La gestión de colecciones de esquemas se realiza con las
instrucciones CREATE XML SCHEMA COLLECTION , ALTER XML SCHEMA
COLLECTION y DROP XML SCHEMA COLLECTION. Cada colección puede contener
uno o más esquemas XML. Esta gestión de colecciones hace mucho más flexible la gestión
de columnas XML con tipo, ya que siempre se puede agregar un esquema XML a la
colección para responder a nuevas restricciones, funcionalidades o formatos de gestión de
datos.
Sin embargo, durante la definición del esquema, no siempre es posible definir el conjunto
de posibilidades. SQL Server soporta las declaraciones any, anyAttribute y anytype en la
definición de esquemas.
Sintaxis
Ejemplo
Ejemplo
Sin embargo, la definición no siempre es tan sencilla y los datos obligatorios pueden ser
completados por datos específicos en casos bien concretos. Por ejemplo, en el caso aquí
mostrado, puede ser interesante completar la información general de un cliente con
información puntual cuyos criterios no necesariamente están definidos de antemano (un
número de teléfono adicional, detalles sobre la entrega, gustos particulares…). Mediante la
etiqueta any es posible adaptar así el esquema XML, con lo que en este caso obtenemos:
minOccurs:
maxOccurs:
namespace:
processContents:
este parámetro permite indicar a SQL Server cómo validar los elementos opcionales en
relación a un esquema.
Tanto si la columna es con tipo como si no, se pueden manipular los datos por medio de las
instrucciones DML INSERT, UPDATE, DELETE y SELECT. No obstante, estas
instrucciones se comportan con los datos XML como columnas basadas en un tipo
relacional clásico, es decir que manipulan toda la información presente en la columna.
Es posible trabajar con datos de tipo fecha y hora (datetime, date y time) en documentos
XML de manera sencilla. Para ello, los datos de tipo fecha y hora se escriben mediante el
formato YYYY-MM-DDThh:mm:ss:nnnZ para expresar una hora GMT o bien YYYY-
MM-DDThh:mm:ss:nnn±hh:mm para expresar la díferencia horaria respecto a la hora
GMT.
Este formato de fecha y hora cumple la forma ISO 8601. La utilización de esta norma
permite transferir fácilmente datos de tipo fecha y hora de un entorno a otro.
Ejemplo
Fila agregada a una columna XML sin tipo, con importación de datos desde un archivo.
b. Métodos específicos
Al buscar datos, el usuario puede desear recuperar únicamente los datos pertinentes a partir
de la fuente XML. Para hacer una analogía, el problema es similar al de los datos de texto
cuando el usuario sólo desea conocer un subconjunto de la cadena de caracteres
almacenada en la base de datos. Para cubrir esta posibilidad, SQL Server ofrece numerosas
funciones de manipulación de cadenas de caracteres. Para extraer partes de un documento
XML, SQL Server ofrece los métodos query(), value(), exist() y nodes(). SQL Server
también dispone del método modify() para modificar datos XML.
Query()
Este método acepta como parámetro una consulta de formato XQuery que haga referencia a
la lista de nodos del documento. Devuelve un elemento XML sin tipo, extraído de la
columna de tipo XML.
Ejemplo
value()
Este método devuelve un valor escalar extraído del documento XML. Acepta como
parámetro una consulta XQuery y el nombre del tipo de datos del valor devuelto.
Ejemplo
El ejemplo siguiente permite conocer la referencia y el precio del primer artículo presente
en el documento XML que tiene el número 1.
exist()
Este método, que acepta como parámetro una consulta de tipo XQuery, devuelve un valor
escalar de tipo bit:
Resulta útil trabajar con este método en conjunto con el método value para no generar un
error cuando la consulta XQuery no ofrece resultados.
Ejemplo
nodes()
Este método es útil cuando se desea obtener las correspondencias entre el tipo XML y un
almacenamiento de datos en formato relacional. A partir de una consulta XQuery pasada
como parámetro, este método permite obtener tanto filas como nodos definidos en este
nivel. Cada fila del conjunto de resultados está en formato XML, pero así resulta fácil
dividir en partes correctamente un documento XML.
Ejemplo
A partir de un dato de tipo XML almacenado en una variable, se dividen datos en función
de la consulta XQuery que se pasa como parámetro al método nodes. El conjunto de
resultados se presenta a continuación, aunque también puede almacenarse en una columna
de tipo XML de una tabla de la base de datos.
modify()
El método modify permite modificar una parte de los datos almacenados en un documento
xml. Al contrario que la instrucción update, que permite actualizar el contenido global de
una columna, el método modify permite modificar valores directamente en la columna de
tipo xml. El método modify permite añadir valores, modificar valores existentes y suprimir
valores. Para realizar estas tres operaciones, el método modify utiliza las expresiones XML
DML: insert, replace value of y delete.
Ejemplo
SQL Server ofrece la posibilidad de definir índices sobre las columnas de tipo XML.
Cuando tiene lugar una consulta, los datos XML se procesan en el nivel de cada fila, lo que
puede provocar que los procesamientos sean largos y costosos, sobre todo si la consulta
afecta a una gran cantidad de filas o cuando los datos de formato XML son voluminosos.
También es posible definir un índice de texto integral sobre las columnas de tipo XML, con el fin de
indexar únicamente el contenido e ignorar las marcas XML.
a. Índice principal
El índice principal para una columna de tipo XML necesita que la tabla posea un índice
organizado en función de la clave principal.
Sintaxis
Ejemplo
b. Índice secundario
El documento XML sólo puede contener 128 niveles como máximo. Los documentos que
posean una jerarquía más compleja se rechazan en el momento de la inserción o la
modificación de las columnas.
De la misma forma, la indexación se realiza sobre los primeros 128 bytes del nodo; los
valores más largos no se tienen en cuenta de cara al índice.
Sintaxis
PATH
Permite construir un índice sobre las columnas path y value (ruta y valor) del índice XML
principal. Este índice permite mejorar claramente las respuestas cuando se utilice el método
exist(), en una clausula where por ejemplo.
PROPERTY
Permite construir un índice sobre las columnas PK, path y value del índice XML principal.
El símbolo PK corresponde a la clave principal de la tabla. Este tipo de índice resulta útil
para utilizar el método value() en consultas SQL de manipulación de datos.
VALUE
Permite construir un índice sobre las columnas value y path del índice XML principal. Este
índice resulta útil principalmente para las consultas en las que se conozca el valor de nodo
independientemente de la ruta de acceso, cosa que puede suceder, por ejemplo, cuando se
utiliza el método exist().
Ejemplo
En el ejemplo siguiente, se crean los tres tipos de índices a partir del índice XML principal
definido para la columna página de tipo XML de la tabla Catálogo.
4. XQuery y Xpath
Los documentos de formato XML son cada vez más populares, por lo que cada vez son más
frecuentes las consultas de este tipo de datos. El lenguaje XQuery tiene el objetivo de ser
un lenguaje tan sencillo y eficaz para consultar datos de formato XML como lo es el
lenguaje SQL para consultar datos almacenados en formato relacional.
Se puede consultar la documentación exacta sobre las reglas que rigen el lenguaje de
interrogación XQuery en la página http://www.w3.org/TR/xquery.
Dentro de XQuery está integrado el lenguaje de navegación XPath 2.0, que corresponde a
consultas XQuery definidas única y enteramente con una ruta. La expresión de esta ruta
permite localizar uno o más nodos en el documento XML de origen. Se puede limitar el
número de nodos seleccionados definiendo filtros. Éstos, a su vez, pueden utilizar los
valores contenidos en los atributos de los nodos para evaluar una condición booleana.
Ejemplo
La consulta XQuery biblioteca/autor/* ofrecerá como resultado solamente los libros, ya que
la ruta de elementos seleccionados debe ser biblioteca/autor/algo.
Ejemplo
Se puede trabajar con los atributos de los nodos XML en la consulta XQuery. Para hacer
referencia a un atributo, hay que anteponer el símbolo @ a su nombre.
Ejemplo
Para presentar el nombre de pila de los autores, hay que utilizar la siguiente consulta
XQuery: biblioteca/autor/@nombre. Para tener la seguridad de que la consulta sólo
producirá un valor único, hay que precisar el número de cada nodo presente en la consulta.
El ejemplo permite conocer el nombre del primer autor y el apellido del segundo autor.
Se puede trabajar con los parámetros para imponer condiciones de selección de nodos. El
filtro expresado entre corchetes permite definir una condición que devolverá un valor
booleano que indicará si el nodo está seleccionado o no.
Ejemplo
Para escribir consultas de extracción de datos aún más flexibles, XQuery ofrece las
instrucciones for, where y return. La construcción de la consulta puede ser más sofisticada
y permitir la extracción de informaciones de forma propia. La consulta XQuery contiene
todos los elementos necesarios para extraer la información del documento en formato
XML.
Ejemplo
En el ejemplo siguiente, se recorre gracias a un bucle for el documento XML en busca de
los autores cuyo nombre es Julio. Cada subconjunto del documento que corresponde a un
paso del recorrido se conserva en la variable $element.
Para cada elemento del bucle for, se aplica una condición suplementaria con el operador
where. En el ejemplo aquí presentado, sólo se conservan los libros identificados como
clásicos.
Durante el recorrido del documento xml, a veces es necesario asignar valores a variables.
Esta operación es posible gracias a la instrucción let, que permite la valoración de una
variable en una expresión XQuery. La consulta XQuery está entonces en situación de
realizar operaciones más complejas, como el recuento.
Ejemplo
Para cada elemento del recorrido, y, por tanto, para cada autor, se cuenta el número de
libros mediante la instrucción count y este valor se asigna a la variable $número.
5. FOR XML
El uso de FOR XML representa un buen medio para gestionar el intercambio en formato
XML con una aplicación cliente. Esta cláusula permite convertir el resultado de una
consulta SELECT en formato XML.
Ejemplo
Ejemplo
Esta directiva TYPE también permite simplificar la escritura de consultas SQL para generar
un documento XML más o menos complejo. Se pueden utilizar todas las funcionalidades de
SQL para generar de forma rápida y simple un documento de formato XML.
Ejemplo
También existe la posibilidad de definir una ruta (PATH) a nivel de la cláusula FOR XML,
o bien directamente en el nivel del alias de columna en la consulta Select.
Ejemplo
El caso anterior se ha revisado indicando las rutas para obtener exactamente el documento
XML deseado.
Este método permite tratar un documento XML en forma de conjunto de resultados. Con
OPEN XML se puede integrar el tratamiento de un documento XML en una consulta SQL
de tipo SELECT, INSERT, UPDATE y DELETE.
Con la aparición del tipo XML, este método se utiliza cada vez menos.
Sintaxis
idoc
consultaXPath
flags
estructuraDatos
Ejemplo
Este método permite acceder de forma fácil a recursos externos al servidor para trabajar
tanto con datos como con datos presentes en forma de tabla en la base de trabajo actual. La
fuente de datos puede ser el sistema de archivos Windows o una fuente OLEDB.
Tal vez sea más conveniente usar este método que el programa de importación bcp.
Sintaxis
OPENROWSET(nombreProveedor,cadenaConexión,consulta)
nombreProveedor
cadenaConexión
Cadena de conexión para conectar con la fuente de datos. Los parámetros de esta cadena
dependen del proveedor OLEDB seleccionado.
consulta
Ejemplo
Esta funcionalidad necesita que el servicio IIS esté instalado y configurado en el servidor
en el que funciona el motor SQL Server. Por ello, la verificación de la disponibilidad del
servidor IIS se realiza en el momento de instalar SQL Server.
En SQL Server es el middleware orientado a mensajería, Service Broker, el principal
usuario de los extremos así definidos. Este servicio se basa en los extremos durante la
puesta en práctica mediante varias instancias de SQL Server.
1. Principios de funcionamiento
Los servicios Web XML nativos de SQL Server tienen el objetivo de facilitar el acceso a la
información para aplicaciones que tengan una necesidad puntual de hacerlo.
Al ofrecer esta solución a través de SOAP , las aplicaciones no Windows pueden acceder
fácilmente a los datos almacenados en una base de datos SQL Server. Los clientes
Windows pueden utilizar tanto MDAC (Microsoft Data Access Component), como
SQLXML 3.0 para trabajar con SQL Server.
Para poder usar los servicios Web XML, las aplicaciones deben disponer de un extremo en
el servidor SQL Server. Este extremo está disponible a través del protocolo HTTP. A cada
extremo definido se asocian procedimientos almacenados y funciones propias de la
aplicación, es decir que para el usuario que acceda por el extremo HTTP sólo estarán
disponibles estos elementos.
Las funciones y procedimientos se clasifican como métodos Web (web methods). Una
colección de métodos web que funcionan entre sí constituye un servicio Web.
El servicio Web se describe con un archivo WSDL que SQL Server puede generar
automáticamente y hacer accesible para el punto de entrada HTTP.
Todas las aplicaciones capaces de trabajar con un servicio Web pueden acceder a la
instancia SQL Server. Como las tecnologías que rigen los servicios Web están
normalizadas y son estables, se puede trabajar con servicios Web por medio de
muchos lenguajes de programación. Por ejemplo, una aplicación escrita en Java
puede acceder fácilmente a datos de una base SQL Server, sin que sea necesario
instalar un controlador JDBC.
Una excelente integración con las herramientas de desarrollo de aplicaciones Web.
De hecho, los resultados están en formato XML y las herramientas de desarrollo de
aplicaciones Web pueden tratar estos datos de forma fácil y eficaz si, por ejemplo,
aplican una hoja de estilo XSL.
Una integración más fácil con los clientes móviles que se conectan al servidor con
frecuencia irregular. Además, el formato XML normalizado permite adaptarse a
todo tipo de aplicaciones, como las desarrolladas para terminales móviles.
Para que sea posible utilizar estos servicios Web, hay que configurar el servidor. Las etapas
de este proceso de configuración son:
Luego habrá que generar el archivo WDSL relativo al servicio Web y, por último, integrar
el uso de estos servicios Web directamente en una aplicación cliente.
Para que SQL Server pueda responder a las solicitudes realizadas a través de un mensaje
SOAP por el protocolo HTTP, hace falta que el servidor pueda escuchar este protocolo.
Debe crearse un directorio virtual o punto de entrada HTTP (http endpoint) que
corresponda a una URL válida y accesible desde el exterior.
Para administrar los puntos de entrada HTTP, SQL Server dispone de las instrucciones
CREATE, ALTER y DROP ENDPOINT .
a. CREATE ENDPOINT
Este método permite crear el extremo HTTP. Se puede definir simultáneamente las
funciones que estarán disponibles en él.
La instrucción se divide en dos grandes partes: primero el protocolo de red permite acceder
al punto de entrada, y luego se exponen los métodos ofrecidos en el servicio Web.
Dado el gran número de opciones que posee este comando, sólo se detallan a continuación los
más significativos.
Sintaxis
nombreExtremo
Nombre lógico del extremo (httpEndPoint). Este nombre permitirá identificar al extremo al
que hagan referencia las instrucciones ALTER ENDPOINT y DROP ENDPOINT.
AUTHORIZATION conexión
Esta opción permite crear un extremo y otorgarle su propiedad a una conexión válida
definida en SQL Server. De forma predeterminada, también es su propietario el creador de
httpEndPoint.
STATE
Permite precisar el estado del extremo, que de forma predeterminada está detenido (no
accesible).
AS {HTTP|TCP}
Permite especificar el protocolo utilizado para acceder al servicio Web. Según el protocolo
definido, las opciones de configuración serán distintas: por ejemplo, LISTERNER_PORT y
LISTERNER_IP si el protocolo es TCP, o PATH, AUTHENTICATION, PORTS, SITE...
si el protocolo es HTTP.
Permite definir la "carga útil" del extremo, es decir las funciones y procedimientos
almacenados que participarán en la definición del servicio Web. Los argumentos que
siguen son propios del tipo de contenido del punto de entrada. Por ejemplo, si el contenido
es de tipo SOAP los argumentos permitirán definir la correspondencia entre el nombre de
procedimientos y funciones y el nombre con el que los identificará el servicio Web.
También se indica el método de construcción del archivo WDSL.
Ejemplo
El extremo está definido para HTTP y el método es accesible por medio de SOAP.
b. ALTER ENDPOINT
Sintaxis
ALTER ENDPOINT nombreExtremo
[ AFFINITY = { NONE | <64bit_integer> | ADMIN } ]
[ STATE = { STARTED | STOPPED | DISABLED } ]
AS { HTTP | TCP } (parámetrosEspecíficosDelProtocolo )
FOR { SOAP | TSQL | SERVICE_BROKER | DATABASE_MIRRORING}
(argumentosEspecíficosDelTipoDeContenido)
Ejemplo
c. DROP ENDPOINT
Sintaxis
Ejemplo
Con los parámetros con valor de tabla es posible administrar un conjunto estructurado de
datos sin necesidad de crear una tabla, ni siquiera temporal. En este sentido, la utilización
de estos tipos permite ganar en flexibilidad de utilización y a veces incluso en rendimiento.
Sin embargo, los parámetros con valor de tabla son siempre parámetros de sólo lectura. Por
tanto, el procedimiento o la función que posee un parámetro de este tipo no puede
modificar los datos presentes en este parámetro.
En el procedimiento o en la función que poseen un parámetro de este tipo, los datos son
extraídos mediante consultas SELECT o mediante la utilización de un cursor.
Ejemplo
Finalmente, una secuencia de comandos Transact SQL permite almacenar los números y
los nombres de los clientes que viven en Barcelona en una variable de tipo tcliente.
1. HierarchyId
Se trata de un tipo de datos específico de SQL Server que puede ser utilizado para crear una
estructura jerárquica en una tabla relacional. Se pueden extraer los datos de esta tabla
mediante consultas jerárquicas.
El tipo hierarchyId ofrece todo el soporte necesario para crear adecuadamente una jerarquía
en las tablas. No obstante, el simple hecho de definir una columna de este tipo en una tabla
no garantiza en ningún caso que los datos se clasifiquen de manera jerárquica. Es el
desarrollador o el usuario final quien tiene que valorar esta columna. De la misma manera,
si se ha de administrar la noción de unicidad de los valores, es necesario definir una
restricción de unicidad.
2. Los índices
Para acelerar el recorrido de los directorios jerárquicos, es posible definir índices. Sin
embargo, los índices sólo serán útiles si respetan dicho árbol de directorios. Puesto que hay
dos maneras de recorrer un árbol, existen dos maneras de definir estos índices. El primer
método es tratar de llegar lo más rápido posible al nivel hoja y a continuación explorar el
conjunto de hojas de una misma rama antes de pasar a la siguiente rama.
3. Los métodos
GetAncestor(nivel)
Este método permite identificar a la jerarquía superior de un nodo. El valor entero pasado
como parámetro permite precisar el número de niveles que hay que subir. Este valor es por
tanto estrictamente positivo e inferior al valor devuelto por GetLevel.
Este método permite saber qué nodo es el descendiente directo del nodo identificado como
padre y en relación al cual se ejecuta el método. En caso de que haya varios nodos hijos es
posible precisar 1 ó 2 hermanos del descendiente para localizar de forma precisa la
ubicación del nodo descendiente. Este tipo de posicionamiento es especialmente útil en el
momento de insertar datos en un árbol seleccionado.
GetLevel()
GetRoot()
Este método permite identificar de forma inmediata el nodo raíz del árbol de directorios.
IsDescendant (nodoPorComprobar)
Parse (cadenaCaracteres)
Read (representaciónBinaria)
Este método sólo es utilizable en el contexto del CLR y permite realizar una lectura en
binario del nodo respecto al cual se ejecuta este método.
Este método permite modificar el nodo raíz y definir la nueva ruta de acceso en relación a
la nueva raíz indicada en el parámetro.
ToString()
Este método es el método inverso de Parse y permite obtener una representación textual del
valor hierarchyId del nodo.
Write (flujoBinario)
Este método reservado al código CLR permite definir a partir de un flujo binario el valor de
tipo hierarchyId del nodo. El método Write permite realizar la operación inversa del trabajo
realizado con el método Read.
Ejemplo
La primera etapa consiste en crear una tabla con una columna de tipo jerárquico. En el
ejemplo presentado a continuación, se ha definido una tabla que representa a los empleados
de una empresa con su puesto y su posición jerárquica respectiva.
A continuación se definen los índices en esta tabla. El primer índice se crea mediante la
inserción de una restricción de clave primaria. El segundo índice se refiere a la columna de
tipo hierarchyId. Finalmente, para permitir recorrer rápidamente la lista de empleados que
se encuentran en un mismo nivel de la jerarquía, se inserta una nueva columna en la
definición de la tabla. Esta columna contiene un dato calculado a partir de la posición del
empleado en la jerarquía:
Ahora que está definida la estructura, es posible insertar datos en esta tabla:
Ahora es posible extraer los datos como deseemos. En este primer ejemplo, se han extraído
todos los empleados que tienen como superior jerárquico directo al jefe:
Las dos primeras soluciones plantean el problema de la vinculación entre los diferentes
datos. Por ejemplo, cómo asociar correctamente la imagen de un producto a su referencia,
su denominación… y en particular cómo garantizar que si se elimina una imagen deje de
existir su artículo asociado.
Para tratar de aprovechar las diferentes opciones, SQL Server propone dos soluciones
diferentes.
La primera consiste en utilizar una segunda base para almacenar los datos de tipo blob
(Binary Large OBject) pero conservando un vínculo entre los datos locales y los datos
remotos. Este servidor de archivos BLOB evidentemente puede ser de Microsoft, pero
todos los grandes fabricantes del mercado son compatibles con esta solución. En efecto,
este tipo de solución puede ser interesante cuando los datos de tipo BLOB deben ser
almacenados en un servidor distinto del servidor SQL, o cuando ya existen aplicaciones que
alimentan este almacén de BLOB.
Sea cual sea el modelo de almacenamiento escogido, la búsqueda de estos datos sigue
siendo complicada. Para realizar esta tarea, SQL Server utiliza el servicio de texto integral
incluido en SQL Server. Esta integración permite reducir la complejidad de administración
y por tanto el coste durante el despliegue de soluciones SQL Server que utilizan esta
funcionalidad. Además, esta integración permite obtener mejores resultados.
Sintaxis
Sp_filestream_configure @enable_level= nivel ,@share_name=
nombreRecursoCompartido
nivel
nombreRecursoCompartido
Ejemplo
Para administrar los archivos físicos SQL Server utiliza los grupos de archivos. La
administración de los datos FILESTREAM no escapa a la regla y por eso es necesario
definir un grupo de archivos. La particularidad de este grupo de archivos proviene del
hecho de que no está compuesto de archivos, sino que corresponde a una carpeta creada
anteriormente en el sistema de archivos.
Ejemplo
Entonces se puede definir una columna de tipo FILESTREAM, pero sólo si las tablas
poseen una columna de tipo uniqueidentifier rowguidcol, que no acepten los valores null y
con una restricción de unicidad o bien de clave primaria.
Ejemplo
Ahora es posible insertar nuevas filas de datos en la tabla. Como Transact SQL no es el
lenguaje mejor adaptado para importar imágenes (es mejor utilizar .Net), se trata como una
cadena de caracteres por lo que se considerará como un dato binario.
Para responder a estas limitaciones, SQL Server propone los tipos geometry y geography.
El tipo geometry trabaja sobre un mapa en dos dimensiones y permite representar datos a
escala local. El tipo geography utiliza la latitud y la longitud para almacenar los distintos
datos.
Se puede definir un índice sobre las columnas que alojan datos geográficos mediante un
cuadro de varios niveles.
Ejemplo
Los datos de tipo geography se manipulan con los métodos asociados a este tipo. Los
métodos se denominan de la siguiente manera: geography::nombreMétodo. Los datos de
tipo geography pueden ser un punto, una fila o un polígono.
Ejemplo
La programación de estos tratamientos se puede hacer por tanto directamente desde Visual
Studio. Para que los métodos y procedimientos así definidos puedan ser utilizados desde las
instrucciones SQL se realiza un mapeo Transact SQL con el código MSIL.
El hecho de pasar por el CLR integrado en SQL Server es mucho más seguro (y sencillo)
que llamar a procedimientos almacenados ampliados. Efectivamente, el CLR presente en
SQL Server es únicamente parcial y no cubre todas las funcionalidades ofrecidas por
Framework .Net. Por ejemplo, todos los objetos relativos a la administración de la interfaz
gráfica no están. Limitando el número de funcionalidades ofrecidas por el CLR es posible
prevenir la actuación de determinado código malintencionados.
Contrariamente lo que se podría pensar tras una primera aproximación rápida a SQL
Server, Transact SQL no se ve amenazado en ningún caso por el código CLR. De hecho,
ambos tienen sus ventajas y sus inconvenientes. En función del trabajo que se haya de
realizar se escogerá de manera natural uno u otro.
Es posible completar estas características precisando que aunque Transact SQL no posee
una gestión optimizada para las cadenas de caracteres, dispone de numerosas funciones de
manejo de datos.
CLR permite producir un código más optimizado y por tanto más productivo. También
permite aprovechar la riqueza de los lenguajes C# y VB.Net.
El código CLR está especialmente bien adaptado para definir tratamientos complejos.
Permite asimismo administrar flujos XML complejos. Finalmente, CLR permite crear sus
propios tipos de datos estructurados: los UDT (o User Defined Types).
El código CLR también puede imponerse de forma lógica, por ejemplo durante la escritura
de un procedimiento relativamente complejo. Es entonces cuando se nota la riqueza de un
lenguaje orientado a objetos y del Framework .Net. Por ejemplo, para detectar un formato
en una cadena de caracteres es mucho más sencillo utilizar CLR y las expresiones regulares
en lugar de escribir un código complicado y no optimizado en Transact SQL.
En el caso del tratamiento de las cadenas de caracteres por una función del CLR, conviene
saber que los lenguajes como C# y VB.Net trabajan sobre datos de tipo carácter en formato
unicode, por lo que es necesario utilizar los tipos nchar y nvarchar en Transact SQL.
El código CLR se puede cargar en la base de dos formas: directamente desde Visual Studio
o desde el ensamblador de MSIL mediante la instrucción Transact SQL CREATE
ASSEMBLY.
Si se escriben las funciones SQL CLR desde Visual Studio, la implementación sobre SQL
Server es automática.
Las funciones siempre deben tener como prefijo el nombre del esquema sobre el cual están
definidas (dbo en general), durante su utilización.
Para acceder a recursos externos al servidor de base de datos, como el registro de eventos,
el registro de Windows o bien la invocación de un servicio Web, es necesario tener acceso
al código CLR. Ante todo, no se deben utilizar procedimientos no documentados sp_xxxx o
xp_xxxx, porque no necesariamente estarán presentes en las versiones futuras de SQL
Server.
Al utilizar Transact SQL, la mayor parte del tiempo las instrucciones SQL están codificadas
de manera permanente o estática. El compilador puede así detectar los errores de sintaxis
desde la creación del procedimiento o de la función.
Durante la integración de instrucciones SQL en código CLR, las instrucciones SQL sólo
son compiladas en el momento de la ejecución del código que transmite las instrucciones
SQL al motor de base de datos. El comportamiento es similar al que encontramos durante la
utilización del procedimiento almacenado sp_executesql que permite reconstruir de forma
dinámica instrucciones SQL en Transact SQL.
De igual manera, el código CLR considera como un flujo binario los datos de tipo
TIMESTAMP.
El CLR de SQL Server permite el acceso a los datos a través de ADO. Esta capa puede,
ahora, ser considerada como un estándar de acceso a los datos desde .Net y permite
encontrar rápidamente los automatismos adquiridos durante el diseño de programas
clientes.
Además, SQL Server propone para el código que se ejecuta sobre el servidor clases
específicas en el espacio de nombre Microsoft.SqlServer.Server.
Debido a esto, es necesario dar prioridad a la ejecución del código en el aplicativo cliente
(desde el punto de vista del servidor de base de datos) para aligerar la carga de trabajo del
servidor.
La clase SQLContext propone el método IsAvailable, que devuelve un valor booleano true
(verdadero) si el código se ejecuta sobre el servidor y false (falso) si no es así.
Antes de comenzar a escribir código CLR para SQL Server hay que activar la aceptación de
este tipo de código por parte de SQL Server. No se trata de una opción ni de un
componente que haya que instalar, sino de activar una opción de configuración. Por razones
de seguridad, esta opción está desactivada de forma predeterminada. Puede ser activada
desde la superficie de exposición o directamente desde Transact SQL mediante el
procedimiento almacenado sp_configure. Se trata entonces de modificar el valor de la
opción de configuración CLR_ENABLED . Esta configuración a través de Transact SQL
puede ser realizada desde SQL Server Management Studio o bien desde SQLCMD, tal y
como se ilustra a continuación.
Aunque en teoría sea posible escribir el código fuente desde cualquier editor, incluso desde
el Bloc de notas de Windows, se recomienda encarecidamente emplear Visual Studio para
definir elementos en código CLR administrados por SQL Server. Desde Visual Studio , el
despliegue sobre la instancia de SQL Server y la correspondencia entre CLR y Transact
SQL se establecen de forma automática.
Para garantizar al máximo la seguridad de la aplicación, SQL Server nunca suprimirá de
forma implícita un procedimiento o una función. Deben suprimirse junto con el assembly
antes de lanzar una nueva generación desde Visual Studio.
Después de lanzar Visual Studio, hay que crear un proyecto de tipo SQL Server.
A continuación, Visual Studio solicita agregar una referencia al servidor que sirve de base
para el proyecto.
En el caso aquí ilustrado, hay que seleccionar como proveedor de datos .Net Framework
Data Provider for SQL Server. A continuación hay que identificar completamente al
servidor indicando su ubicación (local) porque el servidor SQL Server y las herramientas
de desarrollo Visual Studio están presentes en el puesto.
Los diferentes tipos de desarrollo ofrecidos por el CLR se exponen y se ilustran con un
ejemplo. Los ejemplos están indicados en C#, pero también es posible realizar el mismo
trabajo en Visual Basic.
Los tipos de datos personalizados o UDT (User Defined Type) ofrecen al desarrollador la
posibilidad de complementar los tipos propuestos por SQL Server para almacenar
información en el formato que se desee. Sin embargo, los tipos UDT pueden resultar ser
una trampa si se utilizan de forma distinta a su propósito, como por ejemplo para
transformar SQL Server en una base orientada a objetos. Cuando se define una columna
mediante un tipo UDT, se actualizan la totalidad de los campos constitutivos de este tipo,
incluso aunque sólo se haya movilizado un valor. De igual manera, la manipulación de este
tipo será más complicada y menos productiva que si se utiliza una estructura relacional
clásica.
Los tipos UDT, por el contrario, están bien adaptados cuando se trata de almacenar valores
cuya estructura es compleja y en los que los diferentes campos están vinculados entre sí.
Por ejemplo, un número de seguridad social: la estructura es compleja, pero está
perfectamente definida y los datos están vinculados entre sí para componer un número
único. Si se define un tipo UDT es posible definir funciones y procedimientos que
manipulen este tipo. Debido a que la estructura es compleja, la verificación de los datos
será más fácil en C# y en VB.Net que en Transact SQL.
Para definir su propio tipo de dato es necesario, desde la ventana Solution Explorer,
seleccionar Add - User-Defined Type desde el menú contextual asociado al proyecto.
A continuación aparecerá el cuadro de diálogo que permite insertar un nuevo componente
en el proyecto. En el ejemplo siguiente, se crea el tipo TCliente.
Entonces es posible definir una tabla que posea una columna de tipo TCliente.
4. Procedimiento almacenado
using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlTypes;
using System.IO;
using Microsoft.SqlServer.Server;
Antes de compilar, hay que comprobar que el nivel de permisos sea No seguro (Unsafe) en
el nivel de propiedades del proyecto, ficha Base de datos.
El código CLR también puede aprovecharse para definir triggers de base de datos más
complejos que los que se pueden definir fácilmente en Transact SQL.
Al igual que con los elementos anteriores, hay que agregar un trigger de base de datos con
el menú Proyecto - AñadirDesencadenador.
El siguiente ejemplo sólo será posible si la tabla Clientes posee una columna mail de tipo
nvarchar(80).
using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlTypes;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using Microsoft.SqlServer.Server;
using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlTypes;
using System.Text;
using System.IO;
using Microsoft.SqlServer.Server;
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.Native)]
public struct reunir
{
public void Init()
{
i=1;
}
private int i;
Sitios de Internet
Artículos SQL Server 2008: http://www.devjoker.com/html/SQL-Server-2008.html
MSDN: http://msdn2.microsoft.com/en-us/sqlserver/default.aspx
Technet: http://technet.microsoft.com/es-es/sqlserver/default.aspx
GO
);
GO
);
GO
);
GO
);
GO
);
GO
);
GO
);
GO
GO
GO
GO
GO
GO
GO
GO
ALTER TABLE articulos ADD CONSTRAINT fk_articulos_categorias FOREIGN
KEY(codigo_cat)
GO
Glosario
ADO ActiveX Data Objectpal
API Application Programming Interface
CLR Common Language Runtime
DMV Dynamic Management View
ETL Extraction Transformation and Load
GC Garbage Collector
GAC Global Assembly Cache
ODS Open Data Services
OLTP On Line Transaction Processing
OLAP OnLine Analytical Processing
RID Row Identifier
SOAP Simple Object Access Protocol
SQL Structure Query Language
SSIS SQL Server Integration Services
TSQL Transact SQL
TVF Table Valued Functions
UDF User Defined aggregate Function