0% encontró este documento útil (0 votos)
90 vistas

Transact SQL

Este documento introduce Transact SQL, el lenguaje de programación de SQL Server para extender SQL con instrucciones adicionales como variables, bucles y sentencias de control de flujo. Explica conceptos básicos como tipos de datos, declaración de variables, asignación de valores y uso de lotes.

Cargado por

BryanSersoker
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOC, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
90 vistas

Transact SQL

Este documento introduce Transact SQL, el lenguaje de programación de SQL Server para extender SQL con instrucciones adicionales como variables, bucles y sentencias de control de flujo. Explica conceptos básicos como tipos de datos, declaración de variables, asignación de valores y uso de lotes.

Cargado por

BryanSersoker
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOC, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 38

Introduccin a Transact SQL

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. Transact SQL es el lenguaje procedimental de programacin que proporciona SQL Server para ampliar SQL con los elementos caractersticos de los lenguajes de programacin: variables, sentencias de control de flujo, buclesTransact SQL es el lenguaje de programacin que proporciona SQL Server para extender el SQL estndar con otro tipo de instrucciones. Con Transact SQL vamos a poder programar las unidades de programa de la base de datos SQL Server, estn son: Procedimientos almacenados Funciones Triggers Scripts Pero adems Transact SQL nos permite realizar programas sobre las siguientes herramientas de SQL Server: Service Broker Fundamentos de Transact SQL Para programar en Transact SQL es necesario conocer sus fundamentos. Como introduccin vamos a ver algunos elementos y conceptos bsicos del lenguaje. Transact SQL no diferencia maysculas de minsculas Un comentario es una aclaracin que el programador incluye en el cdigo, dos tipos: o -- Para un comentario de lnea simple o /* ... */ Para un comentario de varias lneas Un literal es un valor fijo de tipo numrico, carcter, cadena o lgico no representado por un identificador (es un valor explcito). Una 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 carcter @, 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:
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.
Un 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. Un script est compuesto por uno o varios lotes. Un lote delimita el alcance de las variables y sentencias del script. Dentro de un mismo script se diferencian los diferentes lotes a travs de la instruccin GO.
-- Este es el primer lote del script SELECT * FROM COMENTARIOS

GO -- GO 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 disco-memoria 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 numricos. Cuanto mayor sea el nmero que puedan almacenar mayor ser en consecuencia el espacio utilizado para almacenarlo. Como regla general se recomienda usar el tipo de dato mnimo posible. Todos los datos numricos admiten el valor NULL. Bit. Puede almacenar el rango de valores de 1 a 0. Tinyint. Puede almacenar el rango de valores de 0 a 255. SmallInt. Puede almacenar el rango de valores -32768 a 32767. Int. Puede almacenar el rango de valores -231 a 231-1. BigInt. Puede almacenar el rango de valores -263 a 263-1. Decimal(p,s). Una columna de tipo decimal puede almacenar datos numricos decimales sin redondear. Donde p es la precisin (nmero total del dgitos) y s la escala (nmero de valores decimales) Flota[(n)]. Una columna de datos float puede almacenar el rango de valores -1,79x-10308 a 1,79x-10308, si la definimos con el valor mximo de precisin.
Donde n es el nmero de bits que se utilizan para almacenar la mantisa del nmero float en notacin cientfica y, por tanto, dicta su precisin y el tamao de almacenamiento. Si se especifica n, debe ser un valor entre 1 y 53. El valor predeterminado de n es 53. n value Precisin Tamao de almacenamiento 1-24 7 dgitos 4 bytes 25-53 15 dgitos 8 bytes SQL Server 2005 trata n como uno de dos valores posibles. Si 1<=n<=24, n se trata como 24. Si 25<=n<=53, n se trata como 53.

Real. Sinnimo de float(24). Puede almacenar el rango de valores -3,4x-1038 a 3,4x-1038, Money - SmallMoney: Almacena valores numricos monetarios, con una precisin de hasta diez milsimas de la unidad monetaria.
Tipo de datos

Money
smallmoney

Intervalo De -922,337,203,685.477,5808 a 922,337,203,685.477,5807 De - 214.748,3648 a 214.748,3647

Almacenamiento 8 bytes 4 bytes

Notas Los tipos de datos Money y smallmoney tienen una precisin de una diezmilsima de las unidades monetarias que representan.

Todos los tipos de datos enteros pueden marcarse con la propiedad identity para hacerlos autonumricos.
DECLARE @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

4
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 carcter. Char(n). Almacena n caracteres en formato ASCII, 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(5), guardamos el valor 'A', se almacena 'A ', ocupando los cinco bytes. Varchar(n).Almacena n caracteres en formato ASCII, un byte por cada letra. Cuando almacenamos datos en el tipo varchar, nicamente se utilizan los caracteres necesarios. Por ejemplo, si en un varchar(255), guardamos el valor 'A', se almacena 'A', ocupando solo un byte bytes. Varchar(max). Igual que varchar, pero al declararse como max puede almacenar 231-1 bytes. Nchar(n).Almacena n caracteres en formato UNICODE, dos bytes por cada letra. Es recomendable utilizar este tipo de datos cuando los valores que vayamos a almacenar puedan pertenecer a diferentes idiomas. Nvarchar(n).Almacena n caracteres en formato UNICODE, dos bytes por cada letra. Es recomendable utilizar este tipo de datos cuando los valores que vayamos a almacenar puedan pertenecer a diferentes idiomas. Nvarchar(max).Igual que varchar, pero al declararse como max puede almacenar 231-1 bytes.

Tipos de datos de fecha. Datetime. Almacena fechas con una precisin de milisegundo. Debe usarse para fechas muy especificas. SmallDatetime. Almacena fechas con una precisin 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 automticamente 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 mxima de 8000 bytes. Varbinary. Se utiliza para almacenar datos binarios de longitud variable, con una longitud mxima de 8000 bytes... Es muy similar a binary, salvo que varbinary utiliza menos espacio en disco. Varbinary(max).Igual que varbinary, pero puede almacenar 231-1 bytes Tipos de datos personalizados. Transact SQL permite la creacin de tipos de datos personalizados, a travs de la instruccin CREATE TYPE. Personalmente, desaconsejo el uso de tipos de datos personalizados

CREATE TYPE MD5 FROM CHAR(32) NULL GO DECLARE @miMD5 MD5 set @miMD5 = '0000000000000000000000000000000A' print @miMD5

Declarar variables es Transact SQL Una 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 carcter @, 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. 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

Asignar variables en Transact SQL


En Transact SQL podemos asignar valores a una variable de varias formas: A travs de la instruccin set. Utilizando una sentencia SELECT. Realizando un FETCH de un cursor. El siguiente ejemplo muestra como asignar una variable utilizando la instruccin SET.
DECLARE @nombre VARCHAR(100) -- La consulta debe devolver un nico registro SET @nombre = (SELECT nombre FROM empleados where nemp = 2)

PRINT @nombre El siguiente ejemplo muestra como asignar variables utilizando una sentencia SELECT.
DECLARE @nombre VARCHAR(100), @apellido VARCHAR(100), @sueldo numeric(7,2) SELECT @nombre=nombre , @apellido=Apellido, @sueldo=sueldo FROM empleados WHERE nemp = 1 PRINT @nombre PRINT @apellido PRINT cast(@sueldo as varchar(20)) + '' select * from empleados where nemp = 1

Un punto a tener en cuenta cuando asignamos variables de este modo, es que si la consulta SELECT devuelve ms de un registro, las variables quedarn asignadas con los valores de la ltima fila devuelta. Por ltimo veamos como asignar variables a travs de un cursor.
DECLARE @nombre VARCHAR(100), @apellido VARCHAR(100), @sueldo numeric(7,2) DECLARE CDATOS CURSOR FOR SELECT nombre , Apellido, sueldo FROM empleados OPEN CDATOS FETCH CDATOS INTO @nombre, @apellido, @sueldo

7
WHILE (@@FETCH_STATUS = 0) BEGIN PRINT @nombre PRINT @apellido PRINT @sueldo FETCH CDATOS INTO @nombre, @apellido, @sueldo END CLOSE CDATOS DEALLOCATE CDATOS

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) = (igual a) <> (distinto de) != (distinto de) < (menor que) > (mayor que) >= (mayor o igual a) <= (menor o igual a) !> (no mayor a) !< (no menor a) AND (y lgico) NOT (negacion) OR (o lgico) & (AND a nivel de bit) | (OR a nivel de bit) ^ (OR exclusivo a nivel de bit) + ALL (Devuelve TRUE si el conjunto completo de comparaciones es TRUE) ANY(Devuelve TRUE si cualquier elemento del conjunto de comparaciones es TRUE) BETWEEN (Devuelve TRUE si el operando est dentro del intervalo) EXISTS (TRUE si una subconsulta contiene filas) IN (TRUE si el operando est en la lista) LIKE (TRUE si el operando coincide con un patron) NOT (Invierte el valor de cualquier operador booleano) SOME(Devuelve TRUE si alguna de las comparaciones de un conjunto es TRUE)

Operadores relacionales o de comparacin

Operadores lgicos

Operador de concatenacin

Otros

Estructuras de control en Transact SQL

Estructura condicional IF
La estructura condicional IF permite evaluar una expresin booleana (resultado SI - NO), y ejecutar las operaciones contenidas en el bloque formado por BEGIN END.
IF (<expresion>) BEGIN ... END ELSE IF (<expresion>) BEGIN ... END ELSE BEGIN ... END

Ejemplo de la estructura condicional IF.


DECLARE @Web varchar(100), @diminutivo varchar(3) SET @diminutivo = 'DJK' IF @diminutivo = 'DJK' BEGIN PRINT 'www.devjoker.com' END ELSE BEGIN PRINT 'Otra Web (peor!)' END

La estructura IF admite el uso de subconsultas:


DECLARE @nemp int, @sueldo numeric(7,2) set @nemp = 20 set @sueldo = 5.5 IF EXISTS(SELECT * FROM empleados WHERE nemp = @nemp) BEGIN print('el empleado existe') UPDATE empleados SET sueldo = @sueldo WHERE nemp= @nemp END ELSE BEGIN print('el empleado no exista') INSERT INTO empleados (nemp, sueldo) VALUES (@nemp, @sueldo) END

Estructura condicional CASE


La estructura condicional CASE permite evaluar una expresin 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>

10
ELSE <valor_devuelto> -- Valor por defecto END

Ejemplo de CASE.
DECLARE @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.defecto.com' END) PRINT @Web

Otra sintaxis de CASE 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 END

El mismo ejemplo aplicando esta sintaxis:


DECLARE @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' END) PRINT @Web

Otro aspecto muy interesante de CASE es que permite el uso de subconsultas.


DECLARE @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' END) PRINT @Web

Bucle WHILE
El bucle WHILE se repite mientras expresion se evalue como verdadero, nico tipo de bucle de Transact.
WHILE <expresion> BEGIN ... END

11

Un ejemplo del bucle WHILE.


DECLARE @contador int SET @contador = 0 WHILE (@contador < 100) BEGIN SET @contador = @contador + 1 PRINT 'Iteracion del bucle ' + cast(@contador AS varchar) END

Podemos pasar a la siguiente iteracin del bucle utilizando CONTINUE.


DECLARE @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) END

El bucle se dejar de repetir con la instruccin BREAK.


DECLARE @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) END

Tambin podemos utilizar el bucle WHILE conjuntamente con subconsultas.


create table recibos ( nrecibo int primary key identity , total numeric(7,2) ,pendiente char(1) check (pendiente in('s','S','n','N'))) insert into recibos values (35.34, 's') insert into recibos values (344.34, 's') insert into recibos values (346.34, 's') insert into recibos values (343.34, 's') select * from recibos DECLARE @nRecibo int WHILE EXISTS (SELECT * FROM RECIBOS WHERE PENDIENTE in ('s', 'S')) -- Ojo, la subconsulta se ejecuta una vez por cada iteracion del bucle! BEGIN SET @nRecibo = (SELECT TOP 1 nRecibo FROM RECIBOS WHERE PENDIENTE in ('s', 'S') order by nRecibo asc) UPDATE RECIBOS SET PENDIENTE = 'N'

12
WHERE nRecibo = @nRecibo END

Estructura GOTO
La sentencia goto nos permite desviar el flujo de ejecucin hacia una etiqueta. Fu 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 GOTO, recomendndose el uso de TRY - CATCH para la gestin de errores.
DECLARE @divisor int, @dividendo int, @resultado int SET @dividendo = 100 SET @divisor = 0 SET @resultado = @dividendo/@divisor IF @@ERROR > 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 CATCH A partir de la versin 2005, SQL Server proporciona el control de errores a travs de las instrucciones TRY y CATCH.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 CATCH es la siguiente:
BEGIN TRY ... END TRY BEGIN CATCH ... END CATCH

El siguiente ejemplo ilustra el uso de TRY - CATCH.


BEGIN TRY DECLARE @divisor int , @dividendo int, @resultado int SET @dividendo = 100 SET @divisor = 0 -- Esta lnea provoca un error de division por 0 SET @resultado = @dividendo/@divisor PRINT 'No hay error' END TRY BEGIN CATCH PRINT 'Se ha producido un error'

13
END CATCH

Funciones especiales de Error


Las funciones especiales de error, estn disponibles nicamente en el bloque CATCH para la obtencin de informacin detallada del error. Son: ERROR_NUMBER(), devuelve el nmero de error. ERROR_SEVERITY(), devuelve la severidad del error. ERROR_STATE(), devuelve el estado del error. ERROR_PROCEDURE(), devuelve el nombre del procedimiento almacenado que ha provocado el error. ERROR_LINE(), devuelve el nmero de lnea en el que se ha producido el error. ERROR_MESSAGE(), devuelve el mensaje de error. Son extremadamente tiles para realizar una auditora de errores.
BEGIN TRY DECLARE @divisor int , @dividendo int, @resultado int SET @dividendo = 100 SET @divisor = 0 -- Esta lnea provoca un error de division por 0 SET @resultado = @dividendo/@divisor PRINT 'No hay error' END TRY BEGIN CATCH PRINT ERROR_NUMBER() PRINT ERROR_SEVERITY() PRINT ERROR_STATE() PRINT ERROR_PROCEDURE() PRINT ERROR_LINE() PRINT ERROR_MESSAGE() END 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 @@ERROR

14

En versiones anteriores a SQL Server 2005, no estaban disponibles las instrucciones TRY CATCH. 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.
DECLARE @divisor int , @dividendo int , @resultado int SET @dividendo = 100 SET @divisor = 0 -- Esta lnea provoca un error de division por 0 SET @resultado = @dividendo/@divisor IF @@ERROR = 0 BEGIN PRINT 'No hay error' END ELSE BEGIN PRINT 'Hay error' END

El uso de @@ERROR para controlar errores puede provocar multitud de problemas. Uno de los ms habituales es sin duda, incluir una nueva sentencia Transact SQL entre la lnea 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:
DECLARE @divisor int , @dividendo int , @resultado int SET @dividendo = 100 SET @divisor = 0 -- Esta lnea provoca un error de division por 0 SET @resultado = @dividendo/@divisor PRINT 'Controlando el error ...' -- Esta lnea estable @@ERROR a cero IF @@ERROR = 0 BEGIN -- Se ejecuta esta parte! PRINT 'No hay error' END ELSE BEGIN PRINT 'Hay error' END

Generar un error con RAISERROR

15

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 RAISERROR.
DECLARE @tipo int, @clasificacion int SET @tipo = 1 SET @clasificacion = 3 IF (@tipo = 1 AND @clasificacion = 3) BEGIN RAISERROR ('El tipo no puede valer uno y la clasificacion 3', 16, -- Severidad 1 -- Estado ) END

La funcin RAISERROR recibe tres parmetros, 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 25, pero solo podemos asignar valores del 0 al 18. Los errores el 20 al 25 son considerados fatales por el sistema, y cerraran la conexin que ejecuta el comando RAISERROR. Para asignar valores del 19 al 25 se necesitaria ser miembros de la funcin de SQL Server sysadmin.

Transacciones en Transact SQL Concepto de transaccin


Una 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. SQL Server funciona por defecto con Transacciones de confirmacin automtica, es decir, cada instruccin individual es una transaccin y se confirma automticamente, actuar de esta forma seria errnea, ya que cada instruccin se ejecutara y confirmara de forma independiente, por lo que un error dejara los datos errneos en la base de datos

Transacciones implcitas y explicitas


Para agrupar varias sentencias Transact SQL en una nica transaccin, disponemos de los siguientes mtodos: Transacciones explcitas.- Cada transaccin se inicia explcitamente con la instruccin BEGIN TRANSACTION y se termina explcitamente con una instruccin COMMIT o ROLLBACK. Transacciones implcitas.- Se inicia automticamente una nueva transaccin cuando se ejecuta una instruccin que realiza modificaciones en los datos, pero cada transaccin se completa explcitamente con una instruccin COMMIT o ROLLBACK. Para activar-desactivar el modo de transacciones implcitas debemos ejecutar la siguiente instruccin.

16
--Activamos el modo de transacciones implicitas SET IMPLICIT_TRANSACTIONS ON --Desactivamos el modo de transacciones implicitas SET IMPLICIT_TRANSACTIONS OFF

Cuando la opcin ANSI_DEFAULTS est establecida en ON, IMPLICIT_TRANSACTIONS tambin se establece en ON. El siguiente ejemplo muestra el script anterior haciendo uso de transacciones explicitas.

SET IMPLICIT_TRANSACTIONS ON DECLARE @importe DECIMAL(18,2), @CuentaOrigen VARCHAR(12), @CuentaDestino VARCHAR(12) /* Asignamos el importe de la transferencia * y las cuentas de origen y destino */ SET @importe = 50 SET @CuentaOrigen = '200700000002' SET @CuentaDestino = '200700000001' BEGIN TRY /* Descontamos el importe de la cuenta origen */ UPDATE CUENTAS SET SALDO = SALDO - @importe WHERE NUMCUENTA = @CuentaOrigen /* Registramos el movimiento */ INSERT INTO MOVIMIENTOS (IDCUENTA, SALDO_ANTERIOR, SALDO_POSTERIOR, IMPORTE, FXMOVIMIENTO) SELECT IDCUENTA, SALDO + @importe, SALDO, @importe, getdate() FROM CUENTAS WHERE NUMCUENTA = @CuentaOrigen /* Incrementamos el importe de la cuenta destino */ UPDATE CUENTAS SET SALDO = SALDO + @importe WHERE NUMCUENTA = @CuentaDestino /* Registramos el movimiento */ INSERT INTO MOVIMIENTOS (IDCUENTA, SALDO_ANTERIOR, SALDO_POSTERIOR, IMPORTE, FXMOVIMIENTO) SELECT IDCUENTA, SALDO - @importe, SALDO, @importe, getdate() FROM CUENTAS WHERE NUMCUENTA = @CuentaDestino /* Confirmamos la transaccion*/ COMMIT TRANSACTION -- O solo COMMIT END TRY BEGIN CATCH /* Hay un error, deshacemos los cambios*/ ROLLBACK TRANSACTION -- O solo ROLLBACK PRINT 'Se ha producido un error!' END CATCH

El siguiente ejemplo muestra el mismo script con transacciones implcitas. La transaccin sigue activa hasta que emita una instruccin COMMIT o ROLLBACK. Una vez que la primera transaccin se ha confirmado o revertido, se inicia automticamente una nueva transaccin la siguiente vez que la conexin ejecuta una instruccin para modificar datos. La conexin contina generando transacciones implcitas hasta que se desactiva el modo de transacciones implcitas.

17

Podemos verificar el nmero de transacciones activas a travs de @@TRANCOUNT.


SET IMPLICIT_TRANSACTIONS ON BEGIN TRY UPDATE CUENTAS SET FXALTA = FXALTA - 1 PRINT @@TRANCOUNT COMMIT END TRY BEGIN CATCH ROLLBACK PRINT 'Error' END CATCH

Cuando es ON, SET IMPLICIT_TRANSACTIONS establece la conexin al modo de transaccin implcita. Cuando es OFF, restablece la conexin al modo de transaccin con confirmacin automtica. Cuando una conexin est en modo de transaccin implcita y actualmente no est realizando una transaccin, la ejecucin de cualquiera de las instrucciones siguientes inicia una transaccin: ALTER TABLE FETCH REVOKE CREATE GRANT SELECT DELETE INSERT TRUNCATE TABLE DROP OPEN UPDATE Si la conexin tiene ya una transaccin abierta, estas instrucciones no inician una nueva transaccin. Al trmino de las transacciones que se abran automticamente por ser esta opcin ON, el usuario debe confirmarlas o revertirlas explcitamente. En caso contrario, las transacciones y todos los cambios que se realicen en los datos se revertirn cuando el usuario se desconecte. Una vez confirmada una transaccin, la ejecucin de alguna de las instrucciones anteriores iniciar una transaccin nueva. El modo de transaccin implcita permanecer activo hasta que la conexin ejecute una instruccin SET IMPLICIT_TRANSACTIONS OFF, que restablece el modo de confirmacin automtica en la conexin. En el modo de confirmacin automtica, todas las instrucciones individuales se confirman cuando finalizan correctamente. El proveedor OLE DB de SQL Native Client para SQL Server y el controlador ODBC de SQL Native Client establecen automticamente IMPLICIT_TRANSACTIONS en OFF al conectarse. SET IMPLICIT_TRANSACTIONS tiene el valor predeterminado OFF para conexiones con el proveedor administrado SQLClient y para solicitudes SOAP recibidas a travs de extremos HTTP. Cuando SET ANSI_DEFAULTS est establecido en ON, SET IMPLICIT_TRANSACTIONS tambin se establece en ON. La opcin SET IMPLICIT_TRANSACTIONS se establece en tiempo de ejecucin, no en tiempo de anlisis. Ejemplo Transacciones implicitas

SET NOCOUNT ON; --GO SET IMPLICIT_TRANSACTIONS ON; --GO PRINT N'Tran count at start = ' + CAST(@@TRANCOUNT AS NVARCHAR(10)); --Tran count at start = 0 GO IF OBJECT_ID(N'dbo.t1',N'U') IS NOT NULL DROP TABLE dbo.t1; GO CREATE table dbo.t1 (a int); GO INSERT INTO dbo.t1 VALUES (1); GO PRINT 'Tran count despues de create e insert = ' + CAST(@@TRANCOUNT AS NVARCHAR(10)) COMMIT PRINT 'Tran count despues de COMMIT = ' + CAST(@@TRANCOUNT AS NVARCHAR(10)) SELECT * FROM T1 INSERT INTO dbo.t1 VALUES (1); GO PRINT 'Tran count despues de 2 insert = ' + CAST(@@TRANCOUNT AS NVARCHAR(10)) ROLLBACK PRINT 'Tran count despues de ROLLBACK = ' SELECT * FROM T1

18

+ CAST(@@TRANCOUNT AS NVARCHAR(10))

Transacciones anidadas.
Podemos anidar varias transacciones. Cuando anidamos varias transacciones la instruccin COMMIT afectar a la ltima transaccin abierta, pero ROLLBACK afectar a todas las transacciones abiertas. Un hecho a tener en cuenta, es que, si hacemos ROLLBACK de la transaccin superior se desharn tambin los cambios de todas las transacciones internas, aunque hayamos realizado COMMIT de ellas.

BEGIN TRAN UPDATE EMPLEADOS SET NOMBRE = 'Devjoker' WHERE ID=101 BEGIN TRAN UPDATE EMPLEADOS SET APELLIDO1 = 'Devjoker.COM' WHERE ID=101 -- Este COMMIT solo afecta a la segunda transaccion. COMMIT -- Este ROLLBACK afecta a las dos transacciones. ROLLBACK

Una consideracin a tener en cuanta cuando trabajamos con transacciones anidadas es la posibilidad de utilizar puntos de guardado o SAVEPOINTs.

19

Puntos de recuperacin (SavePoint).

20

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.
BEGIN TRAN UPDATE EMPLEADOS SET NOMBRE = 'Devjoker' WHERE ID=101 UPDATE EMPLEADOS SET APELLIDO1 = 'Devjoker.COM' WHERE ID=101 SAVE TRANSACTION P1 -- Guardamos la transaccion (Savepoint) UPDATE EMPLEADOS SET APELLIDO1 = 'Otra cosa!' WHERE ID=101 -- Este ROLLBACK afecta solo a las instrucciones posteriores al savepoint P1. ROLLBACK TRANSACTION P1 -- Confirmamos la transaccion COMMIT select * from recibos begin transaction insert into recibos values( 60, 's') --insecion 1 SAVE TRANSACTION P1 insert into recibos values( 70, 's')--insercion 2 rollback transaction p1 -- deshace la insercion 2 rollback --deshace la insecin 1 y 2

Un usuario puede establecer un punto de almacenamiento, o marcador, dentro de una transaccin. El punto de almacenamiento define una ubicacin a la que la transaccin puede volver si se cancela parte de la transaccin de forma condicional. Si se revierte una transaccin hasta un punto de almacenamiento, se debe continuar hasta su finalizacin con ms instrucciones Transact-SQL si es necesario y una instruccin COMMIT TRANSACTION o se debe cancelar completamente al revertir la transaccin hasta su inicio. Para cancelar una transaccin completa, utilice el formato ROLLBACK TRANSACTION transaction_name. Se deshacen todas las instrucciones o procedimientos de la transaccin. En una transaccin se permiten nombres de puntos de almacenamiento duplicados, pero una instruccin ROLLBACK TRANSACTION que especifique el nombre de un punto de

almacenamiento slo revertir la transaccin hasta la instruccin SAVE TRANSACTION ms reciente que tambin utilice ese nombre.

21

22

No se admite SAVE TRANSACTION en transacciones distribuidas iniciadas explcitamente con BEGIN DISTRIBUTED TRANSACTION u originadas a partir de una transaccin local. Importante: Cuando una transaccin comienza, los recursos utilizados durante la transaccin se mantienen hasta la finalizacin de la misma (es decir, los bloqueos). Cuando se revierte parte de una transaccin hasta un punto de almacenamiento, se mantienen los recursos hasta la finalizacin de la transaccin o hasta revertir la transaccin completa. savepoint_name Es el nombre asignado al punto de almacenamiento. Los nombres de los puntos de almacenamiento deben ajustarse a las reglas para los identificadores, aunque estn limitados a 32 caracteres. @savepoint_variable Es el nombre de una variable definida por el usuario que contiene un nombre de punto de almacenamiento vlido. La variable debe declararse con un tipo de datos char, varchar, nchar o nvarchar. Es posible pasar ms de 32 caracteres a la variable, aunque slo se utilizarn los primeros 32.

Argumentos

Procedimientos almacenados en Transact SQL

23

Un procedimiento es un programa dentro de la base de datos que ejecuta una accin o conjunto de acciones especficas. Un procedimiento tiene un nombre, un conjunto de parmetros (opcional) y un bloque de cdigo. En Transact SQL los procedimientos almacenados pueden devolver valores (numrico entero) o conjuntos de resultados. Para crear un procedimiento almacenado debemos emplear la sentencia CREATE PROCEDURE.
CREATE PROCEDURE <nombre_procedure> [@param1 <tipo>, ...] AS -- Sentencias del procedure

Para modificar un procedimiento almacenado debemos emplear la sentencia ALTER PROCEDURE.


ALTER PROCEDURE <nombre_procedure> [@param1 <tipo>, ...] AS -- Sentencias del procedure

insertaEmpleado

El siguiente ejemplo muestra un procedimiento almacenado, denominado que inserta un registro en la tabla "empleados".

CREATE PROCEDURE insertaEmpleado @nemp int, @nombre varchar(10), @apellido varchar(10), @sueldo numeric(6,2), @ventas numeric(6,2)= 0, @fechaAlta datetime, @nDep int AS BEGIN INSERT INTO empleados (nEmp,nombre, apellido, fe_alta, sueldo, ventas, ndep) VALUES (@nemp,@nombre, @apellido, @fechaAlta,@sueldo, @ventas, @nDep) END

Para la ejecutar un procedimiento almacenado debemos utilizar la sentencia EXEC. Cuando la ejecucin del procedimiento almacenado es la primera instruccin del lote, podemos omitir el uso de EXEC. El siguiente ejemplo muestra la ejecucin del procedimiento almacenado anterior.
DECLARE @fechaAlta datetime set @fechaAlta = convert(datetime, '04/05/2010', 103) EXEC insertaEmpleado 40,'Pedro', 'Herrarte', 1200.00, 2340, @fechaAlta, 1

Siempre es deseable que las instrucciones del procedimiento estn dentro de un bloque TRY CATCH y controlados por una transaccin.
ALTER PROCEDURE insertaEmpleado @nemp int, @nombre varchar(10), @apellido varchar(10), @sueldo numeric(6,2), @ventas numeric(6,2)= 0, @fechaAlta datetime, @nDep int AS BEGIN

24
BEGIN TRY BEGIN TRAN INSERT INTO empleados (nEmp,nombre, apellido, fe_alta, sueldo, ventas, ndep) VALUES (@nemp,@nombre, @apellido, @fechaAlta,@sueldo, @ventas, @nDep) COMMIT END TRY BEGIN CATCH ROLLBACK PRINT ERROR_MESSAGE() END CATCH END

DECLARE @fechaAlta datetime set @fechaAlta = convert(datetime, '04/05/2010', 103) EXEC insertaEmpleado 40,'Pedro', 'Herrarte', 1200.00, 2340, @fechaAlta, 1

Si queremos que los parmetros de un procedimiento almacenado sean de entrada-salida debemos especificarlo a travs de la palabra clave OUTPUT , tanto en la definicin del procedimiento como en la ejecucin. El siguiente ejemplo muestra la definicin de un procedimiento con parmetros de salida.
CREATE PROCEDURE spu_ObtenerSaldoCuenta @numCuenta varchar(20), @saldo decimal(10,2) output AS BEGIN SELECT @saldo = SALDO FROM CUENTAS WHERE NUMCUENTA = @numCuenta END

Y para ejecutar este procedimiento:


DECLARE @saldo decimal(10,2) EXEC spu_ObtenerSaldoCuenta '200700000001', @saldo output PRINT @saldo

Un procedimiento almacenado puede devolver valores numricos enteros a travs de la instruccin RETURN. 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 parmetros de salida o funciones escalares (se vern mas adelante en este tutorial). El siguiente ejemplo muestra un procedimiento almacenado que devuelve valores.
CREATE PROCEDURE spu_EstaEnNumerosRojos @numCuenta varchar(20) AS BEGIN IF (SELECT SALDO FROM CUENTAS WHERE NUMCUENTA = @numCuenta) < 0 BEGIN RETURN 1 END ELSE RETURN 0 END

El siguiente ejemplo muestra como ejecutar el procedimiento y obtener el valor devuelto.


DECLARE @rv int EXEC @rv = spu_EstaEnNumerosRojos '200700000001' PRINT @rv

25

Otra caracterstica 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.
CREATE PROCEDURE spu_MovimientosCuenta @numCuenta varchar(20) AS BEGIN SELECT @numCuenta, SALDO_ANTERIOR, SALDO_POSTERIOR, IMPORTE, FXMOVIMIENTO FROM MOVIMIENTOS INNER JOIN CUENTAS ON MOVIMIENTOS.IDCUENTA = CUENTAS.IDCUENTA WHERE NUMCUENTA = @numCuenta ORDER BY FXMOVIMIENTO DESC END

La ejecucin del procedimiento se realiza normalmente.


EXEC spu_MovimientosCuenta '200700000001'

El resultado de la ejecucion ...


NUMCUENTA SALDO_ANTERIOR SALDO_POSTERIOR IMPORTE FXMOVIMIENTO ------------ -------------- ---------------- ------- ----------------------200700000001 50.99 100.99 50.00 2007-08-25 16:18:36.490 200700000001 0.99 50.99 50.00 2007-08-23 16:20:41.183 200700000001 50.99 0.99 50.00 2007-08-23 16:16:29.840 200700000001 0.99 50.99 50.00 2007-08-23 16:14:05.900

Funciones en Transact SQL


SQL Server proporciona al usuario la posibilidad de definir sus propias funciones, conocidas como UDF (user defined functions). Existen tres tipos de funciones. Estas son: Funciones escalares. Funciones en lnea. Funciones en lnea de mltiples sentencias

Funciones escalares

26

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: CREATE FUNCTION <FunctionName> ( -- Lista de parmetros <@Param1, @p1> <Data_Type_For_Param1, , int>, ... ) -- Tipo de datos que devuelve la funcin. RETURNS <Function_Data_Type, ,int> AS BEGIN ... END

El siguiente ejemplo muestra como crear una funcin escalar.


CREATE FUNCTION fn_MultiplicaSaldo ( @NumCuenta VARCHAR(20), @Multiplicador DECIMAL(10,2) ) RETURNS DECIMAL(10,2) AS BEGIN DECLARE @Saldo DECIMAL(10,2), @Return DECIMAL(10,2) SELECT @Saldo = SALDO FROM CUENTAS WHERE NUMCUENTA = @NumCuenta SET @Return = @Saldo * @Multiplicador RETURN @Return END

Pueden ser utilizadas en cualquier sentencia Transact SQL. Un 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. Un aspecto muy a tener en cuenta es que la funcin ejecutar sus sentencias SELECT una vez por cada fila del conjunto de resultados devuelto por la consulta SELECT principal.
SELECT IDCUENTA, NUMCUENTA, SALDO, FXALTA, -- Ejecucin de la funcin: dbo.fn_MultiplicaSaldo( NUMCUENTA, IDCUENTA) AS RESULTADO FROM CUENTAS

El siguiente ejemplo muestra como utilizar una funcin escalar en un script Transact SQL.
DECLARE @NumCuenta VARCHAR(20), @Resultado DECIMAL(10,2) SET @NumCuenta = '200700000001' SET @Resultado = dbo.fn_MultiplicaSaldo(@NumCuenta, 30.5)

27
PRINT @Resultado

Las funciones escalares son muy similares a procedimientos almacenados con parmetros de salida, pero estas pueden ser utilizadas en consultas de seleccin y en la clusula where de las mismas. Las funciones no pueden ejecutar sentencias INSERT o UPDATE.

Funciones en lnea
Las funciones en lnea son las funciones que devuelven un conjunto de resultados correspondientes a la ejecucin de una sentencia SELECT. La sintaxis para una funcin de tabla en lnea es la siguiente:
CREATE FUNCTION <Inline_Function_Name, sysname, FunctionName> ( -- Lista de parmetros <@param1, sysname, @p1> <Data_Type_For_Param1, , int>,... ) RETURNS TABLE AS RETURN ( -- Sentencia Transact SQL )

28

El siguiente ejemplo muestra como crear una funcin en lnea.


CREATE FUNCTION fn_MovimientosCuenta ( @NumCuenta VARCHAR(20) ) RETURNS TABLE AS RETURN ( SELECT MOVIMIENTOS.* FROM MOVIMIENTOS INNER JOIN CUENTAS ON MOVIMIENTOS.IDCUENTA = CUENTAS.IDCUENTA WHERE CUENTAS.NUMCUENTA = @NumCuenta )

No podemos utilizar la clusula ORDER BY en la sentencia de una funcin el lnea. Las funciones en lnea pueden utilizarse dentro de joins o querys como si fueran una tabla normal.
SELECT * FROM fn_MovimientosCuenta('200700000001') SELECT * FROM CUENTAS INNER JOIN CUENTAS_CLIENTE ON CUENTAS_CLIENTE.IDCUENTA = CUENTAS.IDCUENTA INNER JOIN CLIENTES ON CLIENTES.id = CUENTAS_CLIENTE.IDCLIENTE INNER JOIN fn_MovimientosCuenta('200700000001') A ON A.IDCUENTA= CUENTAS.IDCUENTA

Funciones en lnea de mltiples sentencias


Las funciones en lnea de mltiples sentencias son similares a las funciones en lnea excepto que el conjunto de resultados que devuelven puede estar compuesto por la ejecucin de varias consultas SELECT. Este tipo de funcin se usa en situaciones donde se requiere una mayor lgica de proceso. La sintaxis para una funcin de tabla de multisentencias es la siguiente:
CREATE FUNCTION <Table_Function_Name, sysname, FunctionName> ( -- Lista de parmetros <@param1, sysname, @p1> <data_type_for_param1, , int>, ... )

29
RETURNS -- variable de tipo tabla y su estructura <@Table_Variable_Name, sysname, @Table_Var> TABLE ( <Column_1, sysname, c1> <Data_Type_For_Column1, , int>, <Column_2, sysname, c2> <Data_Type_For_Column2, , int> ) AS BEGIN -- Sentencias que cargan de datos la tabla declarada RETURN END

El siguiente ejemplo muestra el uso de una funcin de tabla de multisentencias.


/* Esta funcion busca la tres cuentas con mayor saldo * y obtiene los tres ltimos movimientos de cada una * de estas cuentas */ CREATE FUNCTION fn_CuentaMovimietos() RETURNS @datos TABLE ( -- 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), Importe_Movimiento decimal(10,2), FxMovimiento datetime ) AS BEGIN -- Variables necesarias para la lgica de la funcion. DECLARE @idcuenta int, @numcuenta varchar(20), @saldo decimal(10,2) -- Cursor con las 3 cuentas de mayor saldo DECLARE CDATOS CURSOR FOR SELECT TOP 3 IDCUENTA, NUMCUENTA, SALDO FROM CUENTAS ORDER BY SALDO DESC OPEN CDATOS FETCH CDATOS INTO @idcuenta, @numcuenta, @saldo -- Recorremos el cursor WHILE (@@FETCH_STATUS = 0) BEGIN -- Insertamos la cuenta en la variable de salida INSERT INTO @datos (NumCuenta, Saldo) VALUES (@numcuenta, @saldo) -- Insertamos los tres ltimos movimientos de la cuenta INSERT INTO @datos (Saldo_anterior, Saldo_posterior, Importe_Movimiento, FxMovimiento ) SELECT TOP 3 SALDO_ANTERIOR, SALDO_POSTERIOR, IMPORTE, FXMOVIMIENTO FROM MOVIMIENTOS WHERE IDCUENTA = @idcuenta

30
ORDER BY FXMOVIMIENTO DESC -- Vamos a la siguiente cuenta FETCH CDATOS INTO @idcuenta, @numcuenta, @saldo END CLOSE CDATOS; DEALLOCATE CDATOS; RETURN END

Para ejecutar la funcin:


select * from fn_CuentaMovimietos()

Y el resultado obtenido ...


NumCuenta Saldo Saldo_anterior Saldo_posterior Importe_Movimiento FxMovimiento ------------ ------ --------------- ---------------- ------------------- ----------------------200700000002 500.00 NULL NULL NULL NULL NULL NULL 550.00 500.00 50.00 2007-08-25 16:18:36.490 NULL NULL 600.00 550.00 50.00 2007-08-23 16:20:41.183 NULL NULL 600.00 550.00 50.00 2007-08-23 16:14:05.900 200700000001 100.99 NULL NULL NULL NULL NULL NULL 50.99 100.99 50.00 2007-08-25 16:18:36.490 NULL NULL 0.99 50.99 50.00 2007-08-23 16:20:41.183 NULL NULL 50.99 0.99 50.00 2007-08-23 16:16:29.840

Funciones integradas de Transact SQL (I)


SQL Server pone a nuestra disposicin multitud de funciones predefinidas que proporcionan un amplio abanico de posibilidades. Mostramos aqu algunas de las frecuentes. Podemos acceder al listado completo a travs del siguiente enlace: http://technet.microsoft.com/eses/library/ms187786.aspx

Cast y Convert
Convierten una expresin de un tipo de datos en otro de forma explcita. CAST y CONVERT proporcionan funciones similares. CONVERT ( data_type [ ( length ) ] , expression [ , style ] ) Donde: data_type, es el tipo de destino al que queremos convertir la expresin expresin, la expresin que queremos convertir style, parmetro opcional que especifica el formato que tiene expresin. Por ejemplo, si queremos convertir un varchar a datetime, aqu 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 => dd/mm/aa SET @fecha = CONVERT(datetime, '19/03/2008',103) SELECT @fecha DECLARE @fecha datetime, @fechaFormateada varchar(20) -- Convertimos ahora una fecha a varchar y la formateamos -- 3 => dd/mm/aa SET @fecha = GETDATE() SET @fechaFormateada = CONVERT(varchar(20), @fecha, 3) SELECT @fechaFormateada -- Un ejemplo utilizando CAST DECLARE @dato varchar(2),

31
@dato2 int SET @dato = '27' SET @dato2 = cast(@dato AS int) SELECT @dato2

A continuacin mostramos la tabla de cdigos MicroSoft). Sin el Con el siglo (aa) siglo ? Estndar 1 ( ) (aaaa) 0 o 100 (1, Valor predeterminado 2 ) 1 101 EE.UU. 2 102 ANSI 3 103 Britnico/Francs 4 104 Alemn 5 105 Italiano (1) 6 106 (1) 7 107 8 108 10 11 12 14 -

de estilo (obtenida de Entrada/salida (3)

mes dd aaaa hh:mia.m. (o p. m.) mm/dd/aaaa aa.mm.dd dd/mm/aa dd.mm.aa dd-mm-aa dd mes aa Mes dd, aa hh:mi:ss mes dd aaaa 9 o 109 (1, Valor predeterminado + hh:mi:ss:mmma.m. (o p. 2 ) milisegundos m.) 110 EE.UU. mm-dd-aa 111 JAPN aa/mm/dd 112 ISO aammdd Europeo 13 o 113 (1, dd mes aaaa predeterminado + 2 ) hh:mi:ss:mmm(24h) milisegundos 114 hh:mi:ss:mmm(24h) aaaa-mm-dd 20 o 120 (2) ODBC cannico hh:mi:ss(24h) ODBC cannico (con aaaa-mm-dd 21 o 121 (2) milisegundos) hh:mi:ss.mmm(24h) aaaa-mm126 (4) ISO8601 ddThh:mi:ss.mmm (sin espacios) aaaa-mmISO8601 con zona 127(6, 7) ddThh:mi:ss.mmmZ horaria Z. (sin espacios) dd mes aaaa 130 (1, 2) Hijri (5) hh:mi:ss:mmma.m. dd/mm/aa 131 (2) Hijri (5) hh:mi:ss:mmma.m.

Isnull
Evala una expresin de entrado y si esta es NULL, reemplaza NULL con el valor de reemplazo especificado. El valor de reemplazo debe ser del mismo tipo de datos que la expresin a evaluar. ISNULL ( expression , replacement_value )
DECLARE @datoInt int,

32
@datoVarchar varchar(100) SET @datoInt = NULL SET @datoVarchar = NULL SELECT ISNULL(@dato, -1), ISNULL(@datoVarchar, 'No hay dato')

COALESCE
Devuelve la primera expresin distinta de NULL entre sus argumentos. Un aspecto a tener en cuenta es que todos los argumentos deben ser del mismo tipo. COALESCE ( expression [ ,...n ] )
DECLARE @dato1 int, @dato2 int, @dato3 int, @dato4 int, @dato5 int SET SET SET SET SET @dato1 @dato2 @dato3 @dato4 @dato5 = = = = = null NULL NULL 100 125

-- Devuelve 100 SELECT COALESCE(@dato1,@dato2,@dato3,@dato4,@dato5)

GetDate y GetUTCDate
GetDate devuelve la fecha y hora actuales del sistema en el formato interno estndar de SQL Server 2005 para los valores datetime. GetUTCDate devuelve el valor datetime que representa la hora UTC (hora universal coordinada u hora del meridiano de Greenwich) actual.
DECLARE @fechaLocal datetime, @fechaUTC datetime SET @fechaLocal = getdate() SET @fechaUTC = GETUTCDATE() SELECT @fechaLocal, @fechaUTC

SQL dinmico en Transact SQL


Transact SQL permite dos formas de ejecutar SQL dinmico (construir sentencias SQL dinmicamente para ejecutarlas en la base de datos): La instruccin EXECUTE - o simplemente EXEC El procedimiento almacenado sp_executesql Desde aqu recomendamos la utilizacin de sp_executesql si bien vamos a mostrar la forma de trabajar con ambos mtodos.

La instruccin EXECUTE
La instruccin EXECUTE - o simplemente EXEC - permite ejecutar una cadena de caracteres que representa una sentencia SQL. La cadena de caracteres debe ser de tipo nvarchar . El siguiente ejemplo muestra como ejecutar una cadena de caracteres con la instruccin EXEC.

33
DECLARE @sql nvarchar(1000) SET @sql = 'SELECT COD_PAIS, NOMBRE_PAIS, ACTIVO, FX_ALTA FROM PAISES' EXEC (@sql)

Tambin con SQL dinmico podemos ejecutar sentencias de tipo DDL (Data Definition Languaje), como CREATE TABLE.
DECLARE @sql nvarchar(1000) SET @sql='CREATE TABLE TEMPORAL ( ID int IDENTITY, DATO varchar(100))' EXEC (@sql) SET @sql = 'SELECT * FROM TEMPORAL' EXEC (@sql)

El principal inconveniente de trabajar con la instruccin EXEC es que no permite el uso de parmetros abriendo la puerta a potenciales ataques de Sql Injections - http://www.devjoker.com/contenidos/Articulos/45/Seguridaden-Internet--SQL-Injections.aspx Adems el uso de la instruccin EXEC es menos eficiente, en trminos de rendimiento, que sp_executesql. Para solventar el problema debemos trabajar siempre con sq_executesql, que permite el uso de parmetros y con el que obtendremos un mejor rendimiento de nuestras consultas.

El procedimiento almacenado sp_executesql


Para ejecutar sql dinmico, se recomienda utilizar el procedimiento almacenado sp_executesql, en lugar de una instruccin EXECUTE. sp_executesql admite la sustitucin de parmetros sp_executesql es ms seguro y verstil que EXECUTE sp_executesql genera planes de ejecucin con ms probabilidades de que SQL Server los vuelva a utilizar, es ms eficaz que EXECUTE. El siguiente ejemplo muestra el uso (muy simple) de sp_executesql.
DECLARE @sql nvarchar(1000) SET @sql = 'SELECT COD_PAIS, NOMBRE_PAIS, ACTIVO, FX_ALTA FROM PAISES' EXEC sp_executesql @sql

sp_executesql admite la sustitucin de valores de parmetros para cualquier parmetro especificado en la cadena Transact-SQL a ejecutar. El siguiente ejemplo muestra el uso de sp_executesql con parmetros:
DECLARE @sql nvarchar(1000), @paramDefinition nvarchar(255), @paramValue char(3) SET @paramDefinition = '@codPais char(3)'

34
SET @paramValue = 'ESP' SET @sql = 'SELECT COD_PAIS, NOMBRE_PAIS, ACTIVO, FX_ALTA FROM PAISES WHERE COD_PAIS = @codPais' EXEC sp_executesql @sql, @paramDefinition, @paramValue DECLARE @sql nvarchar(1000), @paramDefinition nvarchar(255), @paramValue int SET @paramDefinition = '@ndep int' SET @paramValue = 1 SET @sql = 'SELECT * FROM empleados PAISES WHERE ndep = @ndep' EXEC sp_executesql @sql, @paramDefinition, @paramValue

Para ejecutar una cadena, se recomienda utilizar el procedimiento almacenado sp_executesql, en lugar de una instruccin EXECUTE. Puesto que este procedimiento almacenado admite la sustitucin de parmetros, sp_executesql es ms verstil que EXECUTE; y como sp_executesql genera planes de ejecucin con ms probabilidades de que SQL Server 2005 los vuelva a utilizar, es ms eficaz que EXECUTE. Lotes independientes Cuando sp_executesql o la instruccin EXECUTE ejecutan una cadena, sta se ejecuta como su propio lote independiente. SQL Server compila la instruccin o instrucciones Transact-SQL de la cadena en un plan de ejecucin independiente del plan de ejecucin del lote que contena sp_executesql o la instruccin EXECUTE. Para los lotes independientes se aplican las siguientes reglas: Las instrucciones Transact-SQL de la cadena EXECUTE o sp_executesql no se compilan en un plan de ejecucin hasta que la instruccin EXECUTE o sp_executesql se han ejecutado. Las cadenas no se analizan ni se comprueba que tengan errores hasta que se han ejecutado. Los nombres a los que se hace referencia en las cadenas no se resuelven hasta que se han ejecutado. Las instrucciones Transact-SQL de la cadena ejecutada no tienen acceso a ninguna de las variables declaradas en el lote que contiene la instruccin EXECUTE o sp_executesql. El lote que contiene la instruccin EXECUTE o sp_executesql no tiene acceso a las variables o cursores locales definidos en la cadena ejecutada. Si la cadena ejecutada contiene una instruccin USE que cambia el contexto de la base de datos, este cambio slo dura hasta que finaliza la ejecucin de sp_executesql o la instruccin EXECUTE. La ejecucin de los dos lotes siguientes muestra estos puntos:

Copiar
/*Show not having access to variables from the calling batch. */ DECLARE @CharVariable CHAR(3); SET @CharVariable = 'abc'; /* sp_executesql fails because @CharVariable has gone out of scope. */ EXECUTE sp_executesql N'PRINT @CharVariable'; GO /* Show database context resetting after sp_executesql finishes. */ USE master; GO EXECUTE sp_executesql N'USE AdventureWorks;' GO /* This statement fails because the database context has now returned to master. */ SELECT * FROM Sales.Store; GO

35

Sustituir valores de parmetros sp_executesql admite la sustitucin de valores de parmetros para cualquier parmetro especificado en la cadena Transact-SQL, pero la instruccin EXECUTE no lo hace. Por tanto, las cadenas Transact-SQL generadas por sp_executesql son ms similares que las generadas por la instruccin EXECUTE. El optimizador de consultas de SQL Server probablemente compare las instrucciones Transact-SQL de sp_executesql con los planes de ejecucin de las instrucciones ejecutadas previamente, lo que ahorra la sobrecarga de trabajo que supone compilar un nuevo plan de ejecucin. En la instruccin EXECUTE, todos los valores de los parmetros se deben convertir a caracteres o datos Unicode y formar parte de la cadena TransactSQL. Si la instruccin se ejecuta varias veces, debe generarse una cadena Transact-SQL completamente nueva para cada ejecucin, incluso cuando las nicas diferencias se encuentren en los valores suministrados para los parmetros. Esto genera una sobrecarga adicional de las formas siguientes: La capacidad del optimizador de consultas de SQL Server para comparar la nueva cadena Transact-SQL con un plan de ejecucin existente est obstaculizada por el cambio constante de los valores de los parmetros del texto de la cadena, especialmente en las instrucciones Transact-SQL complejas. La cadena completa se debe volver a generar en cada ejecucin. Los valores de los parmetros (que no sean de caracteres ni Unicode) se deben convertir a un formato de caracteres o Unicode en cada ejecucin. sp_executesql admite que se establezcan valores en los parmetros, independientemente de la cadena Transact-SQL: Copiar
DECLARE @IntVariable INT; DECLARE @SQLString NVARCHAR(500); DECLARE @ParmDefinition NVARCHAR(500); /* Build the SQL string one time. */ SET @SQLString = N'SELECT * FROM AdventureWorks.Sales.Store WHERE SalesPersonID = @SalesID'; /* Specify the parameter format one time. */ SET @ParmDefinition = N'@SalesID int'; /* Execute the string with the first parameter value. */ SET @IntVariable = 275;

EXECUTE sp_executesql @SQLString, @ParmDefinition, @SalesID = @IntVariable; /* Execute the same string with the second parameter value. */ SET @IntVariable = 276; EXECUTE sp_executesql @SQLString, @ParmDefinition, @SalesID = @IntVariable;

36

sp_executesql ofrece las siguientes ventajas adicionales: Como el texto real de la instruccin Transact-SQL no cambia entre una ejecucin y otra, el optimizador de consultas debe comparar la instruccin Transact-SQL de la segunda ejecucin con el plan de ejecucin generado para la primera instruccin. De este modo, SQL Server no tiene que compilar la segunda instruccin. La cadena Transact-SQL slo se genera una vez. El archivo de datos tiene formato nativo. No es necesaria la conversin a Unicode. Nota: Los nombres de objeto de la cadena de instrucciones deben aparecer completos para que SQL Server pueda volver a utilizar el plan de ejecucin. Volver a utilizar planes de ejecucin En las versiones anteriores de SQL Server, la nica forma de volver a utilizar los planes de ejecucin era definir las instrucciones Transact-SQL como un procedimiento almacenado y hacer que la aplicacin lo ejecutara. Esto genera una sobrecarga administrativa adicional para las aplicaciones. La utilizacin de sp_executesql puede contribuir a reducir esta sobrecarga, al tiempo que permite que SQL Server vuelva a utilizar planes de ejecucin. Se puede utilizar sp_executesql en lugar de los procedimientos almacenados cuando se ejecute una instruccin Transact-SQL varias veces y la nica variacin la constituyan los valores de los parmetros suministrados a la instruccin Transact-SQL. Al permanecer constantes las instrucciones Transact-SQL y variar slo los valores de los parmetros, es probable que el optimizador de consultas de SQL Server vuelva a utilizar el plan de ejecucin que genera para la primera ejecucin. En el siguiente ejemplo se genera y ejecuta una instruccin DBCC CHECKDB para cada base de datos de un servidor, excepto para las cuatro bases de datos del sistema. Copiar
USE master; GO SET NOCOUNT ON; GO DECLARE AllDatabases CURSOR FOR SELECT name FROM sys.databases WHERE database_id > 4 OPEN AllDatabases DECLARE @DBNameVar NVARCHAR(128) DECLARE @Statement NVARCHAR(300) FETCH NEXT FROM AllDatabases INTO @DBNameVar WHILE (@@FETCH_STATUS = 0) BEGIN PRINT N'CHECKING DATABASE ' + @DBNameVar SET @Statement = N'USE ' + @DBNameVar + CHAR(13) + N'DBCC CHECKDB (' + @DBNameVar + N')' + N'WITH PHYSICAL_ONLY' EXEC sp_executesql @Statement PRINT CHAR(13) + CHAR(13) FETCH NEXT FROM AllDatabases INTO @DBNameVar

END CLOSE AllDatabases DEALLOCATE AllDatabases GO SET NOCOUNT OFF; GO

37

El controlador ODBC de SQL Server utiliza sp_executesql para implementar SQLExecDirect cuando la instruccin Transact-SQL que se est ejecutando contiene marcadores de parmetros enlazados. Esto permite ampliar las ventajas proporcionadas por sp_executesql a todas las aplicaciones que utilicen ODBC o API definidas sobre ODBC, como RDO. Las aplicaciones existentes de ODBC que se transfieren a SQL Server 2005 aumentan automticamente su rendimiento sin que tengan que ser escritas de nuevo. La nica excepcin es que sp_executesql no se usa con parmetros de datos de la ejecucin. Para obtener ms informacin, vea Using Statement Parameters. El proveedor ODBC de SQL Native Client tambin utiliza sp_executesql para implementar la ejecucin directa de instrucciones con parmetros enlazados. Las aplicaciones que usan OLE DB o ADO aprovechan las ventajas proporcionadas por sp_executesql sin que se tengan que escribir de nuevo.

Apndices.
Equivalencia de datos de SQL Server y .NET
La siguiente lista muestra los tipos de datos de SQL Server 2005 y sus equivalentes con CRL, para el namespace System.Data.SqlTypes y los tipos nativos de CRL .NET FrameWork CLR data type SQL Server CLR data type (SQL Server) (.NET Framework) varbinary SqlBytes, SqlBinary Byte[] binary SqlBytes, SqlBinary Byte[] varbinary(1), SqlBytes, SqlBinary byte, Byte[] binary(1) image ninguno ninguno varchar ninguno ninguno char ninguno ninguno nvarchar(1), Char, String, SqlChars, SqlString nchar(1) Char[] SqlChars, SqlString SQLChars es mejor para la nvarchar transferencia de datos y SQLString String, Char[] obtiene mejor rendimiento para operaciones con Strings.

38 nchar SqlChars, SqlString text ninguno ntext ninguno uniqueidenti SqlGuid fier rowversion ninguno bit SqlBoolean tinyint SqlByte smallint SqlInt16 int SqlInt32 bigint SqlInt64 smallmoney SqlMoney money SqlMoney numeric SqlDecimal decimal SqlDecimal real SqlSingle float SqlDouble smalldatetim SqlDateTime e datetime SqlDateTime sql_variant ninguno User-defined ninguno type(UDT) table cursor timestamp xml ninguno ninguno ninguno SqlXml String, Char[] ninguno ninguno Guid Byte[] Boolean Byte Int16 Int32 Int64 Decimal Decimal Decimal Decimal Single Double DateTime DateTime Object Misma clase que la definida en el assemblie. ninguno ninguno ninguno ninguno

También podría gustarte