Está en la página 1de 73

!

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

DCLR @nombre vRCHR(100),
@apellido1 vRCHR(100),
@apellido2 vRCHR(100)

SLCT @nombre=nombre ,
@apellido1=Apellido1,
@apellido2=Apellido2
RON CL!ENTES
HR !D = 1

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.

DCLR @nombre vRCHR(100),
@apellido1 vRCHR(100),
@apellido2 vRCHR(100)

DCLR CDATOS CURSOR
OR
SLCT nombre , Apellido1, Apellido2
RON CL!ENTES

OP! CDATOS
TCH CDATOS !!TO @nombre, @apellido1, @apellido2

H!L (@@ETCH_STATS = 0)
BC!!
PR!!T @nombre
PR!!T @apellido1
PR!!T @apellido2
TCH CDATOS !!TO @nombre, @apellido1, @apellido2
!D

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.

!!SRT !!TO PREC!OS
(PREC!O,
X_!N!C!O,
X_!N,
CO_PRODCTO)
SLCT PREC!O_N!DAD,
getdate(),
getdate() 30,
CO_PRODCTO
RON DETALLE_PED!DO

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

DCLR @Codigo int

!!SRT !!TO PREC!OS
(PREC!O, X_!N!C!O, X_!N, CO_PRODCTO)
vLUS
(10, getdate(),getdate()30, 1)

set @Codigo = @@!dentity

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.

DCLR @Codigo int

!!SRT !!TO PREC!OS
(PREC!O, X_!N!C!O, X_!N, CO_PRODCTO)
vLUS
(10, getdate(),getdate()30, 1)

ST @Codigo = SCOPE_!DENT!TY()
PR!!T @Codigo

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.

DCLR @!LAS_!NSERTADAS TBL
( CO_PREC!O int,
PREC!O decimal,
X_!N!C!O datetime,
X_!N datetime,
CO_PRODCTO int
)

!!SRT !!TO PREC!OS
(PREC!O, X_!N!C!O, X_!N, CO_PRODCTO)
OUTPUT !NSERTED. !!TO @!LAS_!NSERTADAS
vLUS
(10, getdate(),getdate()+30, 1)

SLCT * RON @!LAS_!NSERTADAS

ctualizar datos en Transact SQL


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.

DCLR @!LAS_ACTAL!ZADAS TBL
( CO_CL!ENTE int ,
NONBRE varchar(100),
APELL!DO1 varchar(100),
APELL!DO2 varchar(100)
)

UPDT CL!ENTES
ST
NONBRE = 'Devjoker',
APELL!DO1 = 'Herrarte',
APELL!DO2 = 'Sanchez'
OUTPUT DLTD. !!TO @!LAS_ACTAL!ZADAS
HR CO_CL!ENTE !N (10, 11, 12)

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.

DCLR @!LAS_ACTAL!ZADAS TBL
( CO_CL!ENTE int ,
NONBRE varchar(100),
APELL!DO1 varchar(100),
APELL!DO2 varchar(100)
)

UPDT CL!ENTES
ST
NONBRE = 'Devjoker',
APELL!DO1 = 'Herrarte',
APELL!DO2 = 'Sanchez'
OUTPUT !!SRTD. !!TO @!LAS_ACTAL!ZADAS
HR CO_CL!ENTE !N (10, 11, 12)

SLCT RON @!LAS_ACTAL!ZADAS

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.

DECLARE @!LAS_BORRADAS TABLE
(
!d int,
dato varchar(100),
fx_alta datetime
)

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

Registramos el movimiento
!!SRT !!TO NOv!N!ENTOS
(!DCENTA, SALDO_ANTER!OR, SALDO_POSTER!OR, !NPORTE, XNOv!N!ENTO)
SLCT
!DCENTA, SALDO @importe, SALDO, @importe, getdate()
RON CENTAS
HR NNCENTA = @CuentaOrigen

!ncrementamos el importe de la cuenta destino
UPDT CENTAS
ST SALDO = SALDO @importe
HR NNCENTA = @CuentaDestino

Registramos el movimiento
!!SRT !!TO NOv!N!ENTOS
(!DCENTA, SALDO_ANTER!OR, SALDO_POSTER!OR, !NPORTE, XNOv!N!ENTO)
SLCT
!DCENTA, SALDO @importe, SALDO, @importe, getdate()
RON CENTAS
HR NNCENTA = @CuentaDestino

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.

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 = '200700000002'
ST @CuentaDestino = '200700000001'

BC!! TR!SCT!O! O solo BEC!N TRAN
BC!! TRY
Descontamos el importe de la cuenta origen
UPDT CENTAS
ST SALDO = SALDO @importe
HR NNCENTA = @CuentaOrigen

Registramos el movimiento
!!SRT !!TO NOv!N!ENTOS
(!DCENTA, SALDO_ANTER!OR, SALDO_POSTER!OR,
!NPORTE, XNOv!N!ENTO)
SLCT
!DCENTA, SALDO @importe, SALDO, @importe, getdate()
RON CENTAS
HR NNCENTA = @CuentaOrigen

!ncrementamos el importe de la cuenta destino
UPDT CENTAS
ST SALDO = SALDO @importe
HR NNCENTA = @CuentaDestino

Registramos el movimiento
!!SRT !!TO NOv!N!ENTOS
(!DCENTA, SALDO_ANTER!OR, SALDO_POSTER!OR,
!NPORTE, XNOv!N!ENTO)
SLCT
!DCENTA, SALDO @importe, SALDO, @importe, getdate()
RON CENTAS
HR NNCENTA = @CuentaDestino

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

El siguiente ejemplo muestra el mismo script con transacciones implicitas.


ST !NPL!C!T_TR!SCT!O!S O!

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 = '200700000002'
ST @CuentaDestino = '200700000001'

BC!! TRY
Descontamos el importe de la cuenta origen
UPDT CENTAS
ST SALDO = SALDO @importe
HR NNCENTA = @CuentaOrigen

Registramos el movimiento
!!SRT !!TO NOv!N!ENTOS
(!DCENTA, SALDO_ANTER!OR, SALDO_POSTER!OR,
!NPORTE, XNOv!N!ENTO)
SLCT
!DCENTA, SALDO @importe, SALDO, @importe, getdate()
RON CENTAS
HR NNCENTA = @CuentaOrigen

!ncrementamos el importe de la cuenta destino
UPDT CENTAS
ST SALDO = SALDO @importe
HR NNCENTA = @CuentaDestino

Registramos el movimiento
!!SRT !!TO NOv!N!ENTOS
(!DCENTA, SALDO_ANTER!OR, SALDO_POSTER!OR,
!NPORTE, XNOv!N!ENTO)
SLCT
!DCENTA, SALDO @importe, SALDO, @importe, getdate()
RON CENTAS
HR NNCENTA = @CuentaDestino

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

CRT PROCDUR spu_addCliente @nombre varchar(100),
@apellido1 varchar(100),
@apellido2 varchar(100),
@nifCif varchar(20),
@fxNaciento datetime
S
!!SRT !!TO CL!ENTES
(nombre, apellido1, apellido2, nifcif, fxnacimiento) vLUS
(@nombre, @apellido1, @apellido2, @nifCif, @fxNaciento)

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.

CRT PROCDUR spu_ObtenerSaldoCuenta @numCuenta varchar(20),
@saldo decimal(10,2) output
S
BC!!
SLCT @saldo = SALDO
RON CENTAS
HR NNCENTA = @numCuenta
!D

Y para ejecutar este procedure:

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.

XC spu_NovimientosCuenta '200700000001'
El resultado de la ejecucion ...
NUMCUENTA SALDO_ANTEROR SALDO_POSTEROR MPORTE FXMOVMENTO
------------ -------------- ---------------- ------- -----------------------
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

unciones en Transact SQL


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.

CRT U!CT!O! fn_NultiplicaSaldo
(
@NumCuenta vRCHR(20),
@Nultiplicador DC!NL(10,2)
)
RTUR!S DC!NL(10,2)
S
BC!!
DCLR @Saldo DC!NL(10,2),
@Return DC!NL(10,2)

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

OP! CDATOS
TCH CDATOS !!TO @idcuenta, @numcuenta, @saldo

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

CLOS CDATOS,
DLLOCT CDATOS,

RTUR!
!D
Para ejecutar la funcin:

select from fn_CuentaNovimietos()
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

unciones integradas de Transact SQL (!)


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,

2
)
Europeo predeterminado
milisegundos
dd mes aaaa hh:mi:ss:mmm(24h)
14 114 hh:mi:ss:mmm(24h)
20 o 120 (
2
) ODBC cannico aaaammdd hh:mi:ss(24h)
21 o 121 (
2
) ODBC cannico (con aaaammdd hh:mi:ss.mmm(24h)
milisegundos)
126 (
4
) !SO8601
aaaammddThh:mi:ss.mmm (sin
espacios)

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

DECLARE @dato1 int,
@dato2 int,
@dato3 int,
@dato4 int,
@datoS int

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

También podría gustarte