SQL es un lenguaje de consulta para los sistemas de bases de datos relacinales, pero que no posee la potencia de los lenguajes de programacin. Para abordar el presente tutorial con minimo de garantias es necesario conocer previamente SQL. Podemos acceder a un comp|eto tutor|a| de 80L desde A0U|. Transact SQL es el lenguaje de programacin que proporciona SQL Server para ampliar SQL con los elementos caracteristicos de los lenguajes de programacin: variables, sentencias de control de flujo, bucles ... Cuando se desea realizar una aplicacin completa para el manejo de una base de datos relacional, resulta necesario utilizar alguna herramienta que soporte la capacidad de consulta del SQL y la versatilidad de los lenguajes de programacin tradicionales. Transact SQL es el lenguaje de programacin que proporcionaSQL Server para extender el SQL estandar con otro tipo de instrucciones. Transact SQL existe desde las primeras versiones de SQL Server, si bien a lo largo de este tutorial nos centraremos en la versin SQL Server 200S. Programacin con Transact SQL !ntroduccin SQL es un lenguaje de consulta para los sistemas de bases de datos relacinales, pero que no posee la potencia de los lenguajes de programacin. No permite el uso de variables, estructuras de control de flujo, bucles ... y demas elementos caracteristicos de la programacin. No es de extranar, SQL es un lenguaje de consulta, no un lenguaje de programacin. Sin embargo, SQL es la herramienta ideal para trabajar con bases de datos. Cuando se desea realizar una aplicacin completa para el manejo de una base de datos relacional, resulta necesario utilizar alguna herramienta que soporte la capacidad de consulta del SQL y la versatilidad de los lenguajes de programacin tradicionales. Transact SQL es el lenguaje de programacin que proporciona Nicrosoft SQL Server para extender el SQL estandar con otro tipo de instrucciones y elementos propios de los lenguajes de programacin . Con Transact SQL vamos a poder programar las unidades de programa de la base de datos SQL Server, estan son: O Procedimientos almacenados O unciones O Triggers O Scripts
Pero ademas Transact SQL nos permite realizar programas sobre las siguientes herramientas de SQL Server: O Service Broker undamentos de Transact SQL Primeros pasos con Transact SQL Para programar en Transact SQL es necesario conocer sus fundamentos. Como introduccin vamos a ver algunos elementos y conceptos basicos del lenguaje. O Transact SQL no es CASESENS!T!vE, es decir, no diferencia maysculas de minsculas como otros lenguajes de programacin como C o ]ava. O n comentario es una aclaracin que el programador incluye en el cdigo. Son soportados 2 estilos de comentarios, el de linea simple y de multilinea, para lo cual son empleados ciertos caracters especiales como son: o Para un comentario de linea simple o ... Para un comentario de varias lineas O n literal es un valor fijo de tipo numrico, caracter, cadena o lgico no representado por un identificador (es un valor explicito). O na variable es un valor identificado por un nombre (identificador) sobre el que podemos realizar modificaciones. En Transact SQL los identificadores de variables deben comenzar por el caracter @, es decir, el nombre de una variable debe comenzar por @.Para declarar variables en Transact SQL debemos utilizar la palabra clave declare, seguido del identificador y tipo de datos de la variable. veamos algunos ejemplos:
-- Esto es un comentario de linea simple
/ Este es un comentario con varias lneas. Conjunto de Lineas. / declare @nombre varchar(50)-- declare declara una variable -- @nombre es el identificador de la -- variable de tipo varchar set @nombre = 'www.devjoker.com' -- El signo = es un operador -- www.devjoker.com es un literal print @Nombre -- Imprime por pantalla el valor de @nombre. -- No diferencia maysculas ni minsculas Scripts y lotes. n script de Transact SQL es un conjunto de sentencias de Transact SQL en formato de texto plano que se ejecutan en un servidor de SQL Server. n script esta compuesto por uno o varios lotes. n lote delimita el alcance de las variables y sentencias del script. Dentro de un mismo script se diferencian los diferentes lotes a travs de las instruccin CO.
-- Este es el primer lote del script SELECT FROM CJMENTARIJS GO -- GJ es el separador de lotes -- Este es el segundo lote del script SELECT getdate() -- getdate() es una funcin integrada que devuelve -- la fecha En ocasiones es necesario separar las sentencias en varios lotes, porque Transact SQL no permite la ejecucin de ciertos comandos en el mismo lote, si bien normalmente tambin se utilizan los lotes para realizar separaciones lgicas dentro del script. Tipos de datos en Transact SQL Cuando definimos una tabla, variable o constante debemos asignar un tipo de dato que indica los posibles valores. El tipo de datos define el formato de almacenamiento, espacio que de discomemoria que va a ocupar un campo o variable, restricciones y rango de valores validos. Transact SQL proporciona una variedad predefinida de tipos de datos . Casi todos los tipos de datos manejados por Transact SQL son similares a los soportados por SQL. Tipos de datos numricos. SQL Server dispone de varios tipos de datos nmericos. Cuanto mayor sea el nmero que puedan almacenar mayor sera en consecuencia el espacio utilizado para almacenarlo. Como regla general se recomienda usar el tipo de dato minimo posible. Todos los dato numricos admiten el valor NLL. Bit. na columna o variable de tipo bit puede almacenar el rango de valores de 1 a 0. Tinyint. na columna o variable de tipo tinyint puede almacenar el rango de valores de 0 a 2SS. Small!nt. na columna o variable de tipo smallint puede almacenar el rango de valores 32768 a 32767. !nt. na columna o variable de tipo int puede almacenar el rango de valores 2 31 a 2 31 1 . Big!nt. na columna o variable de tipo bigint puede almacenar el rango de valores 2 63 a 2 63 1 . Decimal(p,s). na columna de tipo decimal puede almacenar datos nmericos decimales sin redondear. Donde p es la precision (nmero total del digitos) y s la escala (nmero de valores decimales) loat. na columna de datos float puede almacenar el rango de valores 1,73x10 308 a 1,73x10 308, , si la definimos con el valor maxmo de precisin. La precisin puede variar entre 1 y S3. Real. Sinnimo de float(24). Puede almacenar el rango de valores 3,4x10 38 a 3,4x10 38,
Noney. Almacena valores nmericos monetarios de 2 63 a 2 63 1, con una precisin de hasta diexz milesimas de la unidad monetaria. SmallNoney. Almacena valores nmericos monetarios de 214.748,3647 a 214.748,3647, con una precisin de hasta diez milesimas de la unidad monetaria. Todos los tipos de datos enteros pueden marcarse con la propiedad identity para hacerlos autonumricos.
ECLARE @bit bit, @tinyint tinyint, @smallint smallint, @int int, @bigint bigint, @decimal decimal(10,3), -- 10 digitos, 7 enteros y -- 3 decimales @real real, @double float(53), @money money set @bit = 1 print @bit set @tinyint = 255 print @tinyint set @smallint = 32767 print @smallint set @int = 642325 print @int set @decimal = 56565.234 -- Punto como separador decimal print @decimal set @money = 12.34 print @money Tipos de datos de caracter. Char(n). Almacena n caracteres en formato ASC!!, un byte por cada letra. Cuando almacenamos datos en el tipo char, siempre se utilizan los n caracteres indicados, incluso si la entrada de datos es inferior. Por ejemplo, si en un char(S), guardamos el valor 'A', se almacena 'A ', ocupando los cinco bytes. varchar(n).Almacena n caracteres en formato ASC!!, un byte por cada letra. Cuando almacenamos datos en el tipo varchar, unicamente se utilizan los caracteres necesarios,Por ejemplo, si en un varchar(2SS), guardamos el valor 'A', se almacena 'A', ocupando solo un byte bytes. varchar(max). !gual que varchar, pero al declararse como max puede almacenar 2 31 1 bytes. !char(n).Almacena n caracteres en formato N!CODE, dos bytes por cada letra. Es recomendable utilizar este tipo de datos cuando los valores que vayamos a almacenar puedan pertenecer a diferente idomas. !varchar(n).Almacena n caracteres en formato N!CODE, dos bytes por cada letra. Es recomendable utilizar este tipo de datos cuando los valores que vayamos a almacenar puedan pertenecer a diferente idomas. !varchar(max).!gual que varchar, pero al declararse como max puede almacenar 2 31 1 bytes. Tipos de datos de fecha. Datetime. Almacena fechas con una precision de milisegundo. Debe usarse para fechas muy especificas. SmallDatetime. Almacena fechas con una precision de minuto, por lo que ocupa la mitad de espacio de que el tipo datetime, para tablas que puedan llegar a tener muchos datos es un factor a tener muy en cuenta. TimeStamp.Se utiliza para marcar un registro con la fecha de insercin actualizacin. El tipo timestamp se actualiza automaticamente cada vez que insertamos o modificamos los datos. Tipos de datos binarios. Binary. Se utiliza para almacenar datos binarios de longitud fija, con una longitud maxima de 8000 bytes. varbinary. Se utiliza para almacenar datos binarios de longitud variable, con una longitud maxima de 8000 bytes..Es muy similar a binary, salvo que varbinary utiliza menos espacio en disco. varbinary(max).!gual que varbinary, pero puede almacenar 2 31 1 bytes Tipo de datos XNL. XNL.na de las grandes mejoras que incorpora SQL Server 200S es el soporte nativo para XNL. Como podemos deducir, este tipo de datos se utiliza para almacenar XNL.
ECLARE @myxml XML
set @myxml = (SELECT @@SERVERNAME NJMBRE FOR XML RAW, TYPE)
print cast(@myxml as varchar(max)) Obtendremos la siguiente salida: <row nombre="SvR01"
Otros tipos de datos. Unique!dentifier. Se utiliza para identificadores nicos. Para generar identificadores nicos debemos utilizar la funcin !!D().
ECLARE @myuniqueid UNIQUEIENTIFIER
set @myuniqueid = NEWID()
print cast(@myuniqueid as varchar(36)) Obtendremos la siguiente salida: 46141D73102C4C23A620732EA0208637 Sql_variant.Permite almacenar valores de diferentes tipos de datos. No puede almacena varchar(max), xml, timestamp y tipos de datos definidos por el usuario. Tipos de datos personalizados. Transact SQL permite la creacin de tipos de datos personalizados, a trevs de la instruccin CRT TYP. Personalmente, desaconsejo el uso de tipos de datos personalizados.
CREATE TYPE M FROM CHAR(32) NULL GJ ECLARE @miMD5 M set @miMD5 = '0000000000000000000000000000000A' print @miMD5 variables en Transact SQL Declarar variables es Transact SQL na variable es un valor identificado por un nombre (identificador) sobre el que podemos realizar modificaciones. En Transact SQL los identificadores de variables deben comenzar por el caracter @, es decir, el nombre de una variable debe comenzar por @. Para declarar variables en Transact SQL debemos utilizar la palabra clave declare, seguido del identificador y tipo de datos de la variable.
-- Esto es un comentario de linea simple
/ Este es un comentario con varias lneas. Conjunto de Lineas. / declare @nombre varchar(50)-- declare declara una variable -- @nombre es el identificador de la -- variable de tipo varchar set @nombre = 'www.devjoker.com' -- El signo = es un operador -- www.devjoker.com es un literal print @Nombre -- Imprime por pantalla el valor de @nombre. -- No diferencia maysculas ni minsculas signar variables en Transact SQL En Transact SQL podemos asignar valores a una variable de varias formas: O A travs de la instrunccin set. O tilizando una sentencia SLCT. O Realizando un TCH de un cursor. El siguiente ejemplo muestra como asignar una variable utilizando la instruccin ST.
DCLR @nombre vRCHR(100) La consulta debe devolver un nico registro ST @nombre = (SLCT nombre RON CL!ENTES HR !D = 1) PR!!T @nombre El siguiente ejemplo muestra como asignar variables utilizando una sentencia SELECT.
PR!!T @nombre PR!!T @apellido1 PR!!T @apellido2 n punto a tener en cuenta cuando asignamos variables de este modo, es que si la consulta SELECT devuelve mas de un registro, las variables quedaran asignadas con los valores de la ltima fila devuelta. Por litmo veamos como asignar variables a travs de un cursor.
CLOS CDATOS DLLOCT CDATOS veremos los cursores con mas detalle mas adelante en este tutorial. Operadores en Transact SQL La siguiente tabla ilustra los operadores de Transact SQL . Tipo de operador Operadores Operador de asignacin Operadores aritmticos (suma) (resta) (multiplicacin) (divisin) (exponente) (modulo) Operadores relacionales o de comparacin = (igual a) < (distinto de) != (distinto de) < (menor que) (mayor que) = (mayor o igual a) <= (menor o igual a) ! (no mayor a) !< (no menor a) Operadores lgicos AND (y logico) NOT (negacion) OR (o logico) & (AND a nivel de bit) , (OR a nivel de bit) ` (OR exclusivo a nivel de bit) Operador de concatenacin
Otros ALL (Devuelve TRE si el conjunto completo de comparaciones es TRE) ANY(Devuelve TRE si cualquier elemento del conjunto de comparaciones es TRE) BETWEEN (Devuelve TRE si el operando esta dentro del intervalo) EXISTS (TRE si una subconsulta contiene filas) IN (TRE si el operando esta en la lista) LIKE (TRE si el operando coincide con un patron) NOT (!nvierte el valor de cualquier operador booleano) SOME(Devuelve TRE si alguna de las comparaciones de un conjunto es TRE) structuras de control en Transact SQL structura condicional ! La estuctura condicional ! permite evaluar una expresion booleana (resultado S! NO), y ejecutar las operaciones contenidas en el bloque formado por BC!! !D.
IF (<expresion) BEGIN ... EN ELSE IF (<expresion) BEGIN ... EN ELSE BEGIN ... EN Ejemplo de la estructura condicional !.
ECLARE @Web varchar(100), @diminutivo varchar(3)
SET @diminutivo = 'DJK'
IF @diminutivo = 'DJK' BEGIN PRINT 'www.devjoker.com' EN ELSE BEGIN PRINT 'Jtra Web (peor!)' EN La estructura ! admite el uso de subconsultas:
ECLARE @coPais int, @descripcion varchar(255) set @coPais = set @descripcion = 'Espaa' IF EXISTS(SELECT FROM PAISES WHERE CJ_PAIS = @coPais) BEGIN UPATE PAISES SET DESCRIPCIJN = @descripcion WHERE CJ_PAIS = @coPais EN
ELSE BEGIN INSERT INTO PAISES (CJ_PAIS, DESCRIPCIJN) VALUES (@coPais, @descripcion) EN structura condicional CS La estructura condicional CS permite evaluar una expresion y devolver un valor u otro. La sintaxis general de case es:
CASE <expresion WHEN <valor_expresion THEN <valor_devuelto WHEN <valor_expresion THEN <valor_devuelto ELSE <valor_devuelto -- Valor por defecto EN Ejemplo de CS.
ECLARE @Web varchar(100), @diminutivo varchar(3) SET @diminutivo = 'DJK' SET @Web = (CASE @diminutivo WHEN 'DJK' THEN 'www.devjoker.com' WHEN 'ALM' THEN 'www.aleamedia.com' ELSE 'www.devjoker.com' EN) PRINT @Web Otra sintaxis de CS nos permite evaluar diferentes expresiones:
CASE WHEN <expresion = <valor_expresion THEN <valor_devuelto WHEN <expresion = <valor_expresion THEN <valor_devuelto ELSE <valor_devuelto -- Valor por defecto
EN El mismo ejemplo aplicando esta sintaxis:
ECLARE @Web varchar(100), @diminutivo varchar(3) SET @diminutivo = 'DJK'
SET @Web = (CASE WHEN @diminutivo = 'DJK' THEN 'www.devjoker.com' WHEN @diminutivo = 'ALM' THEN 'www.aleamedia.com' ELSE 'www.devjoker.com' EN) PRINT @Web
Otro aspecto muy interesante de CS es que permite el uso de subconsultas.
ECLARE @Web varchar(100), @diminutivo varchar(3) SET @diminutivo = 'DJK'
SET @Web = (CASE WHEN @diminutivo = 'DJK' THEN (SELECT web FROM WEBS WHERE id=1) WHEN @diminutivo = 'ALM' THEN (SELECT web FROM WEBS WHERE id=2) ELSE 'www.devjoker.com' EN) PRINT @Web Bucle H!L El bucle H!L se repite mientras expresion se evalue como verdadero. Es el nico tipo de bucle del que dispone Transact SQL.
WHILE <expresion BEGIN ... EN n ejemplo del bucle H!L.
ECLARE @contador int SET @contador = 0 WHILE (@contador < 100) BEGIN SET @contador = @contador + 1
PRINT 'Iteracion del bucle ' + cast(@contador AS varchar) EN Podemos pasar a la siguiente iteracin del bucle utilizando CO!T!!U.
ECLARE @contador int SET @contador = 0 WHILE (@contador < 100) BEGIN SET @contador = @contador + 1 IF (@contador % 2 = 0) CONTINUE PRINT 'Iteracion del bucle ' + cast(@contador AS varchar) EN El bucle se dejara de repetir con la instruccin BR.
ECLARE @contador int SET @contador = 0 WHILE (1 = 1) BEGIN SET @contador = @contador + 1 IF (@contador % 50 = 0) BREAK PRINT 'Iteracion del bucle ' + cast(@contador AS varchar) EN Tambin podemos utilizar el bucle H!L conuntamente con subconsultas.
ECLARE @coRecibo int WHILE EXISTS (SELECT FROM RECIBJS WHERE PENDIENTE = 'S')-- Jjo, la subconsulta se ejecuta -- una vez por cada iteracion -- del bucle! BEGIN SET @coRecibo = (SELECT TOP 1 CJ_RECIBJ FROM RECIBJS WHERE PENDIENTE = 'S') UPATE RECIBJS SET PENDIENTE = 'N' WHERE CJ_RECIBJ = @coRecibo EN structura COTO La sentencia goto nos permite desviar el flujo de ejecucin hacia una etiqueta. u muy utilizada en versiones anteriores de SQL Server conjuntamente con la variable de sistema @@ERROR para el control de errores. Actualmente, se desaconseja el uso COTO, recomendandose el uso de TRY CATCH para la gestion de errores.
ECLARE @divisor int, @dividendo int, @resultado int SET @dividendo = 100 SET @divisor = 0 SET @resultado = @dividendo/@divisor
IF @@ERRJR 0 GOTO error
PRINT 'No hay error' RETURN error: PRINT 'Se ha producido una division por cero'
Control de errores en Transact SQL Uso de TRY CTCH A part!r de la versin 200S, SQL Server proporciona el control de errores a travs de las instruccinesTRY y CTCH. Estas nuevas instrucciones suponen un gran paso adelante en el control de errores en SQL Server, un tanto precario en las versiones anteriores. La sintaxis de TRY CTCH es la siguiente:
BEGIN TRY ... EN TRY BEGIN CATCH ... EN CATCH El siguiente ejemplo ilustra el uso de TRY CTCH.
BEGIN TRY
ECLARE @divisor int ,
@dividendo int,
@resultado int
SET @dividendo = 100
SET @divisor = 0
-- Esta linea provoca un error de division por 0 SET @resultado = @dividendo/@divisor PRINT 'No hay error' EN TRY BEGIN CATCH PRINT 'Se ha producido un error' EN CATCH
unciones especiales de rror Las funciones especiales de error,estan disponibles nicamente en el bloque CTCH para la obtencin de informacin detallada del error. Son: O RROR_!UNBR(), devuelve el nmero de error. O RROR_SvR!TY(), devuelve la severidad del error. O RROR_STT(), devuelve el estado del error. O RROR_PROCDUR(), devuelve el nombre del procedimiento almacenado que ha provocado el error. O RROR_L!!(), devuelve el nmero de linea en el que se ha producido el error. O RROR_NSSC(), devuelve el mensaje de error. Son extremadamente tiles para realizar una auditoria de errores.
BEGIN TRY
ECLARE @divisor int ,
@dividendo int,
@resultado int
SET @dividendo = 100
SET @divisor = 0
-- Esta linea provoca un error de division por 0 SET @resultado = @dividendo/@divisor PRINT 'No hay error' EN TRY BEGIN CATCH PRINT ERROR_NUMBER() PRINT ERROR_SEVERITY() PRINT ERROR_STATE() PRINT ERROR_PROCEURE() PRINT ERROR_LINE() PRINT ERROR_MESSAGE() EN CATCH Lgicamente, podemos utilizar estas funciones para almacenar esta informacin en una tabla de la base de datos y registrar todos los errores que se produzcan. La variable de sistema @@RROR En versiones anteriores a SQL Server 200S, no estaban disponibles las instrucciones TRY CTCH. En estas versiones se controlaban los errores utilizando la variable global de sistema @@ERROR, que almacena el nmero de error producido por la ltima sentencia Transact SQL ejecutada.
ECLARE @divisor int , @dividendo int , @resultado int
SET @dividendo = 100 SET @divisor = 0 -- Esta linea provoca un error de division por 0 SET @resultado = @dividendo/@divisor
IF @@ERRJR = 0 BEGIN PRINT 'No hay error' EN ELSE BEGIN PRINT 'Hay error' EN El uso de @@ERROR para controlar errores puede provocar multitud de problemas. no de los mas habituales es sin duda, incluir una nueva sentencia Transact SQL entre la linea que provoco el error y la que lo controla. Esa nueva instruccin restaura el valor de @@ERROR y no controlaremos el error. El siguiente ejemplo ilustra esta situacin:
ECLARE @divisor int , @dividendo int , @resultado int
SET @dividendo = 100 SET @divisor = 0 -- Esta linea provoca un error de division por 0 SET @resultado = @dividendo/@divisor PRINT 'Controlando el error ...' -- Esta linea estable @@ERRJR a cero IF @@ERRJR = 0 BEGIN -- Se ejecuta esta parte! PRINT 'No hay error' EN ELSE BEGIN PRINT 'Hay error' EN Cenerar un error con R!SRROR En ocasiones es necesario provocar voluntariamente un error, por ejemplo nos puede interesas que se genere un error cuando los datos incumplen una regla de negocio. Podemos provocar un error en tiempo de ejecucin a travs de la funcin RA!SERROR.
ECLARE @tipo int, @clasificacion int
SET @tipo = 1 SET @clasificacion = 3 IF (@tipo = 1 AN @clasificacion = 3) BEGIN RAISERROR ('El tipo no puede valer uno y la clasificacion 3', 16, -- Severidad 1 -- Estado ) EN La funcin RA!SERROR recibe tres parametros, el mensaje del error (o cdigo de error predefinido), la severidad y el estado. La severidad indica el grado de criticidad del error. Admite valores de 0 al 2S, pero solo podemos asignar valores del 0 al 18. Los errores el 20 al 2S son considerados fatales por el sistema, y cerraran la conexion que ejecuta el comando R!SRROR. Para asignar valores del 13 al 2S necesitares ser miembros de la funcin de SQL Server sysadmin. El estado es un valor para permitir que el programador identifique el mismo error desde diferentes partes del cdigo. Admite valores entre 1 y 127, permite tratar . Consultar datos en Transact SQL La sentencia SLCT La sentencia SLCT nos permite consultar los datos almacenados en una tabla de la base de datos. El formato de la sentencia select es:
SLCT |LL ] D!ST!!CT ]| TOP expression | PRC!T ] | !TH T!S ] ] <nombre_campos RON <nombre_tabla | !!!R ] LT |OTER]] R!CHT |OTER] ] CROSS] |]O!! ] <nombre_tabla O! <condicion_join| !D]OR <condicion] |HR <condicion | !D]OR <condicion]] |CROUP BY <nombre_campos] |Hv!!C <condicion| !D]OR <condicion]] |ORDR BY <nombre_campo |SC ] DSC] El siguiente ejemplo muestra una consulta sencilla que obtiene el cdigo y la "familia" de una tabla llamada familias (representaria familias de productos por ejemplo).
SLCT CO_AN!L!A, AN!L!A RON AN!L!AS
El uso del asterisco indica que queremos que la consulta devuelva todos los campos que existen en la tabla.
SLCT * RON AN!L!AS Ahora vamos a realizar una consulta obteniendo ademas de los datos de familias, los datos de las categorias y los productos.
SLCT * RON AN!L!AS !!!R ]O!! CATECOR!AS O! CATECOR!AS.CO_AN!L!A = AN!L!AS.CO_AN!L!A !!!R ]O!! PRODCTOS O! PRODCTOS.CO_CATECOR!A = CATECOR!AS.CO_CATECOR!A La combinacin se realiza a travs de la clausula !!!R ]O!!, que es una clasula exclusiva, es decir las familias que no tengan categorias y productos asociados no se devolveran. Si queremos realizar la consulta para que no sea exclusiva, tenemos que utilizar LT ]O!!. El uso de la palabra reservada OUTR es opcional.
SLCT * RON AN!L!AS LT OUTR ]O!! CATECOR!AS O! CATECOR!AS.CO_AN!L!A = AN!L!AS.CO_AN!L!A LT OUTR ]O!! PRODCTOS O! PRODCTOS.CO_CATECOR!A = CATECOR!AS.CO_CATECOR!A Los registros que no tengan datos relacionados en una consulta LT ]O!! devolveran en valor null en los campos que correspondan a las tablas en las que no tienen dato. Tambin podemos forzar un producto cartesiano (todos con todos) a travs de CROSS ]O!!.
SLCT * RON AN!L!AS CROSS ]O!! CATECOR!AS La clausula HR La clausula HR es la instruccin que nos permite filtrar el resultado de una sentencia SLCT.
SLCT CO_AN!L!A, AN!L!A RON AN!L!AS HR CO_AN!L!A = 1 Por supuesto, podemos especificar varias condiciones para el HR:
SLCT RON AN!L!AS HR CO_AN!L!A = 1 OR CO_AN!L!A = 2 Podemos agrupar varias valores para una condicion en la clausula !!:
SLCT RON AN!L!AS HR CO_AN!L!A !N ( 1 , 2)
La clausula HR se puede utilizar conjuntamente con !!!R ]O!!, LT ]O!! ...
SLCT AN!L!AS.CO_AN!L!A, AN!L!AS.AN!L!A RON AN!L!AS !NNER ]O!N CATECOR!AS O! CATECOR!AS.CO_AN!L!A = AN!L!AS.CO_AN!L!A HR AN!L!AS.CO_AN!L!A 1 Siempre que incluyamos un valor alfanumerico para un campo en la condicin HR este debe ir entre comillas simples:
SLCT RON AN!L!AS HR AN!L!A = 'AN!L!A 1' Para consultar campos alfanumericos, es decir, campos de texto podemos utilizar el operador L!conjuntamente con comodines.
SLCT RON AN!L!AS HR AN!L!A L!KE 'AN' Los comodines que podemos utilizar en son los siguientes: O , representa cualquier cadena de texto de cero o mas caracteres de cualquier longitud. O _ , representa un caracter. O |ad], representa cualquier caracter del intervalo ad. O |abcd], representa cualquier caracter del grupo abcd. O |ad], representa cualquier caracter diferente del intervalo ad. O |abcd], representa cualquier caracter distinto del grupo abcd. Tambin podemos obtener los valores distintos utilizando D!ST!!CT.
SLCT D!ST!!CT AN!L!A Devuelve los distintos valores de AN!L!A RON AN!L!AS Podemos limitar el nmero de registros que devuelve la consulta a travs de la clausula TOP. La clausulaTOP admite como parametros un valor numrico entero o un porcentaje (slo a partir de la version 200S)
SLCT TOP 10 Devuelve 10 registros RON AN!L!AS
SLCT TOP S0 PRC!T Devuelve el S0 de los registros RON AN!L!AS La clausula TOP se puede combinar con |Th T|E8 en consultas agregadas. La clausula ORDR BY Podemos especificar el orden en el que seran devueltos los datos a travs de la clausula ORDR BY.
SLCT CO_AN!L!A, AN!L!A RON AN!L!AS ORDR BY AN!L!A DSC Tambin podemos indicar el indice del campo en la lista de seleccin en lugar de su nombre :
SLCT CO_AN!L!A, AN!L!A RON AN!L!AS ORDR BY 2 DSC Ordena por AN!L!A Consultas agregadas La clausula CROUP BY La clausula CROUP BY combina los registros devueltos por una consulta SLCT obteniendo uno o varios valores agregados(suma, valor minimo y maximo ...). Para cada registro se puede crear un valor agregado si se incluye una funcin SQL agregada, como por ejemplo Sum o Count, en la instruccin SLCT. Su sintaxis es:
SELECT ALL | ISTINCT ( TOP <n WITH TIES(( <342bre_ca254 ,<342bre_ca254,( ,1:3ci43_agregad4,( FROM <342bre_tabla|<342bre_vista ,<342bre_tabla|<342bre_vista,( WHERE <c43dici43 AN|OR <condicion,(( GROUP BY <342bre_ca254 ,<342bre_ca254 ,(( HAVING <c43dici43 AN|OR <condicion,(( ORER BY <342bre_ca254|<indice_campo ASC | ESC( ,<342bre_ca254|<indice_campo ASC | ESC (,(( Si se utiliza CROUP BY pero no existe una funcin SQL agregada en la instruccin SLCT se obtiene el mismo resultado que con una consulta SLCT D!ST!!CT. Los valores Null en los campos CROUP BY se agrupan y no se omiten. No obstante, los valores Null no se evalan en ninguna de las funciones SQL agregadas. Todos los campos de la lista de campos de SLCT deben incluirse en la clausula CROUP BY o como argumentos de una funcin SQL agregada. El siguiente ejemplo realiza una "cuenta" de los datos que hay en la tabla PRODCTOS.
SLCT CONT() RON PRODCTOS Este otro ejemplo, muestra la suma del PREC!O de cada uno de los productos que componen un pedido, para calcular el total del pedido agrupados por los datos del cliente.
SLCT CL!ENTES.NONBRE, CL!ENTES.APELL!DO1, CL!ENTES.APELL!DO2, SN(PREC!O) Total del pedido RON DETALLE_PED!DO !NNER ]O!N PED!DOS O! DETALLE_PED!DO.CO_PED!DO = PED!DOS.CO_PED!DO !NNER ]O!N CL!ENTES O! PED!DOS.CO_CL!ENTE = CL!ENTES.CO_CL!ENTE CROUP BY CL!ENTES.NONBRE, CL!ENTES.APELL!DO1, CL!ENTES.APELL!DO2 Siempre que incluyamos una clausula HR en una consulta agregada esta se aplica antes de calcular el valor agregado. Es decir, si sumamos el valor de las ventas por producto, la suma se calcula despues de haber aplicado el filtro impuesto por la clausula HR.
SLCT CL!ENTES.NONBRE, CL!ENTES.APELL!DO1, CL!ENTES.APELL!DO2, SN(PREC!O) Total del pedido RON DETALLE_PED!DO !NNER ]O!N PED!DOS O! DETALLE_PED!DO.CO_PED!DO = PED!DOS.CO_PED!DO !NNER ]O!N CL!ENTES O! PED!DOS.CO_CL!ENTE = CL!ENTES.CO_CL!ENTE La clausula WHERE se aplica antes de realizar el calculo HR CL!ENTES.NONBRE != 'N NONBRE' CROUP BY CL!ENTES.NONBRE, CL!ENTES.APELL!DO1, CL!ENTES.APELL!DO2 La clausula Hv!!C Es posible que necesitemos calcular un agregado, pero que no necesitemos obtener todos los datos, solo los que cumplan una condicin del agregado. Por ejemplo, podemos calcular el valor de las ventas por producto, pero que solo queramos ver los datos de los producto que hayan vendido mas o menos de una determinada cantidad. En estos casos debemos utilizar la clausula Hv!!C. na vez que CROUP BY ha combinado los registros, Hv!!C muestra cualquier registro agrupado por la clausula CROUP BY que satisfaga las condiciones de la clausula Hv!!C. Se utiliza la clausula HRpara excluir aquellas filas que no desea agrupar, y la clausula Hv!!C para filtrar los registros una vez agrupados. Hv!!C es similar a HR, determina qu registros se seleccionan pero despues de calcular el agregado. na vez que los registros se han agrupado utilizando CROUP BY, Hv!!C determina cuales de ellos se van a mostrar. Hv!!C permite el uso de funciones agregadas.
SLCT CL!ENTES.NONBRE, CL!ENTES.APELL!DO1, CL!ENTES.APELL!DO2, SN(PREC!O) Total del pedido RON DETALLE_PED!DO !NNER ]O!N PED!DOS O! DETALLE_PED!DO.CO_PED!DO = PED!DOS.CO_PED!DO !NNER ]O!N CL!ENTES O! PED!DOS.CO_CL!ENTE = CL!ENTES.CO_CL!ENTE La clausula WHERE se aplica antes de realizar el calculo HR CL!ENTES.NONBRE != 'N NONBRE' CROUP BY CL!ENTES.NONBRE, CL!ENTES.APELL!DO1, CL!ENTES.APELL!DO2 Hv!!C SN(PREC!O) 100 unciones agregadas. Transact SQL pone a nuestra disposicin multiples funciones agregadas, las mas comunes son: O NAX O N!N O CONT O SN O AvC
vC Calcula la media aritmtica de un conjunto de valores contenidos en un campo especificado de una consulta. Su sintaxis es la siguiente
AVG(ex5r)
En donde expr representa el campo que contiene los datos numricos para los que se desea calcular la media o una expresin que realiza un calculo utilizando los datos de dicho campo. La media calculada por Avg es la media aritmtica (la suma de los valores dividido por el nmero de valores). La funcin Avg no incluye ningn campo Null en el calculo.
SLCT CL!ENTES.NONBRE, CL!ENTES.APELL!DO1, CL!ENTES.APELL!DO2, AvC(PREC!O) Promedio del pedido RON DETALLE_PED!DO !NNER ]O!N PED!DOS O! DETALLE_PED!DO.CO_PED!DO = PED!DOS.CO_PED!DO !NNER ]O!N CL!ENTES O! PED!DOS.CO_CL!ENTE = CL!ENTES.CO_CL!ENTE GROUP BY CLIENTES.NJMBRE, CL!ENTES.APELL!DO1, CL!ENTES.APELL!DO2
Count Calcula el nmero de registros devueltos por una consulta. Su sintaxis es la siguiente:
COUNT(ex5r) En donde expr contiene el nombre del campo que desea contar. Los operandos de expr pueden incluir el nombre de un campo de una tabla, una constante o una funcin (la cual puede ser intrinseca o definida por el usuario pero no otras de las funciones agregadas de SQL). Puede contar cualquier tipo de datos incluso texto. Aunque expr puede realizar un calculo sobre un campo, Count simplemente cuenta el nmero de registros sin tener en cuenta qu valores se almacenan en los registros. La funcin Count no cuenta los registros que tienen campos null a menos que expr sea el caracter comodin asterisco (). Si utiliza un asterisco, Count calcula el nmero total de registros, incluyendo aquellos que contienen campos null. Count() es considerablemente mas rapida que Count(Campo).
SLCT CONT() RON PED!DOS
SLCT CL!ENTES.NONBRE, CONT() RON PED!DOS !NNER ]O!N CL!ENTES O! PED!DOS.CO_CL!ENTE = CL!ENTES.CO_CL!ENTE CROUP BY CL!ENTES.NONBRE
Nax, Nin
Devuelven el minimo o el maximo de un conjunto de valores contenidos en un campo especifico de una consulta. Su sintaxis es:
MIN(ex5r) MAX(ex5r) En donde expr es el campo sobre el que se desea realizar el calculo. Expr pueden incluir el nombre de un campo de una tabla, una constante o una funcin (la cual puede ser intrinseca o definida por el usuario pero no otras de las funciones agregadas de SQL).
SLCT CL!ENTES.NONBRE, N!!(PED!DOS.X_ALTA), NX(PED!DOS.X_ALTA) RON PED!DOS !!!R ]O!! CL!ENTES O! PED!DOS.CO_CL!ENTE = CL!ENTES.CO_CL!ENTE CROUP BY CL!ENTES.NONBRE
Sum
Devuelve la suma del conjunto de valores contenido en un campo especifico de una consulta. Su sintaxis es:
SUM(ex5r) En donde expr respresenta el nombre del campo que contiene los datos que desean sumarse o una expresin que realiza un calculo utilizando los datos de dichos campos. Los operandos de expr pueden incluir el nombre de un campo de una tabla, una constante o una funcin (la cual puede ser intrinseca o definida por el usuario pero no otras de las funciones agregadas de SQL).
SLCT CL!ENTES.NONBRE, SUN(PED!DOS.TOTAL_PED!DO) RON PED!DOS !!!R ]O!! CL!ENTES O! PED!DOS.CO_CL!ENTE = CL!ENTES.CO_CL!ENTE CROUP BY CL!ENTES.NONBRE Uso de Select TOP con consultas agregadas. Podemos utilizar SLCT TOP con consultas agregadas como con cualquier otra instruccion Transact SQL. En estos casos, la clausula TOP se aplica despues de calcular el agregado, devolviendo las N filas indicadas. En este escenario es posible que queramos obtener los N valores que satisfagan una condicion. Por ejemplo, queremos si queremos obtener los tres primeros clientes con mayores pedidos, usariamos una consulta parecida a esta:
SLCT TOP 3 CL!ENTES.NONBRE, SN(DETALLE_PED!DO.PREC!O) RON DETALLE_PED!DO !!!R ]O!! PED!DOS O! DETALLE_PED!DO.CO_PED!DO = PED!DOS.CO_PED!DO !!!R ]O!! CL!ENTES O! PED!DOS.CO_CL!ENTE = CL!ENTES.CO_CL!ENTE CROUP BY CL!ENTES.NONBRE ORDR BY 2 SN(DETALLE_PED!DO.PREC!O_N!DAD) Sin embargo, puede darse el caso, de que el cuarto cliente devuelto por la consulta tenga un valor agragado identico al tercero, (es decir, estan empatados). El uso de TOP 3 discriminaria el cuarto registro. Para evitar este comportamiento, y que la consulta devuelva tambin al cuarto cliente utilizamos la clausula!TH T!S.
SLCT TOP 3 !TH T!S CL!ENTES.NONBRE, SN(DETALLE_PED!DO.PREC!O) RON DETALLE_PED!DO !NNER ]O!N PED!DOS O! DETALLE_PED!DO.CO_PED!DO = PED!DOS.CO_PED!DO !NNER ]O!N CL!ENTES O! PED!DOS.CO_CL!ENTE = CL!ENTES.CO_CL!ENTE CROUP BY CL!ENTES.NONBRE ORDR BY 2 SN(DETALLE_PED!DO.PREC!O_N!DAD)
Operaciones con conjuntos.
SQL Server 200S permite tres tipos de operaciones con conjuntos: O N!ON, disponible en todas las versiones de SQL Server. O EXCEPT, nuevo en SQL Server 200S. O !NTERSECT, nuevo en SQL Server 200S. Para utilizar operaciones de conjuntos debemos cumplir una serie de normas. O Las consultas a unir deben tener el mismo nmero campos, y ademas los campos deben ser del mismo tipo. O Slo puede haber una nica clausula ORDER BY al final de la sentencia SELECT. U!!O! U!!O! devuelve la suma de dos o mas conjuntos de resultados. El conjunto obtenido como resultado deU!!O! tiene la misma estructura que los conjuntos originales. El siguiente ejemplo muestra el uso de U!!O!
SLCT Nombre, Apellido1 , Apellido2, NifCif, xNacimiento RON ENPLEADOS U!!O! SLCT Nombre, Apellido1 , Apellido2, NifCif, xNacimiento RON CL!ENTES Cuando realizamos una consulta con U!!O! internamente se realiza una operacion D!ST!!CT sobre el conjunto de resultados final. Si queremos obtener todos los valores debemos utiliza U!!O! LL.
SLCT Nombre, Apellido1 , Apellido2, NifCif, xNacimiento RON ENPLEADOS U!!O! ALL SLCT Nombre, Apellido1 , Apellido2, NifCif, xNacimiento RON CL!ENTES XCPT XCPT devuelve la diferencia (resta) de dos o mas conjuntos de resultados. El conjunto obtenido como resultado de XCPT tiene la misma estructura que los conjuntos originales. El siguiente ejemplo muestra el uso de XCPT
SLCT Nombre, Apellido1 , Apellido2, NifCif, xNacimiento RON ENPLEADOS XCPT SLCT Nombre, Apellido1 , Apellido2, NifCif, xNacimiento RON CL!ENTES El uso de XCPT, como norma general, es mucho mas rapido que utilizar condiciones !OT !! oX!STS en la clausula HR. !!TRSCT Devuelve la interseccin entre dos o mas conjuntos de resultados en uno. El conjunto obtenido como resultado de !!TRSCT tiene la misma estructura que los conjuntos originales. El siguiente ejemplo muestra el uso de !!TRSCT
SLCT Nombre, Apellido1 , Apellido2, NifCif, xNacimiento RON ENPLEADOS !!TRSCT SLCT Nombre, Apellido1 , Apellido2, NifCif, xNacimiento RON CL!ENTES
!nsertar datos en Transact SQL !nsercin individual de filas. Para realizar la inserccin individual de filas SQL posee la instruccin !!SRT !!TO.La inserccin individual de filas es la que mas comunmente utilizaremos. Su sintaxis es la siguiente:
INSERT INTO <342bre_tabla (<ca2541,<ca2542,...()( values (<val4r1,<val4r2,...); El siguiente ejemplo muestra la insercin de un registro en la tabla PREC!OS.
!!SRT !!TO PREC!OS (PREC!O, X_!N!C!O, X_!N, CO_PRODCTO) vLUS (10, getdate(),getdate()30, 1) !nsertcin mltiple de filas. Tambin es posible insertar en una tabla el resultado de una consulta SELECT. De este modo se insertaran tantas filas como haya devuelto la consulta SELECT. El siguiente ejemplo muestra la insercin multiple de filas.
!nsercin de valores por defecto. Tambin podemos forzar a que la inserccin se realice con los datos por defecto establecidos para la tabla (o null si no tienen valores por defecto).
!!SRT !!TO PREC!OS DULT vLUS En SQL Sever podemos marcar un campo de una tabla como autonumrico (identity), cuando insertamos un registro en dicha tabla el valor del campo se genera automaticamente. Para recuperar el valor generado disponemos de varios mtodos: O tilizar la funcion @@identity, que devuelve el ltimo valor identidad insertado por la transaccion:
PR!!T @Codigo El uso de @@!dentity no siempre es valido, ya que al devolver el litmo valor identidad insertado por la transaccin, no nos garantiza que el valor haya sido insertado en la tabla que nos interesa (por ejemplo la tabla podria tener un trigger que insertara datos en otra tabla con campos identidad). O En este tipo de escenarios debemos utilizar la funcin, SCOP_!D!T!TY.
Clausula OUTPUT A partir de la version de SQL Server 200S disponemos de la clausula OUTPUT para recuperar los valores que hemos insertado. Al igual que en un trigger disponemos de las tablas lgicas !!SRTD yDLTD. Las columnas con prefijo DLTD reflejan el valor antes de que se complete la instruccin UPDT oDLT. Es decir, son una copia de los datos "antes" del cambio. DLTD no se puede utilizar con la clausula OUTPUT en la instruccin !!SRT. Las columnas con prefijo !!SRTD reflejan el valor despus de que se complete la instruccinUPDT o !!SRT, pero antes de que se ejecuten los desencadenadores. Es decir, son una copia de los datos "despues" del cambio. !!SRTD no se puede utilizar con la clausula OUTPUT en la instruccin DLT.
Update Para la actualizacin de datos Transact SQL dispone de la sentencia UPDT. La sentencia PDATE permite la actualizacin de uno o varios registros de una nica tabla. La sintaxis de la sentencia PDATE es la siguiente
UPATE <nombre_tabla SET <campo1 = <valor1 ,<campo2 = <valor2,...,<campoN = <valorN(, WHERE <condicion(; El siguiente ejemplo muestra el uso de PDATE.
UPDT CL!ENTES ST NONBRE = 'Devjoker', APELL!DO1 = 'Herrarte', APELL!DO2 = 'Sanchez' HR CO_CL!ENTE = 10 n aspecto a tener en cuenta, sobre todo si has trabajado con ORACLE, es que SQL graba los cambios inmediatamente sin necesidad de hacer CONN!T. Por supuesto podemos gestionar nosostros las transacciones pero es algo que hay que hacer de forma explicita con la instruccion BC!! TR! y que se vera en capitulos posteriores de este tutorial. Update !!!R ]O!! En ocasiones queremos actaualizar los datos de una tabla con los datos de otra (muy comn para desnormalizar un modelo de datos). Habitualmente, usamos subconsultas para este proposito, pero Transact SQL permite la utilizacin de la sentencia PDATE !NNER ]O!N.
UPDT CL!ENTES ST NONBRE = !CHERO_CL!ENTES.NONBRE, APELL!DO1 = !CHERO_CL!ENTES.APELL!DO1, APELL!DO2 = !CHERO_CL!ENTES.APELL!DO2 RON CL!ENTES !NNER ]O!N !CHERO_CL!ENTES O! !CHERO_CL!ENTES.CO_CL!ENTE = CL!ENTES.CO_CL!ENTE Clausula OUTPUT A partir de la version de SQL Server 200S disponemos de la clausula OUTPUT para recuperar los valores que hemos insertado. Al igual que en un trigger disponemos de las tablas lgicas !!SRTD yDLTD. Las columnas con prefijo DLTD reflejan el valor antes de que se complete la instruccin UPDT oDLT. Es decir, son una copia de los datos "antes" del cambio. DLTD no se puede utilizar con la clausula OUTPUT en la instruccin !!SRT.
SLCT RON @!LAS_ACTAL!ZADAS Las columnas con prefijo !!SRTD reflejan el valor despus de que se complete la instruccinUPDT o !!SRT, pero antes de que se ejecuten los desencadenadores. Es decir, son una copia de los datos "despues" del cambio. !!SRTD no se puede utilizar con la clausula OUTPUT en la instruccin DLT.
Borrar datos en Transact SQL Delete Para borrar datos de una tabla debemos utilizar la sentencia DELETE. Para ejecutar los ejemplos de este capitulo debemos ejecutar el siguiente script, que crea la tabla "DATOS" y carga registros en ella.
CREATE TABLE DATOS ( !d int identity not null, dato varchar(100), fx_alta datetime, constraint PK_DATOS PR!NARY KEY (!d) )
CO
DECLARE @i int, @dato varchar(100) set @i = 0 WH!LE (@i <100) BEC!N SET @i = @i 1 set @dato = 'Dato:' cast(@i as varchar) !NSERT !NTO DATOS (dato, fx_alta) vALES (@dato, getdate()) END
CO
SELECT from DATOS
Para borrar los registros de la tabla "DATOS" ejecutaremos la siguiente instruccin. Notese que no se especifica ninguna condicin WHERE por lo que se borran todos los datos de la tabla.
DELETE RON DATOS Lgicamente podemos especicar que registros queremos borrar a travs de la clausula WHERE.
DELETE RON DATOS WHERE !d=12 Cuando borramos datos de una tabla, podemos obtener el nmero de filas que han sido afectadas por la instruccin a travs de la variable @@RowCount. El siguiente ejemplo ilustra el uso de @@RowCount.
DELETE RON DATOS WHERE !d=17
SELECT @@ROWCONT Clausula OUTPUT A partir de la version de SQL Server 200S disponemos de la clausula OUTPUT para recuperar los valores que hemos insertado. Al igual que en un trigger disponemos de las tablas lgicas !!SRTD yDLTD. Las columnas con prefijo DLTD reflejan el valor antes de que se complete la instruccin UPDT oDLT. Es decir, son una copia de los datos "antes" del cambio. DLTD no se puede utilizar con la clausula OUTPUT en la instruccin !!SRT.
DELETE RON DATOS OTPT DELETED. !NTO @!LAS_BORRADAS WHERE !d=17
SELECT from @!LAS_BORRADAS Truncate Table Para borrar datos de forma masiva disponemos de la instruccin TRNCATE TABLE, que borra todos los datos de una tabla.
TRNCATE TABLE DATOS Cuando trabajamos con TRNCATE TABLE debemos tener en cuenta las siguientes consideraciones: O TRNCATE TABLE no admite la clausula WHERE. O No podemos ejecutar TRNCATE TABLE sobre tablas que sean "padres" en foreign keys.
Transacciones en Transact SQL Concepto de transaccion na transaccin es un conjunto de operaciones Transact SQL que se ejecutan como un nico bloque, es decir, si falla una operacin Transact SQL fallan todas. Si una transaccin tiene xito, todas las modificaciones de los datos realizadas durante la transaccin se confirman y se convierten en una parte permanente de la base de datos. Si una transaccin encuentra errores y debe cancelarse o revertirse, se borran todas las modificaciones de los datos. El ejemplo clasico de transaccin es una transferencia bancaria, en la que quitamos saldo a una cuenta y lo anadimos en otra. Si no somo capaces de abonar el dinero en la cuenta de destino, no debemos quitarlo de la cuenta de origen. SQL Server funciona por defecto con Transacciones de confirmacin automatica , es decir, cada instruccin individual es una transaccin y se confirma automaticamente. Sobre el ejemplo anterior de la transferencia bancaria, un script deberia realizar algo parecido a los siguiente:
DCLR @importe DC!NL(18,2), @CuentaOrigen vRCHR(12), @CuentaDestino vRCHR(12) Asignamos el importe de la transferencia y las cuentas de origen y destino
ST @importe = S0 ST @CuentaOrigen = '200700000001' ST @CuentaDestino = '200700000002'
Descontamos el importe de la cuenta origen UPDT CENTAS ST SALDO = SALDO @importe HR NNCENTA = @CuentaOrigen
Esta forma de actuar seria erronea, ya que cada instruccin se ejecutaria y confirmaria de forma independiente, por lo que un error dejaria los datos erroneos en la base de datos ( y ese es el peor error que nos podemos encontrar! ) Transacciones implicitas y explicitas Para agrupar varias sentencias Transact SQL en una nica transaccin, disponemos de los siguientes mtodos: O Transacciones explicitas Cada transaccin se inicia explicitamente con la instruccin BC!! TR!SCT!O! y se termina explicitamente con una instruccin CONN!T o ROLLBC. O Transacciones implicitas Se inicia automativamente una nueva transaccin cuando se ejecuta una instruccin que realiza modificaciones en los datos, pero cada transaccin se completa explicitamente con una instruccinCONN!T o ROLLBC. Para activardesactivar el modo de transacciones implicitas debemos ejecutar la siguiente instruccin.
Activamos el modo de transacciones implicitas ST !NPL!C!T_TR!SCT!O!S O!
Desactivamos el modo de transacciones implicitas ST !NPL!C!T_TR!SCT!O!S O Cuando la opcin !S!_DULTS esta establecida en O!, !NPL!C!T_TR!SCT!O!S tambin se establece en O!. El siguiente ejemplo muestra el script anterior haciendo uso de transacciones explicitas.
Confirmamos la transaccion CONN!T TR!SCT!O! O solo CONN!T !D TRY BC!! CTCH Hay un error, deshacemos los cambios ROLLBC TR!SCT!O! O solo ROLLBACK PR!!T 'Se ha producido un error!' !D CTCH
La transaccin sigue activa hasta que emita una instruccin CONN!T o ROLLBC. na vez que la primera transaccin se ha confirmado o revertido, se inicia automaticamente una nueva transaccin la siguiente vez que la conexin ejecuta una instruccion para modificar datos. La conexin contina generando transacciones implicitas hasta que se desactiva el modo de transacciones implicitas. Podemos verificar el nmero de transacciones activas a travs de @@TRANCONT.
ST !NPL!C!T_TR!SCT!O!S O! BC!! TRY UPDT CENTAS ST XALTA = XALTA 1 PR!!T @@TRANCONT CONN!T !D TRY BC!! CTCH ROLLBC PR!!T 'Error' !D CTCH Otro punto a tener en cuenta cuando trabajamos con transacciones son los bloqueos y el nivel de aislamiento. Podemos aprender ms sobre b|oqueos y n|ve| de a|s|am|ento en este art|cu|o. Transacciones anidadas. Podemos anidar varias transacciones. Cuando anidamos varias transacciones la instruccin CONN!T afectara a la ltima transaccin abierta, pero ROLLBACK afectara a todas las transacciones abiertas. n hecho a tener en cuenta, es que, si hacemos ROLLBACK de la transaccin superior se desharan tambin los cambios de todas las transacciones internas, aunque hayamos realizado CONN!T de ellas.
BC!! TR!
UPDT ENPLEADOS ST NONBRE = 'Devjoker' HR !D=101
BC!! TR!
UPDT ENPLEADOS ST APELL!DO1 = 'Devjoker.CON' HR !D=101
Este CONN!T solo afecta a la segunda transaccion. CONN!T
Este ROLLBACK afecta a las dos transacciones. ROLLBC
na consideracin a tener en cuanta cuando trabajamos con transacciones anidadas es la posibilidad de utilizar puntos de guardado o SAvEPO!NTs. Puntos de recuperacion (SavePoint). Los puntos de recuperacin (SavePoints) permiten manejar las transacciones por pasos, pudiendo hacer rollbacks hasta un punto marcado por el savepoint y no por toda la transaccin. El siguiente ejemplo muestra como trabajar con puntos de recuperacin.
BC!! TR!
UPDT ENPLEADOS ST NONBRE = 'Devjoker' HR !D=101
UPDT ENPLEADOS ST APELL!DO1 = 'Devjoker.CON' HR !D=101
Sv TR!SCT!O! P1 Cuardamos la transaccion (Savepoint)
UPDT ENPLEADOS ST APELL!DO1 = 'Otra cosa!' HR !D=101
Este ROLLBACK afecta solo a las instrucciones posteriores al savepoint P1. ROLLBC TR!SCT!O! P1
Confirmamos la transaccion CONN!T
Procedimientos almacenados en Transact SQL
n procedimiento es un programa dentro de la base de datos que ejecuta una accin o conjunto de acciones especificas. n procedimiento tiene un nombre, un conjunto de parametros (opcional) y un bloque de cdigo. En Transact SQL los procedimientos almacenados pueden devolver valores (numerico entero) o conjuntos de resultados. Para crear un procedimiento almacenado debemos emplear la sentencia CRT PROCDUR.
CRT PROCDUR <nombre_procedure |@param1 <tipo, ...] S Sentencias del procedure Para modificar un procedimiento almacenado debemos emplear la sentencia LTR PROCDUR.
LTR PROCDUR <nombre_procedure |@param1 <tipo, ...] S Sentencias del procedure
El siguiente ejemplo muestra un procedimiento almacenado, denominado spu_addCliente que inserta un registro en la tabla "CL!ENTES".
Para la ejecutar un procedimiento almacenado debemos utilizar la sentencia XC. Cuando la ejecucin del procedimiento almacenado es la primera instruccin del lote, podemos omitir el uso de XC. El siguiente ejemplo muestra la ejecucin del procedimiento almacenado anterior.
DCLR @fecha_nacimiento datetime set @fecha_nacimiento = convert(datetime, '130S137S', 103) XC spu_addCliente 'Pedro', 'Herrarte', 'Sanchez', '00000002323', @fecha_nacimiento Siempre es deseable que las instrucciones del procedure esten dentro de un bloque TRY CTCH y controlados por una transaccin.
LTR PROCDUR spu_addCliente @nombre varchar(100), @apellido1 varchar(100), @apellido2 varchar(100), @nifCif varchar(20), @fxNaciento datetime S BC!! TRY BC!! TR! !!SRT !!TO CL!ENTES (nombre, apellido1, apellido2, nifcif, fxnacimiento) vLUS (@nombre, @apellido1, @apellido2, @nifCif, @fxNaciento) CONN!T !D TRY BC!! CTCH ROLLBC PR!!T ERROR_NESSACE() !D CTCH Si queremos que los parametros de un procedimiento almacenado sean de entradasalida debemos especificarlo a travs de la palabra clave OUTPUT , tanto en la definicin del procedure como en la ejecucin. El siguiente ejemplo muestra la definicin de un procedure con parametros de salida.
DCLR @saldo decimal(10,2) XC spu_ObtenerSaldoCuenta '200700000001', @saldo output PR!!T @saldo n procedimiento almacenado puede devolver valores numericos enteros a travs de la instruccin RETRN. Normalmente debemos utilizar los valores de retorno para determinar si la ejecucin del procedimiento ha sido correcta o no. Si queremos obtener valores se recomienda utilizar parametros de salida o funciones escalares (se veran mas adelante en este tutorial). El siguiente ejemplo muestra un procedimiento almacenado que devuelve valores.
CRT PROCDUR spu_EstaEnNumerosRojos @numCuenta varchar(20) S BC!! ! (SLCT SALDO RON CENTAS HR NNCENTA = @numCuenta) < 0 BC!! RTUR! 1 !D LS RTUR! 0 !D El siguiente ejemplo muestra como ejecutar el procedure y obtener el valor devuelto.
DCLR @rv int XC @rv = spu_EstaEnNumerosRojos '200700000001' PR!!T @rv Otra caracteristica muy interesante de los procedimientos almacenados en Transact SQL es que pueden devolver uno o varios conjuntos de resultados. El siguiente ejemplo muestra un procedimiento almacenado que devuelve un conjunto de resultados.
CRT PROCDUR spu_NovimientosCuenta @numCuenta varchar(20) S BC!! SLCT @numCuenta, SALDO_ANTER!OR, SALDO_POSTER!OR, !NPORTE, XNOv!N!ENTO RON NOv!N!ENTOS !NNER ]O!N CENTAS O! NOv!N!ENTOS.!DCENTA = CENTAS.!DCENTA HR NNCENTA = @numCuenta ORDR BY XNOv!N!ENTO DSC !D La ejecucin del procedimiento se realiza normalmente.
SQL Server proporciona al usuario la posibilidad de definir sus propias funciones, conocidad como D (user defined functions). Exisiten tres tipos de funciones. Estas son: O unciones escalares. O unciones en linea. O unciones en linea de multiples sentencias unciones escalares Las funciones escalares devuelven un nico valor de cualquier tipo de los datos tal como int, money, varchar, real, etc. La sintaxis para una funcin escalar es la siguiente:
CRT U!CT!O! <Scalar_unction_Name, sysname, unctionName ( Lista de parametros <@Param1, sysname, @p1 <Data_Type_or_Param1, , int, ... ) Tipo de datos que devuelve la funcin. RTUR!S <unction_Data_Type, ,int S BC!! ... !D El siguiente ejemplo muestra como crear una funcin escalar.
SLCT @Saldo = SALDO RON CENTAS HR NNCENTA = @NumCuenta
ST @Return = @Saldo @Nultiplicador
RTUR! @Return !D Pueden ser utilizadas en cualquier sentencia Transact SQL. n aspecto a tener en cuenta, es que para utilizar una funcin escalar debemos identificar el nombre de la funcin con el propietario de la misma. El siguiente ejemplo muestra como utilizar la funcin anteriormente creada en una sentencia Transact SQL. n aspecto muy a tener en cuenta es que la funcin ejecutara sus sentencias SELECT una vez por cada fila del conjunto de resultados devuelto por la consulta SELECT principal.
SLCT !DCENTA, NNCENTA, SALDO, XALTA, Ejecucion de la funcion: dbo.fn_NultiplicaSaldo( NNCENTA, !DCENTA) S RESLTADO RON CENTAS El siguiente ejemplo muestra como utilizar una funcin escalar en un script Transact SQL.
DCLR @NumCuenta vRCHR(20), @Resultado DC!NL(10,2)
ST @NumCuenta = '200700000001' ST @Resultado = dbo.fn_NultiplicaSaldo(@NumCuenta, 30.S)
PR!!T @Resultado Las funciones escalares son muy similares a proced|m|entos a|macenados con parametros de salida, pero estas pueden ser utilizadas en consultas de seleccion y en la clausula where de las mismas. Las funciones no pueden ejecutar sentencias !NSERT o PDATE. unciones en linea Las funciones en linea son las funciones que devuelven un conjunto de resultados correspondientes a la eecucin de una sentencia SELECT. La sintaxis para una funcin de tabla en linea es la siguiente:
CRT U!CT!O! <!nline_unction_Name, sysname, unctionName ( Lista de parametros <@param1, sysname, @p1 <Data_Type_or_Param1, , int,... ) RTUR!S TBL S RTUR! ( Sentencia Transact SQL ) El siguiente ejemplo muestra como crear una funcin en linea.
CRT U!CT!O! fn_NovimientosCuenta ( @NumCuenta vRCHR(20) ) RTUR!S TBL S RTUR! ( SLCT NOv!N!ENTOS. RON NOv!N!ENTOS !NNER ]O!N CENTAS O! NOv!N!ENTOS.!DCENTA = CENTAS.!DCENTA HR CENTAS.NNCENTA = @NumCuenta ) No podemos utilizar la clausula ORDER BY en la sentencia de una funcin el linea. Las funciones en linea pueden utilizarse dentro de joins o querys como si fueran una tabla normal.
SLCT RON fn_NovimientosCuenta('200700000001')
SLCT RON CENTAS !NNER ]O!N CENTAS_CL!ENTE O! CENTAS_CL!ENTE.!DCENTA = CENTAS.!DCENTA !NNER ]O!N CL!ENTES O! CL!ENTES.id = CENTAS_CL!ENTE.!DCL!ENTE !NNER ]O!N fn_NovimientosCuenta('200700000001') A O! A.!DCENTA= CENTAS.!DCENTA unciones en linea de multiples sentencias Las funciones en linea de multiples sentencias son similares a las funciones en linea excepto que el conjunto de resultados que devuelven puede estar compuesto por la ejecucin de varios consultas SLCT. Este tipo de funcin se usa en situaciones donde se requiere una mayor lgica de proceso. La sintaxis para una funciones de tabla de multi sentencias es la siguiente:
CRT U!CT!O! <Table_unction_Name, sysname, unctionName ( Lista de parametros <@param1, sysname, @p1 <data_type_for_param1, , int, ... ) RTUR!S variable de tipo tabla y su estructura <@Table_variable_Name, sysname, @Table_var TBL ( <Column_1, sysname, c1 <Data_Type_or_Column1, , int, <Column_2, sysname, c2 <Data_Type_or_Column2, , int ) S BC!! Sentencias que cargan de datos la tabla declarada RTUR! !D El siguiente ejemplo muestra el uso de una funcion de tabla de multi sentencias.
Esta funcion busca la tres cuentas con mayor saldo y obtiene los tres ltimos movimientos de cada una de estas cuentas
CRT U!CT!O! fn_CuentaNovimietos() RTUR!S @datos TBL ( Estructura de la tabla que devuelve la funcion. NumCuenta varchar(20), Saldo decimal(10,2), Saldo_anterior decimal(10,2), Saldo_posterior decimal(10,2), !mporte_Novimiento decimal(10,2), xNovimiento datetime ) S BC!! variables necesarias para la lgica de la funcion. DCLR @idcuenta int, @numcuenta varchar(20), @saldo decimal(10,2)
Cursor con las 3 cuentas de mayor saldo DCLR CDATOS CURSOR OR SLCT TOP 3 !DCENTA, NNCENTA, SALDO RON CENTAS ORDR BY SALDO DSC
Recorremos el cursor H!L (@@ETCH_STATS = 0) BC!! !nsertamos la cuenta en la variable de salida !!SRT !!TO @datos (NumCuenta, Saldo) vLUS (@numcuenta, @saldo) !nsertamos los tres ltimos movimientos de la cuenta !!SRT !!TO @datos (Saldo_anterior, Saldo_posterior, !mporte_Novimiento, xNovimiento ) SLCT TOP 3 SALDO_ANTER!OR, SALDO_POSTER!OR, !NPORTE, XNOv!N!ENTO RON NOv!N!ENTOS HR !DCENTA = @idcuenta ORDR BY XNOv!N!ENTO DSC vamos a la siguiente cuenta TCH CDATOS !!TO @idcuenta, @numcuenta, @saldo !D
SQL Server pone a nuestra disposicin multitud de funciones predefinidas que proporcionan un amplio abanico de posibilidades. Nostramos aqui algunas de las frecuentes. Podemos acceder al listado completo a travs del siguiente enlace: ttp:||tecnet.m|crosoft.com|es-es|||brary|ms18778.aspx Cast y Convert Convierten una expresin de un tipo de datos en otro de forma explicita. CST y CO!vRTproporcionan funciones similares. CO!vRT ( data_type | ( length ) ] , expression | , style ] ) Donde: O data_type, es el tipo de destino al que queremos convertir la expresion O expresion, la expresion que queremos convertir O style, parametro opcional que especifica el formato que tiene expresion. Por ejemplo, si queremos convertir un varchar a datetime, aqui debemos especificar el formato de la fecha (el tipo varchar).
DECLARE @fecha varchar(20) Convertimos un valor varchar a datetime El 103 indica el formato en el que esta escrita la fecha 103 = ddmmaa SET @fecha = CONvERT(datetime, '13032008',103)
SELECT @fecha
DECLARE @fecha datetime, @fechaormateada varchar(20) Convertimos ahora una fecha a varchar y la formateamos 3 = ddmmaa SET @fecha = CETDATE() SET @fechaormateada = CONvERT(varchar(20), @fecha, 3)
SELECT @fechaormateada
n ejemplo utilizando CAST DECLARE @dato varchar(2), @dato2 int SET @dato = '27' SET @dato2 = cast(@dato AS int)
SELECT @dato2 A continuacin mostramos la tabla de cdigos de estilo (obtenida de NicroSoft). $in el siglo (aa) ( 1 ) Con el siglo ?(aaaa) Estndar Entrada/salida ( 3 ) 0 o 100 ( 1,
2 ) valor predeterminado mes dd aaaa hh:mia.m. (o p. m.) 1 101 EE.. mmddaaaa 2 102 ANS! aa.mm.dd 3 103 Britanicorancs ddmmaa 4 104 Aleman dd.mm.aa S 10S !taliano ddmmaa 6 106 (1) dd mes aa 7 107 (1) Nes dd, aa 8 108 hh:mi:ss 3 o 103 ( 1,
2 ) valor predeterminado milisegundos mes dd aaaa hh:mi:ss:mmma.m. (o p. m.) 10 110 EE.. mmddaa 11 111 ]APON aammdd 12 112 !SO aammdd 13 o 113 ( 1,
127( 6, 7 ) !SO8601 con zona horaria Z. aaaammddThh:mi:ss.mmmZ (sin espacios) 130 ( 1,
2 ) Hijri ( S ) dd mes aaaa hh:mi:ss:mmma.m. 131 ( 2 ) Hijri ( S ) ddmmaa hh:mi:ss:mmma.m. !snull Evalua una expresion de entrado y si esta es NLL, reemplaza NLL con el valor de reemplazo especificado. El valor de reemplazo debe ser del mismo tipo de datos que la expresion a evaluar. !S!ULL ( expression , replacement_value )
DECLARE @dato!nt int, @datovarchar varchar(100)
SET @dato!nt = NLL SET @datovarchar = NLL
SELECT !SNLL(@dato, 1), !SNLL(@datovarchar, 'No hay dato') COLSC Devuelve la primera expresin distinta de NLL entre sus argumentos. n aspecto a tener en cuenta es que todos los argumentos deben ser del mismo tipo. COLSC ( expression | ,...n ] )
SET @dato1 = null SET @dato2 = NLL SET @dato3 = NLL SET @dato4 = 100 SET @datoS = 12S
Devuelve 100 SELECT COALESCE(@dato1,@dato2,@dato3,@dato4,@datoS) CetDate y CetUTCDate CetDate devuelve la fecha y hora actuales del sistema en el formato interno estandar de SQL Server 200S para los valores datetime. CetUTCDate devuelve el valor datetime que representa la hora TC (hora universal coordinada u hora del meridiano de Creenwich) actual.
DECLARE @fechaLocal datetime, @fechaTC datetime
SET @fechaLocal = getdate() SET @fechaTC = CETTCDATE()
SELECT @fechaLocal, @fechaTC
Triggers en Transact SQL n trigger( o desencadenador) es una clase especial de procedimiento almacenado que se ejecuta automaticamente cuando se produce un evento en el servidor de bases de datos. SQL Server proporciona los siguientes tipos de triggers: O Trigger DNL, se ejecutan cuando un usuario intenta modificar datos mediante un evento de lenguaje de manipulacin de datos (DNL). Los eventos DNL son instrucciones !NSERT, PDATE o DELETE de una tabla o vista. O Trigger DDL, se ejecutan en respuesta a una variedad de eventos de lenguaje de definicin de datos (DDL). Estos eventos corresponden principalmente a instrucciones CREATE, ALTER y DROP de TransactSQL, y a determinados procedimientos almacenados del sistema que ejecutan operaciones de tipo DDL. Trigger DNL. Los trigger DNL se ejecutan cuando un usuario intenta modificar datos mediante un evento de lenguaje de manipulacin de datos (DNL). Los eventos DNL son instrucciones !NSERT, PDATE o DELETE de una tabla o vista. La sintaxis general de un trigger es la siguiente.
CRT TR!CCR <Trigger_Name, sysname, Trigger_Name O! <Table_Name, sysname, Table_Name ATER <Data_Nodification_Statements, , !!SRT,DLT,UPDT S BC!! SET NOCONT ON added to prevent extra result sets from interfering with SELECT statements. ST !OCOU!T O!, !nsert statements for trigger here !D Antes de ver un ejemplo es necesario conocer las tablas inserted y deleted. Las instrucciones de triggers DNL utilizan dos tablas especiales denominadas inserted y deleted. SQL Server 200S crea y administra automaticamente ambas tablas. La estructura de las tablas inserted ydeleted es la misma que tiene la tabla que ha desencadenado la ejecucin del trigger. La primera tabla (inserted) solo esta disponible en las operaciones !NSERT y PDATE y en ella estan los valores resultantes despues de la insercin o actualizacin. Es decir, los datos insertados. !nserted estara vacia en una operacin DELETE. En la segunda (deleted), disponible en las operaciones PDATE y DELETE, estan los valores anteriores a la ejecucin de la actualizacin o borrado. Es decir, los datos que seran borrados. Deleted estara vacia en una operacion !NSERT. No existe una tabla PDATED? No, hacer una actualizacin es lo mismo que borrar (deleted) e insertar los nuevos (inserted). La sentencia PDATE es la nica en la que inserted y deleted tienen datos simultaneamente. No puede se modificar directamente los datos de estas tablas. El siguiente ejemplo, graba un historico de saldos cada vez que se modifica un saldo de la tabla cuentas.
CRT TR!CCR TR_CENTAS O! CENTAS ATER UPDT S BC!! SET NOCONT ON impide que se generen mensajes de texto con cada instruccin ST !OCOU!T O!, !!SRT !!TO HCO_SALDOS (!DCENTA, SALDO, XSALDO) SLCT !DCENTA, SALDO, getdate() RON !NSERTED !D La siguiente instruccin provocara que el trigger se ejecute:
UPDT CENTAS ST SALDO = SALDO 10 HR !DCENTA = 1 na consideracin a tener en cuenta es que el trigger se ejecutara aunque la instruccion DNL (PDATE, !NSERT o DELETE ) no haya afectado a ninguna fila. En este caso inserted y deleted devolveran un conjunto de datos vacio. Podemos especificar a que columnas de la tabla debe afectar el trigger.
LTR TR!CCR TR_CENTAS O! CENTAS ATER UPDT S BC!! SET NOCONT ON impide que se generen mensajes de texto con cada instruccin ST !OCOU!T O!,
! UPDT(SALDO) Solo si se actualiza SALDO BC!! !!SRT !!TO HCO_SALDOS (!DCENTA, SALDO, XSALDO) SLCT !DCENTA, SALDO, getdate() RON !NSERTED !D !D Los trigger estan dentro de la transaccin original (!nsert, Delete o pdate) por lo cual si dentro de nuestro trigger hacemos un RollBack Tran, no solo estaremos echando atras nuestro trigger sino tambin toda la transaccin, en otras palabras si en un trigger ponemos un RollBack Tran, la transaccin de !nsert, Delete o pdate volvera toda hacia atras.
LTR TR!CCR TR_CENTAS O! CENTAS ATER UPDT S BC!! SET NOCONT ON impide que se generen mensajes de texto con cada instruccin ST !OCOU!T O!, !!SRT !!TO HCO_SALDOS (!DCENTA, SALDO, XSALDO) SLCT !DCENTA, SALDO, getdate() RON !NSERTED
ROLLBC !D En este caso obtendremos el siguiente mensaje de error: La transaccin termin en el desencadenador. Se anul el lote. Podemos activar y desactivar Triggers a tarvs de las siguientes instrucciones.
Desactiva el trigger TR_CENTAS D!SBL TR!CCR TR_CENTAS O! CENTAS CO activa el trigger TR_CENTAS !BL TR!CCR TR_CENTAS O! CENTAS CO Desactiva todos los trigger de la tabla CENTAS LTR TBL CENTAS D!SBL TR!CCR ALL CO Activa todos los trigger de la tabla CENTAS LTR TBL CENTAS !BL TR!CCR ALL
Trigger DDL Los trigger DDL se ejecutan en respuesta a una variedad de eventos de lenguaje de definicin de datos (DDL). Estos eventos corresponden principalmente a instrucciones CREATE, ALTER y DROP de TransactSQL, y a determinados procedimientos almacenados del sistema que ejecutan operaciones de tipo DDL. La sintaxis general de un trigger es la siguiente.
CRT TR!CCR <trigger_name, sysname, table_alter_drop_safety O! DTBS OR <data_definition_statements, , DROP_TABLE, ALTER_TABLE S BC!! ... EN La siguiente instruccin impide que se ejecuten sentencias DROP TABLE y ALTER TABLE en la base de datos.
CRT TR!CCR TR_SECR!DAD O! DTBS OR DROP_TABLE, ALTER_TABLE S BC!! R!SRROR ('No est permitido borrar ni modificar tablas !' , 16, 1) ROLLBC TR!SCT!O! !D