Está en la página 1de 10

moreplus.

es - La pagina de los Programadores

Pgina 1

Iniciar sesin

S&aacutebado 21 de Junio de 108

PORTADA

FAQ MSDN

Lunes, 7 de Abril de 2008

NOTICIAS

Procedimientos almacenados SQL Server 2005


DESCARGAS

Autora:
ARTICULOS

Maika Hernndez Analista Programadora MCTS SQL Server Introduccin Los procedimientos almacenados permiten ejecutar procedimientos parecidos a los usados en un lenguaje de programacin, pero directamente desde la base de datos, optimizando el rendimiento y la velocidad del mismo. De hecho, a la hora de hacer consultas y operaciones a una base de datos, es recomendable usar siempre procedimientos almacenados, en la medida de lo posible. Cmo creo un procedimiento almacenado?

FAQ MSDN

FORO MSDN

BUSCAR

EQUIPO

Para crear un procedimiento almacenado sobre una BBDD, el la carpeta Programacin, pulsamos botn derecho y elegimos Nuevo procedimiento almacenado.

Aparecer un plantilla formada por un CREATE PROCEDURE seguido de las variables de entrada o salida, un BEGIN a partir del cual escribiramos el cdigo correspondiente para ese procedimiento y un END GO para dar por finalizado el mismo.

http://www.moreplus.es/index.aspx?accion=articulo&id=136

21-06-2008 00:39:05

moreplus.es - La pagina de los Programadores

Pgina 2

La sentencia CREATE PROCEDURE que aparece en la plantilla del nuevo procedimiento, har que cuando terminemos de escribirlo y despus de analizarlo (el icono de la parte superior con un visto), cuando pulsemos Analizar (icono en forma de admiracin de la barra de herramientas), el nuevo procedimiento se cree. Cuando pulsemos el botn Ejecutar (icono con forma de signo de admiracin) NO se ejecuta el procedimiento en s, sino la sentencia CREATE PROCEDURE que crear el procedimiento en la base de datos. Esta sentencia slo se ejecutar una vez. A partir de entonces, si queremos hacer algn cambio en el procedimiento, usaremos la sentencia ALTER en lugar de CREATE para que stos se guarden. Para ejecutar el procedimiento almacenado en s, existen dos formas. Hacer una ejecucin parcial, o una total. Para realizar una ejecucin parcial, seleccionamos la parte del procedimiento y pulsamos Ejecutar. Para hacer una ejecucin total, pulsamos botn derecho sobre el procedimiento en el treeview y seleccionamos la opcin de ejecutar procedimiento almacenado. Si el procedimiento se ha ejecutado correctamente, devolver un 0. En caso contrario, mostrar un mensaje con la lnea de cdigo errnea que ha producido que no se haya completado el procedimiento. Nombre del procedimiento Para asignar un nombre a un procedimiento, escribimos la siguiente sentencia:

ALTER PROCEDURE [dbo].[NOMBRE_DEL_PROCEDIMIENTO]

Paso de variables de un procedimiento Las variables necesarias para el procedimiento, se declaran justo despus del nombre del mismo, antes del BEGIN con el tipo correspondiente a continuacin:

ALTER PROCEDURE [dbo].[NOMBRE_DEL_PROCEDIMIENTO] @ID_USUARIO bigint, @ID_TIPO_PERFIL int, @ID_CORREO = 0, @ID_PASSWORD output AS BEGIN

La tercera variable, significa que puede venir o no. La cuarta variable es de salida. Le pasamos una variable y podemos recuperar su valor en el programa. Declaracin de variables

http://www.moreplus.es/index.aspx?accion=articulo&id=136

21-06-2008 00:39:05

moreplus.es - La pagina de los Programadores

Pgina 3

Las variables que se vayan a usar en el procedimiento se declaran dentro del BEGIN principal del procedimiento

ALTER PROCEDURE [dbo].[NOMBRE_DEL_PROCEDIMIENTO] AS BEGIN DECLARE DECLARE DECLARE DECLARE @ID_ZONA_NEW AS BIGINT @DESC_ZONA_NEW AS VARCHAR(1000) @EXISTE_ZONA AS BIT @DATEVAR AS DATETIME

El tipo de las variables coincide con los tipos de SQL Server. Deben ser iguales los elementos de la tabla con la variable declarada. Para inicializar las variables, usamos la sentencia SET.

SET @ID_ZONA_NEW = null SET @DATEVAR = getdate()

Tambin se puede usar la sentencia SELECT.

SELECT @NOMBRE_VARIABLE =PRUEBAS

La diferencia entre ellas es que la sentencia SELECT mostrar un mensaje en el cuadro de dilogo inferior al ejecutar el procedimiento Sentencias de programacin La sentencia IF es igual a la de programacin. Cada parte se engloba en un BEGIN y en un END, de la siguiente forma:

IF @ID_TIPO_PERFIL = 1 BEGIN ... END ELSE BEGIN ... END

-- ELSEIF

http://www.moreplus.es/index.aspx?accion=articulo&id=136

21-06-2008 00:39:05

moreplus.es - La pagina de los Programadores

Pgina 4

IF @ID_TIPO_PERFIL = 1 BEGIN ... END ELSE BEGIN IF @CODIGO_POSTAL_TA ISNULL BEGIN ... END END

La sentencia de programacin WHILE se usa de la siguiente forma:

WHILE @VARIABLE > 0 BEGIN ... BREAK CONTINUE END

Se puede usar BREAK para salir forzosamente del bucle, o CONTINUE para continuar. Otras funciones son WAITFOR, que espera un cierto tiempo a seguir con la ejecucin del SP y RETURN, que sale del SP sin ejecutar nada ms. Funciones Algunas funciones que incluye T-Sql que pueden ser de utilidad son las siguientes: ASCII Devuelve el cgido ASCII del carcter ms a la izquierda de una expreion de caracteres. CHAR Una funcin de cadena que convierte un cdigo ASCII int en un carcter. LEN Devuelve el nmero de caracteres. LTRIM Devuelve una expresin de caracteres despus de quitar los espacios en blanco de la izquierda. REPLACE Reemplaza por una tercera expresin todas las apariciones de la segunda expresin. SUBSTRING Devuelve parte de una expresion de caracteres. UPPER Devuelve una expresin en mayscula. GETDATE Devuelve la fecha y la hora actuales del sistema. DATEADD Devuelve un valor DateTime nuevo que se basa en la suma de un intervalo a la fecha especificada. DATEDIFF

http://www.moreplus.es/index.aspx?accion=articulo&id=136

21-06-2008 00:39:05

moreplus.es - La pagina de los Programadores

Pgina 5

Devuelve el nmero de lmites de fecha y hora que hay entre dos fechas especificadas. DATEPART Devuelve un entero que representa la parte de la fecha especificada de la fecha indicada. Variables del sistema de utilidad @@IDENTITY y SCOPE_IDENTITY() Cuando insertamos un nuevo valor en una tabla, podemos obtener el identificador de ese nuevo registro. Si tenemos una columna, con identidad (lo que sera equivalente a un autonumrico), es decir, que es la bbdd quien le asigna el valor, con @@IDENTITY recuperamos ese valor. Ejemplo:

DECLARE @NUEVO_ID AS BIGINT INSERT INTO NOMBRE_TABLA (CAMPO1, CAMPO2) VALUES (VALOR1, VALOR2) SELECT @NUEVO_ID =@@IDENTITY INSERT INTO NOMBRE_TABLA (CAMPO1, CAMPO2) VALUES (VALOR1, VALOR2) SELECT @NUEVO_ID =SCOPE_IDENTITY()

En un procedimiento almacenado sin Triggers de los que hablaremos a continuacin, ambas sentencias nos devuelven lo mismo. Pero, si por ejemplo, nuestro INSERT activa otro procedimiento que a su vez, esta llamando a otro INSERT, el valor que recibir el @@IDENTITY ser el del segundo insert, que no nos interesa. Por eso, es recomendable usar SCOPE_IDENTITY(). @@ERROR Cuando realizamos cualquier operacin, si no se produce ningn error, esta variable se mantiene a 0, sino, obtendr otro valor. Es til crear una variable de tipo entero a la que le asignamos este valor cada vez que realizamos una operacin, para verificar que si sta se ha realizado correctamente. Transacciones Se declaran con BEGIN TRAN. A partir de esta sentencia, todo las operaciones que realicemos se van guardando internamente. Si al final del procedimiento ejecutamos COMMIT TRAN, todas las operaciones escritas a partir del BEGIN TRAN se ejecutaran. Si ponemos ROLLBACK TRAN, de desharn todas las acciones escritas a partir del BEGIN TRAN. Esto es muy til para evitar que si un procedimiento se queda a medias o se ha producido algn error, datos intiles se queden insertados o actualizados. Ejemplo:

http://www.moreplus.es/index.aspx?accion=articulo&id=136

21-06-2008 00:39:05

moreplus.es - La pagina de los Programadores

Pgina 6

DECLARE @ERROR AS INT SELECT @ERROR = @error +abs(@@error) BEGIN TRAN TRANSACCION_PRUEBA .... SELECT @ERROR = @error +abs(@@error) IF @ERROR <> 0 BEGIN ROLLBACK TRAN TRANSACCION_PRUEBA END ELSE BEGIN COMMIT TRAN TRANSACCION_PRUEBA END

Nota: TRY y CATCH Adems del @@ERROR existe una sentencia ms cmoda a la hora de detectar que se ha producido un error en nuestro procedimiento y ejecutar un ROLLBACK en consecuencia. Al igual que en C# se puede abrimos un try para la secuencias de comandos que podran dar error y un catch para realizar un deshacer si esto ocurre.

BEGIN TRAN (el nombre solo es necesario en el caso de que haya varias transacciones) BEGIN TRY .... COMMIT TRAN END TRY BEGIN CATCH ROLLBACK TRAN END CATCH

Cursores Un cursor nos permite movernos por los registros de una consulta (el resultado obtenido de una select) uno por uno. Esto es muy til si lo que queremos es realizar una accion si el id de un registro es autonumerico y no lo conocemos hasta que se inserta el registro y queremos insertar ese id en cualquier otra tabla. Lo primero que tenemos que hacer es declarar el cursor con la sentencia que nos devolver los datos DECLARE NombreCursor CURSOR FOR (la sentencia SQL que nos devolver los datos) A continuacin abrimos el cursor

http://www.moreplus.es/index.aspx?accion=articulo&id=136

21-06-2008 00:39:05

moreplus.es - La pagina de los Programadores

Pgina 7

OPEN NombreCursor Para leer los registros del cursor, usamos la sentencia FETCH NEXT FROM NombreCursor INTO (la variable o variables en la que guardaremos el contenido de los resultados de la select) Una vez tenemos el contenido guardado, podemos usar esas variables para las acciones que necesitemos. Iremos recorriendo con el cursor cada una de las filas que nos ha devuelto la consulta mientras el estado sea correcto (@@ fetch_status= 0) y leyendo el siguiente registro al final del mismo. No debemos olvidar cerrar y liberar el espacio creado por el cursor al final, con las sentencias CLOSE y DEALLOCATE respectivamente. Ejemplo:

DECLARE @ID_CODIGO_POSTAL AS BIGINT DECLARE @DESC_CODIGO_POSTAL AS VARCHAR DECLARE @ZONA AS BIGINT

--DECLARAMOS EL CURSOR DECLARE cursorCodigoPostal CURSORFOR SELECT ID_CODIGO_POSTAL, DESC_CODIGO_POSTAL FROM CODIGOS_POSTALES

--ABRIMOS EL CURSOR OPEN cursorCodigoPostal

--LEEMOS EL PRIMER REGISTRO FETCH NEXT FROM cursorCodigoPostal INTO @ID_CODIGO_POSTAL, @DESC_CODIGO_POSTAL

--MIENTRAS EL STATUS SEA 0 WHILE @@fetch_status = 0 BEGIN --REALIZAMOS LAS ACCIONES QUE QUERAMOS SELECT @ID_ZONA = ID_ZONA FROM ZONA_CP WHERE ID_CODIGO_POSTAL = @ID_CODIGO_POSTAL UPDATE ANUNCIOS SET ID_ZONA = @ID_ZONA, SET DESC_CODIGO_POSTAL = @DESC_CODIGO_POSTAL WHERE ID_CODIGO_POSTAL = @ID_CODIGO_POSTAL

http://www.moreplus.es/index.aspx?accion=articulo&id=136

21-06-2008 00:39:05

moreplus.es - La pagina de los Programadores

Pgina 8

FETCH NEXT FROM cursorCodigoPostal INTO @ID_CODIGO_POSTAL, @DESC_CODIGO_POSTAL END CLOSE cursorCodgioPostal DEALLOCATE cursorCodgioPostal END

Nota: Tablas Temporales Los cursores tienen una desventaja. Mientras el cursor permanece abierto, las tablas a las que afecte se mantienen bloqueadas mientras ste este en funcionamiento. No tiene sentido que se permita insertar o modificar un registro en ese momento, porque los resultados obtenidos podran ser distintos a los que hubiera luego en la tabla. Pero tampoco tiene sentido que la tabla se quede bloqueada, por lo que es, en muchas ocasiones recomendable, usar una tabla temporal intermedia en la que guardaremos los resultados de la consulta y sobre la cual abriremos el cursor. La tabla temporal desaparecer el final del procedimiento.

-- DECLARACION DE VARIABLES DECLARE @ID_CODIGO_POSTAL AS BIGINT DECLARE @DESC_CODIGO_POSTAL AS VARCHAR DECLARE @ZONA AS BIGINT -- TABLA TEMPORAL PARA CONSULTA DECLARE @TMP_CODIGOS_POSTALES Table ( ID_CODIGO_POSTAL BIGINT, DESC_CODIGO_POSTAL VARCHAR ) -- Insertamos en la tabla temporal INSERT @TMP_CODIGOS_POSTALES ( ID_CODIGO_POSTAL, DESC_CODIGO_POSTAL ) SELECT ID_CODIGO_POSTAL, DESC_CODIGO_POSTAL FROM CODIGOS_POSTALES -Declaramos el cursor de la tabla temporal

DECLARE CursorTablaTemp CURSORFOR SELECT ID_CODIGO_POSTAL , DESC_CODIGO_POSTAL FROM @TMP_CODIGOS_POSTALES

http://www.moreplus.es/index.aspx?accion=articulo&id=136

21-06-2008 00:39:05

moreplus.es - La pagina de los Programadores

Pgina 9

-- Abrimos cursor OPEN CursorTablaTemp

-- Leemos el primer registro del cursor FETCH NEXT FROM CursorTablaTemp INTO @ID_CODIGO_POSTAL , @DESC_CODIGO_POSTAL WHILE @@FETCH_STATUS = 0 BEGIN SELECT @ID_ZONA = ID_ZONA FROM ZONA_CP WHERE ID_CODIGO_POSTAL = @ID_CODIGO_POSTAL UPDATE ANUNCIOS SET ID_ZONA = @ID_ZONA, SET DESC_CODIGO_POSTAL = @DESC_CODIGO_POSTAL WHERE ID_CODIGO_POSTAL = @ID_CODIGO_POSTAL FETCH NEXT FROM CursorTablaTemp INTO @ID_CODIGO_POSTAL , @DESC_CODIGO_POSTAL END CLOSE CursorTablaTemp DEALLOCATE CursorTablaTemp END

COMENTARIOS

Escrito por SamPistolas el Miercoles, 23 de Abril de 2008 Muy buen tutorial... cualquiera puede entenderlo. Gracias por el aporte Escrito por Negrucia el Miercoles, 9 de Abril de 2008 me parece un buen resumen sobre manejo de procedimientos, personalmente me ayudo, es claro a la hora de dar ejemplos gracias y espero que encontremos mas ejemplos de este tipo

NUEVO COMENTARIO Agradecemos tu participacin. Te pedimos que mantengas en tus opiniones la debida educacin y el respeto a los dems. Los mensajes enviados no son revisados por el titular de esta pgina web, por lo que no asume ninguna responsabilidad respecto del contenido de los mismos. Nick:

anonimo

http://www.moreplus.es/index.aspx?accion=articulo&id=136

21-06-2008 00:39:05

moreplus.es - La pagina de los Programadores

Pgina 10

http://www.moreplus.es/index.aspx?accion=articulo&id=136

21-06-2008 00:39:05

También podría gustarte