procedimiento almacenado inf 257
Post on 14-Dec-2014
61 Views
Preview:
TRANSCRIPT
PROCEDIMIENTO ALMACENADO INF 257
Un procedimiento almacenado (stored procedure) es un programa (o procedimiento) el cual es almacenado físicamente en una base de datos. Generalmente son escritos en un lenguaje de bases de datos propietario como PL/SQL para Oracle database o PL/PgSQL para PostgreSQL. La ventaja de un procedimiento almacenado es que al ser ejecutado, en respuesta a una petición de usuario, es ejecutado directamente en el motor de bases de datos, el cual usualmente corre en un servidor separado. Como tal, posee acceso directo a los datos que necesita manipular y solo necesita enviar sus resultados de regreso al usuario, deshaciéndose de la sobrecarga resultante de comunicar grandes cantidades de datos salientes y entrantes.
Usos típicos para procedimientos almacenados incluyen la validación de datos siendo integrados a la estructura de base de datos (los procedimientos almacenados utilizados para este propósito a menudo son llamados detonadores), o encapsular un proceso grande y complejo. El último ejemplo generalmente ejecutará más rápido como un procedimiento almacenado que de haber sido implementado como, por ejemplo, un programa corriendo en el sistema cliente y comunicándose con la base de datos mediante el envío de consultas SQL y recibiendo sus resultados.
Los procedimientos pueden ser ventajosos: Cuando una base de datos es manipulada desde muchos programas externos. Al incluir la lógica de la aplicación en la base de datos utilizando procedimientos almacenados, la necesidad de embeber la misma lógica en todos los programas que acceden a los datos es reducida. Esto puede simplificar la creación y, particularmente, el mantenimiento de los programas involucrados.
Podemos ver un claro ejemplo de estos procedimientos cuando requerimos realizar una misma operación en un servidor dentro de algunas o todas las bases de datos y a la vez dentro de todas o algunas de las tablas de las bases de datos del mismo. Para ello podemos utilizar a los Procedimientos almacenados auto creables que es una forma de generar ciclos redundantes a través de los procedimientos almacenados.
Obtenido de "http://es.wikipedia.org/wiki/Procedimientos_almacenados"
Categorías: Wikipedia:Fusionar | Objetos de la base de datos relacional
Generando Procedimientos Almacenados de manera automática
Fecha: 05/Ago/2005 (04-08-05)Autor: Martin Luchessi
Hola, mi nombre es Martín Luchessi. Soy de Rosario, Argentina y es la primera vez que escribo (o al menos, intento escribir) un artículo sobre informática, asi que por favor, ténganme paciencia. :P
La idea de este artículo es explicar, al menos desde mi experiencia, el uso de las vistas de sistema y funciones de SQL Server, para realizar un script que genere código SQL para crear un procedimiento almacenado (desde ahora en adelante, PA) que actualice, modifique y elimine registros de una tabla dada de acuerdo a la clave de la misma.
Si bien con SQL Server 2000 podemos generar 3 PAs que hagan las 3 consultas por separado, la idea es que este script genere UN solo PA y que realice la acción correspondiente de acuerdo a un parámetro del PA.
Este script generará un código que se escribirá en el panel de resultados de SQL Server, el cual nosotros copiaremos luego para correrlo en una nueva consulta.
Es decir, la idea es que el código generado sea algo asi:
CREATE PROCEDURE <NOMBRE_DEL_PA>
(
@p_parametro1 TIPO_DATO,
@p_parametro2 TIPO_DATO,
…
@p_tipo_accion CHAR(1)
)
AS
Si @tipo_accion = ‘A’ –-acción ACTUALIZAR O INSERTAR
si no existe un registro en la tabla indicada para la clave de la misma
Ejecuto una consulta INSERT sobre la tabla
si existe el registro
Ejecuto una consulta UPDATE sobre la tabla
END
IF @tipo_accion = “E” –acción ELIMINAR
Borro los registros de la tabla.
Devuelvo cantidad de registros actualizados por la consulta
Vale la pena aclarar, que al momento de borrar registros, el script no controla (al menos esta versión no lo hace) que existan tablas relacionadas con la tabla de la cual se desea borrar registros. Es decir, si quiero borrar una persona y esta tiene números de teléfonos relacionados, si existe una restricción de clave foránea armada para la tabla de personas, con aquella que guarda los números de teléfonos, el motor de base de datos generará una excepción y no permitirá efectuar la consulta. De la misma manera, tampoco controla que, al momento de insertar un nuevo registro en la tabla, se esté ingresando datos que no existan en tablas relacionadas con ésta.
Bueno, basta ya de explicaciones y pongámonos manos a la obra.
DECLARACIÓN DE LAS VARIABLES DE ENTRADA.
En primer lugar, necesitaremos 2 variables importantes para este script. Una que contendrá el nombre de la tabla sobre la que generaremos el PA y otra que contendrá el nombre del PA. Ésta variable en realidad puede ser obviada, ya que podemos dejar que el script se encargue de nombrar el PA. En mi caso yo elegí que si esta variable viene vacía el PA se llame “PA_ABM_NOMBRE_TABLA”, pero es algo que fácilmente pueden cambiar si no les gusta. Ambas variables fueron declaradas como SYSNAME, ya que éste es el tipo de datos suministrado por el sistema y definido por el usuario que es funcionalmente equivalente a nvarchar(128) y que se utiliza para hacer referencia a nombres de objetos de bases de datos.
A continuación escribimos dos líneas que nos permitirán asignarle valor a estas variables. Los valores van escritos entre comillas simples por ser SYSNAME un tipo de dato de texto.
DECLARE @P_NOMBRE_TABLA SYSNAME
DECLARE @P_NOMBRE_PA SYSNAME
set @P_NOMBRE_TABLA = 'aquí va el nombre de la tabla'
set @P_NOMBRE_PA = 'aquí va el nombre del PA si quieren asignarle uno'
Esta sección es la única parte del código que tendremos que modificar, cuando queramos generar un PA para una tabla.
DECLARACIÓN DE VARIABLES AUXILIARES
Las siguientes son variables auxiliares que nos ayudarán a mantener el texto que deberá escribir el script en el panel de resultados del Analizador de Consultas de SQL Server 2000.
DECLARE @SQL_CABECERA VARCHAR(8000)
DECLARE @dato VARCHAR(8000)
DECLARE @SQL_WHERE VARCHAR(8000)
DECLARE @SQL_UPDATE VARCHAR(8000)
DECLARE @SQL_INSERT VARCHAR(8000)
DECLARE @SQL_VALUES VARCHAR(8000)
DECLARE @SQL_DELETE VARCHAR(8000)
La variable @SQL_CABECERA la utilizaremos para guardar la cabecera del PA. Es decir, toda la sección que comprende la verificación de que el PA exista en la base de datos, la eliminación y posterior creación del PA con sus parámetros.
Las restantes variables declaradas arriba se utilizarán para armar cada consulta.
Ahora bién. ¿Cómo sabemos que tabla hay que actualizar y bajo qué condición? ¿Cómo sabemos cuales columnas son clave de la tabla y cual no? ¿Qué tipo de dato tiene cada columna de la tabla? Todos estos datos son necesarios para actualizar una tabla, o mejor dicho, sus datos.
Para esto, vamos a necesitar, una variable de tipo TABLE, que me permita dejar registrado todas las características de la tabla sobre la que se quiere operar. Y además, el órden en que se encuentran las columnas, para luego poder respetar los índices de la tabla.
DECLARE @tabla TABLE(orden smallint, columna SYSNAME, pk BIT, parametro varchar(25), tipo_dato varchar(25), largo smallint, decimales smallint)
La columna columna, contendrá el nombre de las columnas de la tabla.
La columna PK, nos indicará si la columna de la tabla es Primary Key o no.
La columna parámetro, nos servirá para saber a que parámetro del PA corresponde esta columna.
La columna tipo_dato, largo y decimales dejarán registrado que tipo de dato tiene la columna de la tabla, el largo del tipo de dato y la precisión del mismo.
También necesitaremos declarar variables para las columnas, para utilizarlas a la hora de recorrer la VARIABLE @tabla.
DECLARE @orden SMALLINT
DECLARE @largo SMALLINT
DECLARE @decimales SMALLINT
DECLARE @pk BIT
DECLARE @parametro VARCHAR(25)
DECLARE @columna SYSNAME
Por último,esta variable @update, sirve como bandera para controlar que si la tabla es una tabla TODO-CLAVE, es decir, que todas las columnas de la tabla son clave primaria, no será necesario hacer un update de la misma. Por lo tanto, tomará valor 0 (cero) cuando no sea necesario y 1 (uno) cuando si lo sea.
DECLARE @update BIT
VALIDANDO LA EXISTENCIA DE LA TABLA
Antes de empezar a generar el código, sería interesante que el script controle que la tabla sobre la cual se quiere generar el PA exista.
Si el nombre de la tabla está vacío, sería interesante imprimir un cartel insitando al programador, o usuario del script , a que escriba un nombre de una tabla, sino el script no tendría sentido.
IF LEN(@p_nombre_tabla)=0
begin
PRINT 'ESTAS PENSANDO EN LO QUE HACES? Y EL NOMBRE DE LA TABLA? '
PRINT 'ADIVINO NO SOY!'
RETURN
end
Del mismo modo, un nombre de tabla inválido tendría el mismo efecto y podemos generar un mensaje de error de la base de datos, haciendo una consulta sobre la tabla inexistente, para obviarnos el poner un mensaje nosotros,.
IF OBJECT_ID(@p_nombre_tabla) IS NULL
begin
--PRINT 'LA TABLA <' + @p_nombre_tabla + '> NO EXISTE COMO UN OBJETO'
SET @p_nombre_tabla='SELECT 1 FROM ' + @p_nombre_tabla
exec(@p_nombre_tabla)
return
end
La función Object_ID(objeto) devolverá null si la tabla no se encuentra en la base de datos y el ID de la tabla, en caso contrario.
RECOLECTANDO DATOS SOBRE LA TABLA
Para armar este script vamos a necesitar distinguir las distintas partes del PA que queremos que arme. Para mi entender, el PA consta de 4 partes:
· CABECERA
· CONSULTA INSERT
· CONSTULTA UPDATE
· CONSULTA DELETE
En la cabecera, cómo dije anteriormente, vamos a escribir la creación del PA, con sus parámetros y los tipos de datos de los mismos. Además, vamos a agregarle valores por defecto a estos, para asi lograr que se puedan obviar ciertos parámetros cuando se quiera ejecutar el PA desde alguna aplicación. Por ejemplo, cuando se quiera hacer un DELETE los únicos parámetros que tendremos que pasarle serían aquellos que son clave de la tabla y el parámetro “@p_accion = ‘E’”.
En la consulta INSERT, no tendremos demasiados problemas. Sólo necesitamos los nombres de las columnas y sus valores.
En cambio en las consultas UPDATE y DELETE necesitaremos armar el WHERE de la consulta, y es aquí donde viene el pequeño problema ya que necesitaremos saber cuáles columnas son PRIMARY KEY y cuales no.
Aquí haremos uso de la variable @Tabla que hemos declarado al comienzo de nuestro script para poder guardar toda la información que necesitemos sobre la tabla que estamos trabajando y así no hacer una consulta a las tablas de sistema cada vez que lo requiramos.
Para buscar información sobre las tablas haremos uso de las VISTAS DE ESQUEMA DE INFORMACIÓN de SQL Server 2000.
Estas vistas proporcionan una vista interna e independiente de las tablas del sistema de los metadatos de SQL Server. Las vistas de esquema de información permiten que las aplicaciones funcionen correctamente aunque se hayan realizado cambios significativos en las tablas del sistema. Las vistas de esquema de información que contiene SQL Server cumplen la definición del estándar SQL-92 para INFORMATION_SCHEMA.
Estas vistas se definen en un esquema especial llamado INFORMATION_SCHEMA, contenido en cada base de datos. Cada vista de INFORMATION_SCHEMA contiene metadatos para todos los objetos de datos almacenados en esa base de datos en particular. Esta tabla describe las relaciones existentes entre los nombres de SQL Server y los nombres estándar de SQL-92.
Vamos a utilizar las siguientes vistas:
· COLUMNS
Contiene una fila por cada columna a la que puede tener acceso el usuario actual en la base de datos actual.
· TABLE_CONSTRAINTS
Contiene una fila por cada restricción de tabla de la base de datos actual. Esta vista de esquema de información devuelve información acerca de los objetos sobre los que el usuario actual tiene permisos.
· KEY_COLUMN_USAGE
Contiene una fila por cada columna, de la base de datos actual, que está restringida como clave. Esta vista de esquema de información devuelve información acerca de los objetos sobre los que el usuario actual tiene permisos.
De la vista COLUMNS nos interesa buscar el nombre de cada columna de la tabla (COLUMN_NAME), el tipo de dato de cada columna (DATA_TYPE), el tamaño máximo de caracteres (CHARACTER_MAXIMUM_LENGTH) en caso de tipos de dato de texto, o la precisión (NUMERIC_PRESICION) en caso de tipos de datos numéricos (en caso de datos con decimales, necesitaremos saber cuántos decimales tiene con (NUMERIC_SCALE)), y el número identificador de columna (ORDINAL_POSITION).
Las vistas KEY_COLUMN_USAGE y TABLE_CONSTRAINTS las vamos a usar para ver que columnas de la tabla son PRIMARY KEY haciendo una consulta y relacionando columnas entre las vistas.
Así, cada dato que seleccionemos de estas vistas, lo insertaremos en la variable @tabla, de la siguiente manera:
insert into @tabla
select
COLS.ORDINAL_POSITION,
COLS.COLUMN_NAME,
convert(bit,(
select count(*)
from
INFORMATION_SCHEMA.TABLE_CONSTRAINTS as CONST
1
2
3
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as COL ON
CONST.TABLE_SCHEMA = COL.TABLE_SCHEMA AND
CONST.TABLE_NAME = COL.TABLE_NAME AND
CONST.CONSTRAINT_NAME = COL.CONSTRAINT_NAME
where
CONST.CONSTRAINT_TYPE = 'PRIMARY KEY' AND
CONST.CONSTRAINT_SCHEMA = 'dbo' AND
COL.TABLE_NAME = COLS.TABLE_NAME AND
COL.COLUMN_NAME = COLS.COLUMN_NAME
)),
'@p_' + COLS.COLUMN_NAME,
UPPER(COLS.DATA_TYPE),
ISNULL(COLS.CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION),
isnull(cols.numeric_scale,0)
from
INFORMATION_SCHEMA. COLUMNS COLS WITH (NOLOCK)
where
COLS.TABLE_NAME = @P_NOMBRE_TABLA
order by
cols.ordinal_position
4
5
6
7
8
Como podemos observar, en las líneas 1 y 2, estamos usando las columnas ORDINAL_POSITION y COLUMN_NAME para guardarlas en las columnas “orden” y “columna” de la tabla @tabla.
En la línea 3 nos vamos a detener un poco. Más arriba en este artículo, habíamos dicho que necesitábamos saber qué columnas de la tabla eran clave primaria para poder luego armar el WHERE de las consultas UPDATE y DELETE. Aquí se está realizando una subconsulta para contar todas las columnas cuyo tipo de constraint sea “PRIMARY KEY” de la tabla @P_NOMBRE_TABLA, relacionando las vistas TABLE_CONSTRAINTS y KEY_COLUMN_USAGE por medio de sus columnas TABLE_SCHEMA, CONSTRAINT_NAME y TABLE_NAME, para ver cuales son las restricciones de @P_NOMBRE_TABLA. Como sólo nos interesa la restricción PRIMARY KEY, filtramos por la columna CONSTRAINT_TYPE de la vista TABLA_CONSTRAINTS.
A continuación, convertimos el valor que devuelve la subconsulta a Bit, asi podremos guardar en la columna PK de @tabla , un 1 si el COUNT es > 0, y 0 en caso contrario.
En el renglón marcado con el número 4 estamos guardando el valor para la columna @parametro de la variable @tabla, ya con el agregado del prefijo “@p_”, que nos indicará cuál es el parámetro del PA que le corresponde a cada columna.
En la linea 5, vamos a guardar el tipo de dato de la columna, y en las líneas 6 y 7 obtendremos el largo del tipo de dato y la precisión. Si CHARACTER_MAXIMUM_LENGHT es NULL entonces guardermos NUMERIC_PRESICION, ya que estaríamos en presencia de un tipo de dato numérico. Si NUMERIC_SCALE es NULL entonces guardaremos 0 ya que estaríamos en presencia de datos enteros, texto. Para los tipos de dato DATETIME no nos interesa tener mucho detalle en este caso.
En las líneas 7 y 8 solamente le indicamos a la consulta en que tabla queremos que busque información y ordenamos por ORDINAL_POSITION para que busque en el orden de las columnas de la tabla.
Veamos todo esto en un ejemplo práctico.
Ejemplo: PA sobre la tabla PERSONAS.
Supongamos una tabla PERSONAS con los siguientes atributos.
Si hacemos una consulta sobre la variable @tabla, luego de recabar los datos, daría un resultado como este:
orden
columna
pk
parametro tipo_dato
largo
Decimales
1 Cod_persona 1 @p_Cod_persona
INT 10 0
2 Nombre 0 @p_Nombre
VARCHAR
50 0
3 Apellido 0 @p_Apellido
VARCHAR
50 0
4 Tipo_doc 0 @p_Tipo_doc
SMALLINT
5 0
5 Nro_doc 0 @p_Nro_doc
VARCHAR
20 0
6 Fec_nacimiento 0 @p_Fec_nacimiento
DATETIME
23 3
Cómo podemos observar, la columna Cod_persona, tiene un 1 en PK, es decir que es clave primaria. El parámetro que le corresponderá en el PA se llamará @p_Cod_persona, es de tipo INT con un largo de 10 y 0 decimales, lo cual es correcto.
Ahora, vamos a acomodar la columna tipo_dato de @tabla para que contenga el podamos tener el tamaño máximo de caracteres, o la presición del tipo de dato entre paréntesis ya que cuando tengamos que cuando tengamos que declarar los parámetros del PA los vamos a necesitar.
Para esto hacemos un cursor que recorra la tabla y actualice la columna según si tiene decimales o no, pero sólo para aquellas columnas que lo requieran.
DECLARE C_COLUMNAS CURSOR LOCAL FOR
SELECT
orden,
largo,
decimales
FROM
@tabla
WHERE
tipo_dato IN ('VARCHAR','CHAR','NVARCHAR','NCHAR','DECIMAL','NUMERIC')
OPEN C_COLUMNAS
FETCH NEXT FROM C_COLUMNAS INTO
@orden,
@largo,
@decimales
WHILE @@FETCH_STATUS = 0
BEGIN
IF @decimales = 0
UPDATE
@tabla
SET tipo_dato = tipo_dato + '(' + CONVERT(VARCHAR, @largo) + ')'
WHERE
orden = @orden
ELSE
UPDATE
@tabla
SET tipo_dato = tipo_dato + '(' + CONVERT(VARCHAR, @largo) + ',' + CONVERT(VARCHAR,@decimales) + ')'
WHERE
orden = @orden
FETCH NEXT FROM C_COLUMNAS INTO
@orden,
@largo,
@decimales
END
CLOSE C_COLUMNAS
DEALLOCATE C_COLUMNAS
Ahora si, si hiciéramos, otra vez, una consulta sobre @tabla nos quedaría:
orden
columna pk
parametro
tipo_dato
largo
Decimales
1 Cod_persona 1 @p_Cod_persona
INT 10 0
2 Nombre 0 @p_Nombre
VARCHAR(50)
50 0
3 Apellido 0 @p_Apellido
VARCHAR(50)
50 0
4 Tipo_doc 0 @p_Tipo_ SMALLIN 5 0
doc T
5 Nro_doc 0 @p_Nro_doc
VARCHAR(20)
20 0
6 Fec_nacimiento 0 @p_Fec_nacimiento
DATETIME
23 3
Una vez recolectado todos los datos y acomodados a nuestro gusto, estamos listos para armar las partes del PA.
LA CABECERA
Siguiendo con el ejemplo de la tabla PERSONAS, la cabecera del PA debería quedar algo asi:
IF EXISTS (SELECT name FROM sysobjects WHERE name = N'PA_ABM_PERSONAS' AND type = 'P')
DROP PROCEDURE PA_ABM_PERSONAS
GO
CREATE PROCEDURE PA_ABM_PERSONAS
(
@p_Cod_persona INT,
@p_Nombre VARCHAR(50)= NULL ,
@p_Apellido VARCHAR(50)= NULL ,
@p_Tipo_doc SMALLINT= NULL ,
@p_Nro_doc VARCHAR(20)= NULL ,
@p_Fec_nacimiento DATETIME= NULL,
@p_accion CHAR(1) --A = ACTUALIZA (INSERT/UPDATE) , E = ELIMINA
)
AS
La primera parte de la cabecera, cómo dijimos al principio, nos servirá para eliminar el PA de la base de datos en caso de que este ya exista, y luego lo volveremos a crear.
Como podemos notar, en la segunda parte, hay columnas que tienen valores por defecto y otras que no. Este se debe, por supuesto, a que las columnas clave tienen que ser obligatorias a la hora de ejecutar las consultas. También vemos que los tipo de dato de texto tienen que ir declarados con su tamaño máximo de caracteres, al igual que los datos decimales.
EL CUERPO
El cuerpo que queremos armar del PA debería quedar asi:
IF (@p_accion = 'A')
BEGIN -- SI LA ACCION ES ACTUALIZAR
IF NOT EXISTS (
SELECT 1
FROM
PERSONAS
WHERE
Cod_persona = @p_Cod_persona
)
INSERT INTO PERSONAS
(
Cod_persona,
Nombre,
Apellido,
Tipo_doc,
Nro_doc,
Fec_nacimiento
)
VALUES
(
@p_Cod_persona,
@p_Nombre,
@p_Apellido,
@p_Tipo_doc,
@p_Nro_doc,
@p_Fec_nacimiento
)
ELSE --SI EXISTE HAGO UPDATE
UPDATE PERSONAS
SET
Nombre = @p_Nombre,
Apellido = @p_Apellido,
Tipo_doc = @p_Tipo_doc,
Nro_doc = @p_Nro_doc,
Fec_nacimiento = @p_Fec_nacimiento
WHERE
Cod_persona = @p_Cod_persona
END --TERMINA DE ACTUALIZAR
ELSE IF @p_accion = 'E'
DELETE PERSONAS
WHERE
Cod_persona = @p_Cod_persona
RETURN @@ROWCOUNT
GO
Para lograr que el script escriba esto en el panel de resultados, debemos usar el método PRINT en cada línea que queramos escribir o en las variables de texto que declaramos al comienzo de esta historia.
ESCRIBIENDO EL PROCEDIMIENTO ALMACENADO EN PANTALLA
Para comenzar a escribir el PA, debemos, en principio, inicializar las variables.
/* INCIALIZO LAS VARIABLES DEL TEXTO */
IF @P_NOMBRE_PA = ''
SET @P_NOMBRE_PA = 'PA_ABM_'+ @P_NOMBRE_TABLA
SET @SQL_WHERE = ' WHERE
'
SET @SQL_INSERT = ' INSERT INTO ' + @P_NOMBRE_TABLA + '
(
'
SET @SQL_VALUES = ' VALUES
(
'
SET @SQL_UPDATE = ' UPDATE ' + @P_NOMBRE_TABLA + '
SET
'
SET @SQL_DELETE = ' DELETE ' + @P_NOMBRE_TABLA + '
'
SET @SQL_CABECERA = 'IF EXISTS (SELECT name FROM sysobjects WHERE name = N''' + @P_NOMBRE_PA + ''' AND type = ''P'')'+CHAR(13) +
'DROP PROCEDURE ' + @P_NOMBRE_PA + CHAR(13) +
'GO' + CHAR(13) + CHAR(13) + + CHAR(13) + CHAR(13) +
'CREATE PROCEDURE '+ @P_NOMBRE_PA + CHAR(13) + '(' + CHAR(13)
La variable @P_NOMBRE_PA la inicializamos con el nombre de la tabla más el prefijo “PA_ABM_”, sólo en caso de que no se haya ingresado un valor al correr el script.
Una vez inicializadas las variables que vamos a utilizar, comenzamos a armar la información que estas van a contener para luego imprimirla en pantalla.
Lo que vamos a hacer es usar un cursor para recorrer la variable @tabla, y vamos a obtener los valores de las columnas “columna”, “parámetro” y “pk”. Además en la variable auxiliar @dato, vamos a armar la declaración de parámetros de la cabecera.
DECLARE C_TABLA CURSOR LOCAL FOR
SELECT
' ' +parametro + ' ' + tipo_dato +
CASE pk
WHEN 0 THEN '= NULL ,'
ELSE ',' END + CHAR(13),
columna,
parametro,
pk
FROM
@tabla
ORDER BY orden
OPEN C_TABLA
FETCH NEXT FROM C_TABLA INTO
@dato,
@columna,
@parametro,
@pk
Por cada registro, si la columna “pk” es igual a 1, es decir, si es clave primaria vamos a armar el WHERE. Caso contrario armamos las columnas a actualizar en la consulta UPDATE. Además, como podemos ver, vamos hacer uso de la bander @update, asignándole el valor 1 para indicar que hay , al menos una columna que no es clave, por lo tanto se tendrá que escribir la cláusula UPDATE.
Luego armamos los valores para las variables @SQL_INSERT y @SQL_VALUES.
Una vez que se terminó de recorrer todo el cursor, lo cerramos y liberamos la memoria.
WHILE @@FETCH_STATUS = 0
BEGIN
-- SI LA COLUMNA ES CLAVE ARMO EL WHERE
IF (@pk = 1)
SET @SQL_WHERE = @SQL_WHERE + ' ' + @columna + ' = ' + @parametro + ' AND ' + CHAR(13)
ELSE IF (@pk = 0)
SELECT @SQL_UPDATE = @SQL_UPDATE + ' ' + @columna + ' = ' + @parametro + ',' + CHAR(13) ,
@update=1
SET @SQL_INSERT = @SQL_INSERT + ' ' + @columna + ',' + CHAR(13)
SET @SQL_VALUES = @SQL_VALUES + ' ' + @parametro +',' + CHAR(13)
set @SQL_CABECERA = @SQL_CABECERA + @dato
FETCH NEXT FROM C_TABLA INTO
@dato,
@columna,
@parametro,
@pk
END
1
2
3
CLOSE C_TABLA
DEALLOCATE C_TABLA
Finalmente, tenemos que limpiar las variables que hemos utilizado, de las impurezas que nos dejó el concatenar los valores de la tabla. Esto depende de la cantidad de espacios y bajadas de línea que se han concatenado.
SET @SQL_WHERE = LEFT(@SQL_WHERE,LEN(@SQL_WHERE) -6)
SET @SQL_INSERT = LEFT(@SQL_INSERT,LEN(@SQL_INSERT)-2) + '
)'
SET @SQL_VALUES = LEFT(@SQL_VALUES,LEN(@SQL_VALUES)-2) + '
)'
SET @SQL_UPDATE = LEFT(@SQL_UPDATE,LEN(@SQL_UPDATE)-2)
IMPRIMIENDO LAS VARIABLES
¡Bueno! Por fin hemos llegado al final del script. Luego de dar tantas vueltas, vamos a ver los resultados, que, por lo menos en mi caso, fueron más que beneficiosos.
Ahora lo único que resta es imprimir las variables en el panel de resultados.
PRINT @SQL_CABECERA + ' @p_accion CHAR(1) --A = ACTUALIZA (INSERT/UPDATE) , E = ELIMINA
)
AS
'
PRINT 'IF (@p_accion = ''A'')'
PRINT 'BEGIN -- SI LA ACCION ES ACTUALIZAR'
PRINT ' IF NOT EXISTS ( '
PRINT ' SELECT 1 '
PRINT ' FROM '
PRINT ' ' + @P_NOMBRE_TABLA
PRINT ' ' + @SQL_WHERE + '
)'
PRINT @SQL_INSERT
PRINT @SQL_VALUES
IF @update=1
BEGIN
PRINT ' ELSE --SI EXISTE HAGO UPDATE
'
PRINT @SQL_UPDATE
PRINT @SQL_WHERE
END
PRINT 'END --TERMINA DE ACTUALIZAR'
PRINT 'ELSE IF @p_accion = ''E''
'
PRINT @SQL_DELETE
PRINT @SQL_WHERE
PRINT '
RETURN @@ROWCOUNT '
PRINT 'GO
'
GO
La disposición de espacios y bajadas de líneas se pueden ir acomodando a lo largo del armado de las variables y de la impresión final.
Una vez que tengamos todo el script escrito en el Analizador de Consultas, resta elegir sobre que base de datos lo vamos a correr, setear la variable @P_NOMBRE_TABLA y correr el script. En el panel de resultados nos va a aparecer todo el texto del PA, lo copiamos y lo pegamos en una nueva consulta y lo corremos.
Espero que les haya servido este artículo. Yo se que a mi me sirvió mucho el script para ahorrar tiempo en escribir este tipo de PA constantemente. Les adjunto el script completo , el cual pueden abrir con el Analizador de Consultas para usarlo.
Agradezco a Franco Raspo, Matias Toro y Andrés Faya, quienes me motivaron y ayudaron para armar este artículo.
Cualquier sugerencia que quieran hacer, modificaciones y/o correcciones (espero que las hagan) las pueden enviar a martinluchessi@yahoo.com.ar.
Sobre las vistas de SQL pueden encontrar más información en:
http://siquelnet.etraducciones.com/default.aspx?Tema=MSSQL&Seccion=SQL&Articulo=005.xml
o en los libros en pantalla de SQL Server 2000.
Hasta la próxima.
Procedimientos Almacenados Ir arriba Un Procedimiento Almacenado es un programa autocontrolado escrito en lenguaje del DBMS, son almacenados como parte de la Base de Datos y sus metadatos.
Una vez creado un procedimiento almacenado, se puede invocar directamente desde una aplicaci o sustituir el nombre de una tabla o vista, por el nombre de procedimiento en clᵳulas SELECT. Los procedimientos almacenados pueden recibir par᭥tros de entrada y retornar valores a la aplicaci
Las ventajas de usar los procedimientos almacenados incluyen:
o Diseodular. o Aplicaciones que
acceden la misma Base de Datos pueden compartir los procedimientos almacenados, eliminando el co doble y reduciendo el tamae las aplicaciones.
o El f l mantenimiento. ᣩo Cuando un
procedimiento se actualiza, los cambios se reflejan automᴩcamente en todas las aplicaciones, sin la necesidad de recompilar y relinkear. Las aplicaciones son compiladas suna vez para cada cliente.
o Los procedimientos almacenados son ejecutados por el servidor, no por el cliente lo que reduce el tr ᦩ co en la red y mejora el performance o desempeespecialmente para el acceso del cliente remoto.
o Estᮠ almacenados en los servidores y asegurados por las medidas tomadas en la instalacilo que impide que los usuarios normales puedan modificarlos e incluso desconocen su existencia. Este es un elemento de gran valor en lo que a seguridad respecta.
Como se puede apreciar los Sistemas de Bases de Datos ofrecen a desarrolladores, administradores y usuarios una gama muy completa de herramientas que permiten garantizar la integridad, consistencia, confidencialidad y en general seguridad de la informacilmacenada y con un elemento muy importante a favor: Las las de co que se requieren por parte del implementador son muy pocas, en ocasiones solo basta con una sencilla sentencia para obligar al DBMS a controlar y mantener las restricciones necesarias.Cómo crear un procedimiento almacenado (SQL Server Management Studio)
Nuevo: 5 de diciembre de 2005
En este tema se describe cómo crear un procedimiento almacenado de Transact-
SQL mediante el Explorador de objetos de SQL Server Management Studio y se
ofrece un ejemplo en el que se crea un procedimiento almacenado simple en la base
de datos AdventureWorks .
Para crear un procedimiento almacenado
1. En el Explorador de objetos, conéctese a una instancia de SQL Server 2005
Database Engine (Motor de base de datos de SQL Server 2005) y expándala.
2. Expanda Bases de datos, la base de datos a la que pertenece el
procedimiento almacenado y, por último, Programación.
3. Haga clic con el botón secundario en Procedimientos almacenados y, a
continuación, haga clic en Nuevo procedimiento almacenado.
4. En el menú Consulta, haga clic en Especificar valores para parámetros de
plantilla.
5. En el cuadro de diálogo Especificar valores para parámetros de plantilla,
la columna Valor contiene valores recomendados para los parámetros.
Acepte los valores o reemplácelos con nuevos valores y, a continuación, haga
clic en Aceptar.
6. En el editor de consultas, reemplace la instrucción SELECT por las
instrucciones para el procedimiento.
7. Para probar la sintaxis, en el menú Consulta, haga clic en Analizar.
8. Para crear el procedimiento almacenado, en el menú Consulta, haga clic en
Ejecutar.
9. Para guardar la secuencia de comandos, en el menú Archivo, haga clic en
Guardar. Acepte el nombre de archivo o reemplácelo por un nombre nuevo y,
a continuación, haga clic en Guardar.
Nota de seguridad:
Valide toda entrada de usuario. No concatene ninguna entrada de usuario antes de que se valide. No ejecute nunca un comando creado a partir de una entrada de usuario no validada. Para obtener más información, vea Inyección de código SQL.
Para crear un ejemplo de procedimiento almacenado
1. En el Explorador de objetos, conéctese a una instancia de SQL Server 2005
Database Engine (Motor de base de datos de SQL Server 2005) y expándala.
2. Expanda Bases de datos, la base de datos AdventureWorks y, por último,
Programación.
3. Haga clic con el botón secundario en Procedimientos almacenados y, a
continuación, haga clic en Nuevo procedimiento almacenado.
4. En el menú Consulta, haga clic en Especificar valores para parámetros de
plantilla.
5. En el cuadro de diálogo Especificar valores para parámetros de plantilla,
especifique los siguientes valores para los parámetros mostrados.
Parámetro Valor
Author Su nombre.
Create Date La fecha de hoy.
Description Devuelve datos de empleado.
Procedure_name HumanResources.uspGetEmployees
@Param1 @LastName
@Datatype_For_Param1 nvarchar(50)
Default_Value_For_Param1 NULL
@Param2 @FirstName
@Datatype_For_Param2 nvarchar(50)
Default_Value_For_Param2 NULL
6. Haga clic en Aceptar.
7. En el editor de consultas, reemplace la instrucción SELECT por la siguiente
instrucción:
Copiar código
SELECT FirstName, LastName, JobTitle, Department FROM
HumanResources.vEmployeeDepartment WHERE FirstName =
@FirstName AND LastName = @LastName;
8. Para probar la sintaxis, en el menú Consulta, haga clic en Analizar. Si se
devuelve un mensaje de error, compare las instrucciones con la información
anterior y corrija lo que sea necesario.
9. Para crear el procedimiento almacenado, en el menú Consulta, haga clic en
Ejecutar.
10.Para guardar la secuencia de comandos, en el menú Archivo, haga clic en
Guardar. Especifique un nuevo nombre de archivo y haga clic en Guardar.
11.Para ejecutar el procedimiento almacenado, en la barra de herramientas,
haga clic en Nueva consulta.
12.En la ventana de consultas, especifique las siguientes instrucciones:
Procedimientos almacenados del sistema (Transact-SQL)
En SQL Server 2005, muchas actividades administrativas e informativas se pueden
realizar mediante los procedimientos almacenados del sistema. Los procedimientos
almacenados del sistema se agrupan en las categorías que aparecen en la siguiente
tabla.
En esta sección
Categoría Descripción
Procedimientos almacenados de Active Directory
Se utilizan para registrar instancias de SQL Server y bases de datos de SQL Server en Active Directory de Microsoft Windows 2000.
Procedimientos almacenados del catálogo
Se utilizan para implementar las funciones del diccionario de datos ODBC y aislar las aplicaciones ODBC de los cambios en las tablas subyacentes del sistema.
Procedimientos almacenados de cursor
Se utilizan para implementar la funcionalidad de variable de cursor.
Procedimientos almacenados del motor de base de datos
Se utilizan para el mantenimiento general del SQL Server Database Engine (Motor de base de datos de SQL Server).
Procedimientos almacenados de Correo electrónico de base de datos y SQL Mail
Se utilizan para realizar operaciones de correo electrónico desde una instancia de SQL Server.
Procedimientos almacenados de planes de mantenimiento de bases de datos
Se utilizan para configurar las tareas de mantenimiento fundamentales necesarias para administrar el rendimiento de las bases de datos.
Procedimientos almacenados de consultas distribuidas
Se utilizan para implementar y administrar consultas distribuidas.
Procedimientos almacenados de la búsqueda de texto
Se utilizan para implementar y consultar índices de texto.
Procedimientos almacenados del trasvase de registros
Se utilizan para establecer, modificar y supervisar las configuraciones de los trasvases de registros.
Procedimientos almacenados de automatización
Permiten utilizar objetos de automatización estándar en un lote estándar de Transact-SQL.
Procedimientos almacenados de Notification Services
Se utilizan para administrar SQL Server 2005 Notification Services.
Procedimientos almacenados de réplica
Se utilizan para administrar la réplica.
Procedimientos almacenados de seguridad
Se utilizan para administrar la seguridad.
Procedimientos almacenados del Analizador de SQL Server
Son utilizados por el Analizador de SQL Server para supervisar el rendimiento y la actividad.
Procedimientos almacenados del Agente SQL Server
Son utilizados por el Agente SQL Server para administrar actividades programadas y controladas por eventos.
Procedimientos almacenados de tareas Web
Se utilizan para crear páginas Web.
Procedimientos almacenados de XML
Se utilizan para la administración del texto XML.
Procedimientos almacenados extendidos generales
Proporcionan una interfaz de una instancia de SQL Server a los programas externos para diversas actividades de mantenimiento.
Nota:
A menos que se documente específicamente lo contrario, todos los procedimientos almacenados del sistema devuelven el valor 0. Esto indica que son correctos. Para indicar un error, se devuelve un valor distinto de cero.
Procedimientos almacenados del sistema de la API
Los usuarios que ejecutan el Analizador de SQL Server con aplicaciones ADO, OLE
DB y ODBC pueden observar que dichas aplicaciones utilizan procedimientos
almacenados del sistema que no se tratan en la Referencia de Transact-SQL. Estos
procedimientos almacenados son utilizados por el proveedor OLE DB de Microsoft
SQL Native Client y el controlador ODBC de SQL Native Client a fin de implementar
la funcionalidad de una API de base de datos. Estos procedimientos almacenados
simplemente son el mecanismo que el proveedor o el controlador utiliza para
comunicar las solicitudes del usuario a una instancia de SQL Server. Están
destinados al uso interno del proveedor o el controlador. No se permite llamarlos
explícitamente desde una aplicación basada en SQL Server.
La funcionalidad completa de estos procedimientos almacenados está disponible
para las aplicaciones basadas en SQL Server a través de las funciones de la API
que admiten. Por ejemplo, la funcionalidad de cursor del procedimiento almacenado
del sistema sp_cursor está disponible para las aplicaciones OLE DB a través de las
propiedades y métodos de cursor de la API de OLE DB y para las aplicaciones
ODBC a través de los atributos y funciones de cursor de ODBC.
Los siguientes procedimientos almacenados del sistema son compatibles con la funcionalidad
de cursor de ADO, OLE DB y ODBC:
sp_cursor sp_cursorclose sp_cursorexecute
sp_cursorfetch sp_cursoropen sp_cursoroption
sp_cursorprepare sp_cursorunprepare
Los siguientes procedimientos almacenados del sistema son compatibles con el modelo de
preparación o ejecución para la ejecución de instrucciones Transact-SQL en ADO, OLE DB y
ODBC:
sp_execute sp_prepare sp_unprepare
Los procedimientos almacenados sp_createorphan y sp_droporphans se utilizan
para el procesamiento de tipos de datos ntext, text e image de ODBC.
SQL Server utiliza el procedimiento almacenado sp_reset_connection para permitir
las llamadas a procedimientos almacenados remotos en una transacción. Este
procedimiento almacenado también hace que se activen los eventos Audit Login y
Audit Logout cuando se reutiliza una conexión de un grupo de conexiones.
Los procedimientos almacenados del sistema de las siguientes tablas sólo se utilizan
en una instancia de SQL Server o a través de las API cliente y no están destinados
al uso general. Están sujetos a cambios y su compatibilidad no está garantizada.
Los siguientes procedimientos almacenados están documentados en los Libros en pantalla de
SQL Server:
sp_catalogs sp_column_privileges
sp_column_privileges_ex sp_columns
sp_columns_ex sp_databases
sp_datatype_info sp_fkeys
sp_foreignkeys sp_indexes
sp_pkeys sp_primarykeys
sp_server_info sp_special_columns
sp_sproc_columns sp_statistics
sp_table_privileges sp_table_privileges_ex
sp_tables sp_tables_ex
Los siguientes procedimientos almacenados no están documentados:
sp_assemblies_rowset sp_assemblies_rowset_rmt
sp_assemblies_rowset2 sp_assembly_dependencies_rowset
sp_assembly_dependencies_rowset_rmt
sp_assembly_dependencies_rowset2
sp_bcp_dbcmptlevel sp_catalogs_rowset
sp_catalogs_rowset;2 sp_catalogs_rowset;5
sp_catalogs_rowset_rmt sp_catalogs_rowset2
sp_check_constbytable_rowset sp_check_constbytable_rowset;2
sp_check_constbytable_rowset2 sp_check_constraints_rowset
sp_check_constraints_rowset;2 sp_check_constraints_rowset2
sp_column_privileges_rowset sp_column_privileges_rowset;2
sp_column_privileges_rowset;5 sp_column_privileges_rowset_rmt
sp_column_privileges_rowset2 sp_columns_90
sp_columns_90_rowset sp_columns_90_rowset_rmt
sp_columns_90_rowset2 sp_columns_ex_90
sp_columns_rowset sp_columns_rowset;2
sp_columns_rowset;5 sp_columns_rowset_rmt
sp_columns_rowset2 sp_constr_col_usage_rowset
sp_datatype_info_90 sp_ddopen;1
sp_ddopen;10 sp_ddopen;11
sp_ddopen;12 sp_ddopen;13
sp_ddopen;2 sp_ddopen;3
sp_ddopen;4 sp_ddopen;5
sp_ddopen;6 sp_ddopen;7
sp_ddopen;8 sp_ddopen;9
sp_foreign_keys_rowset sp_foreign_keys_rowset;2
sp_foreign_keys_rowset;3 sp_foreign_keys_rowset;5
sp_foreign_keys_rowset_rmt sp_foreign_keys_rowset2
sp_foreign_keys_rowset3 sp_indexes_90_rowset
sp_indexes_90_rowset_rmt sp_indexes_90_rowset2
sp_indexes_rowset sp_indexes_rowset;2
sp_indexes_rowset;5 sp_indexes_rowset_rmt
sp_indexes_rowset2 sp_linkedservers_rowset
sp_linkedservers_rowset;2 sp_linkedservers_rowset2
sp_oledb_database sp_oledb_defdb
sp_oledb_deflang sp_oledb_language
sp_oledb_ro_usrname sp_primary_keys_rowset
sp_primary_keys_rowset;2 sp_primary_keys_rowset;3
sp_primary_keys_rowset;5 sp_primary_keys_rowset_rmt
sp_primary_keys_rowset2 sp_procedure_params_90_rowset
sp_procedure_params_90_rowset2 sp_procedure_params_rowset
sp_procedure_params_rowset;2 sp_procedure_params_rowset2
sp_procedures_rowset sp_procedures_rowset;2
sp_procedures_rowset2 sp_provider_types_90_rowset
sp_provider_types_rowset sp_schemata_rowset
sp_schemata_rowset;3 sp_special_columns_90
sp_sproc_columns_90 sp_statistics_rowset
sp_statistics_rowset;2 sp_statistics_rowset2
sp_stored_procedures sp_table_constraints_rowset
sp_table_constraints_rowset;2 sp_table_constraints_rowset2
sp_table_privileges_rowset sp_table_privileges_rowset;2
sp_table_privileges_rowset;5 sp_table_privileges_rowset_rmt
sp_table_privileges_rowset2 sp_table_statistics_rowset
sp_table_statistics_rowset;2 sp_table_statistics2_rowset
sp_tablecollations sp_tablecollations_90
sp_tables_info_90_rowset sp_tables_info_90_rowset_64
sp_tables_info_90_rowset2 sp_tables_info_90_rowset2_64
sp_tables_info_rowset sp_tables_info_rowset;2
sp_tables_info_rowset_64 sp_tables_info_rowset_64;2
sp_tables_info_rowset2 sp_tables_info_rowset2_64
sp_tables_rowset;2 sp_tables_rowset;5
sp_tables_rowset_rmt sp_tables_rowset2
sp_usertypes_rowset sp_usertypes_rowset_rmt
sp_usertypes_rowset2 sp_views_rowset
sp_views_rowset2 sp_xml_schema_rowset
sp_xml_schema_rowset2
Vea también
Referencia
CREATE PROCEDURE (Transact-SQL)
Otros recursos
Procedimientos almacenados (motor de base de datos)
Running Stored Procedures (OLE DB)
Running Stored Procedures
Ayuda e información
Obtener ayuda sobre SQL Server 2005
top related