lunes, 5 de septiembre de 2011


Procedimiento almacenado
Un procedimiento almacenado (stored procedure en inglés) es un programa (o procedimiento) el cual es almacenado físicamente en una base de datos. Su implementación varía de un gestor de bases de datos a otro. 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 sólo 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 disparadores; triggers en inglés), 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.
 Implementación
Estos procedimientos, se usan a menudo, pero no siempre, para realizar consultas SQL sobre los objetos del banco de datos de una manera abstracta, desde el punto de vista del cliente de la aplicación. Un procedimiento almacenado permite agrupar en forma exclusiva parte de algo específico que se desee realizar o, mejor dicho, el SQL apropiado para dicha acción.
Usos
Los usos 'típicos' de los procedimientos almacenados se aplican en la validación de datos, integrados dentro de la estructura del banco de datos. Los procedimientos almacenados usados con tal propósito se llaman comúnmente disparadores, o triggers. Otro uso común es la 'encapsulación' de un API para un proceso complejo o grande que podría requerir la 'ejecución' de varias consultas SQL, tales como la manipulación de un 'dataset' enorme para producir un resultado resumido.
También pueden ser usados para el control de gestión de operaciones, y ejecutar procedimientos almacenados dentro de una transacción de tal manera que las transacciones sean efectivamente transparentes para ellos.
Ventajas
La ventaja de un procedimiento almacenado, en respuesta a una petición de usuario, está directamente bajo el control del motor del manejador de bases de datos, lo cual corre generalmente en un servidor separado de manejador de bases de datos aumentando con ello, la rapidez de procesamiento de requerimientos del manejador de bases de datos. El servidor de la base de datos tiene acceso directo a los datos necesarios para manipular y sólo necesita enviar el resultado final al usuario. Los procedimientos almacenados pueden permitir que la lógica del negocio se encuentre como un API en la base de datos, que pueden simplificar la gestión de datos y reducir la necesidad de codificar la lógica en el resto de los programas cliente. Esto puede reducir la probabilidad de que los datos sean corrompidos por el uso de programas clientes defectuosos o erróneos. De este modo, el motor de base de datos puede asegurar la integridad de los datos y la consistencia, con la ayuda de procedimientos almacenados. Algunos afirman que las bases de datos deben ser utilizadas para el almacenamiento de datos solamente, y que la lógica de negocio sólo debería ser aplicada en la capa de negocio de código, a través de aplicaciones cliente que deban acceder a los datos. Sin embargo, el uso de procedimientos almacenados no se opone a la utilización de una capa de negocio.
Procedimientos almacenados en MySQL
Desde MySQL 5 los procedimientos almacenados empezaron a ser soportados, como suele suceder en MySQL las sentencias se ejecutan luego de escribir el signo punto y coma (;), por esta razón antes de escribir el procedimiento almacenado la función del punto y coma se asigna a otros caracteres usando la sentencia DELIMITER seguida de un caracter tal como |, de esta manera el procedimiento puede ser escrito usando los punto y comas sin que se ejecute mientras se escribe; después de escrito el procedimiento, se escribe nuevamente la sentencia DELIMITER ; para asignar al punto y coma su función habitual.
El siguiente es un ejemplo de procedimiento almacenado en MySQL:
DELIMITER |

CREATE PROCEDURE autos(IN velocidad INT,IN marca VARCHAR(50))
BEGIN
IF velocidad < 120 THEN
INSERT INTO familiares VALUES(velocidad,marca);
ELSE
INSERT INTO deportivos VALUES(velocidad,marca);
END IF;
END;
|
Usar un procedimiento almacenado con parámetros de entrada
SQL Server 2008 R2
Un SQL Server procedimiento almacenado al que se puede llamar es aquel que contiene uno o más parámetros IN, parámetros que se pueden usar para pasar datos al procedimiento almacenado. El controlador JDBC de Microsoft SQL Server proporciona la clase SQLServerPreparedStatement, que puede usar para llamar a este procedimiento almacenado y para procesar los datos que devuelve.
Si usa el controlador JDBC para llamar a un procedimiento almacenado con los parámetros IN, debe usar la secuencia de escape de SQL call junto con el método prepareCall de la clase SQLServerConnection. La sintaxis de la secuencia de escape call con los parámetros IN es la siguiente:
{call procedure-name[([parameter][,[parameter]]...)]}
ms378675.note(es-es,SQL.105).gifNota:
Para obtener más información acerca de las secuencias de escape de SQL, consulte Usar secuencias de escape SQL.
Al crear la secuencia de escape call , especifique los parámetros IN mediante el carácter ? (signo de interrogación). Este carácter actúa como un marcador de posición para los valores de parámetros pasados al procedimiento almacenado. Para especificar un valor de un parámetro, puede usar uno de los métodos del establecedor de la clase  SQLServerPreparedStatement. El método del establecedor que puede usar se determina mediante el tipo del parámetro IN.
Cuando pasa un valor al método establecedor, debe especificar no solo el valor real que se usará en el parámetro, sino el lugar ordinal que ocupa el parámetro en el procedimiento almacenado. Por ejemplo, si el procedimiento almacenado contiene un solo parámetro IN, su valor ordinal será 1. Si el procedimiento almacenado contiene dos parámetros, el primer valor ordinal es 1 y el segundo 2.
Como ejemplo de cómo llamar a un procedimiento que contiene un parámetro IN, use el procedimiento almacenado uspGetEmployeeManagers de la base de datos de ejemplo AdventureWorks de SQL Server 2005. Este procedimiento almacenado acepta un solo parámetro de entrada llamado EmployeeID (Id. del empleado), que es un valor entero, y devuelve una lista recursiva de empleados y sus jefes según el EmployeeID especificado. El código Java para llamar a este procedimiento almacenado es el siguiente:
public static void executeSprocInParams(Connection con) {
   try {
      PreparedStatement pstmt = con.prepareStatement("{call dbo.uspGetEmployeeManagers(?)}");
      pstmt.setInt(1, 50);
      ResultSet rs = pstmt.executeQuery();

      while (rs.next()) {
         System.out.println("EMPLOYEE:");
         System.out.println(rs.getString("LastName") + ", " + rs.getString("FirstName"));
         System.out.println("MANAGER:");
         System.out.println(rs.getString("ManagerLastName") + ", " + rs.getString("ManagerFirstName"));
         System.out.println();
      }
      rs.close();
      pstmt.close();
   }

   catch (Exception e) {
      e.printStackTrace();
    }
}
Usar un procedimiento almacenado con parámetros de salida              
SQL Server 2008 R2
Un procedimiento almacenado de SQL Server al que se puede llamar es el que devuelve uno o más parámetros OUT, que son los parámetros que el procedimiento almacenado usa para devolver los datos a la aplicación que realiza la llamada. El controlador JDBC de Microsoft SQL Server ofrece la claseSQLServerCallableStatement, que puede usar para llamar a este tipo de procedimiento almacenado y procesar los datos que devuelve.
Cuando se llama a este tipo de procedimiento almacenado con el controlador JDBC, se debe usar la secuencia de escape de SQL call junto con el método prepareCall de la clase SQLServerConnection. La sintaxis para la secuencia de escape call con parámetros OUT es la siguiente:
{call procedure-name[([parameter][,[parameter]]...)]}
ms378108.note(es-es,SQL.105).gifNota:
Para obtener más información acerca de las secuencias de escape de SQL, consulte Usar secuencias de escape SQL.
Al crear la secuencia de escape call , especifique los parámetros OUT mediante el carácter ? (signo de interrogación). Este carácter actúa como un marcador de posición para los valores de parámetros devueltos por el procedimiento almacenado. Para especificar un valor para un parámetro OUT, debe especificar el tipo de datos de cada parámetro mediante el método registerOutParameter de la clase SQLServerCallableStatement antes de ejecutar el procedimiento almacenado.
El valor especificado para el parámetro OUT en el método registerOutParameter debe ser uno de los tipos de datos JDBC incluidos en java.sql.Types, que se asigna a su vez a uno de los tipos de datos de SQL Server nativos. Para obtener más información acerca de los tipos de datos JDBC y de SQL Server, consulteDescribir los tipos de datos del controlador JDBC.
Cuando pasa un valor al método registerOutParameter para un parámetro OUT, debe especificar no solo los tipos de datos usados para el parámetro, sino también la posición ordinal del parámetro o el nombre del mismo en el procedimiento almacenado. Por ejemplo, si el procedimiento almacenado contiene un solo parámetro OUT, su valor ordinal es 1 y, si el procedimiento almacenado contiene dos parámetros, el primer valor ordinal es 1 y el segundo 2.
ms378108.note(es-es,SQL.105).gifNota:
El controlador JDBC no admite el uso de los tipos de datos CURSOR, SQLVARIANT, TABLE y TIMESTAMP SQL Server como parámetros OUT.
Cree, a modo de ejemplo, el siguiente procedimiento almacenado en la base de datos de ejemplo AdventureWorks de SQL Server 2005:
CREATE PROCEDURE GetImmediateManager
   @employeeID INT,
   @managerID INT OUTPUT
AS
BEGIN
   SELECT @managerID = ManagerID
   FROM HumanResources.Employee
   WHERE EmployeeID = @employeeID
END
Este procedimiento almacenado devuelve un solo parámetro OUT (managerID), que es un entero, en función del parámetro IN (employeeID) especificado, que también es un entero. El valor devuelto en el parámetro OUT es ManagerID en función de EmployeeID en la tabla HumanResources.Employee.
En el siguiente ejemplo, se pasa una conexión abierta a la base de datos de ejemplo AdventureWorks a la función y se usa el método execute para llamar al procedimiento almacenado GetImmediateManager:
public static void executeStoredProcedure(Connection con) {
   try {
      CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}");
      cstmt.setInt(1, 5);
      cstmt.registerOutParameter(2, java.sql.Types.INTEGER);
      cstmt.execute();
      System.out.println("MANAGER ID: " + cstmt.getInt(2));
   }
   catch (Exception e) {
      e.printStackTrace();
   }
}
Este ejemplo utiliza las posiciones ordinales para identificar los parámetros. También puede identificar un parámetro utilizando su nombre en lugar de su posición ordinal. En el ejemplo de código siguiente se modifica el ejemplo anterior para demostrar cómo utilizar los parámetros con nombre en una aplicación Java. Observe que los nombres de parámetros se corresponden con los nombres de parámetros en la definición del procedimiento almacenado:
public static void executeStoredProcedure(Connection con) {
   try {
      CallableStatement cstmt = con.prepareCall("{call dbo.GetImmediateManager(?, ?)}");
      cstmt.setInt("employeeID", 5);
      cstmt.registerOutParameter("managerID", java.sql.Types.INTEGER);
      cstmt.execute();
      System.out.println("MANAGER ID: " + cstmt.getInt("managerID"));
      cstmt.close();
   }
   catch (Exception e) {
      e.printStackTrace();
   }
}
ms378108.note(es-es,SQL.105).gifNota:
En estos ejemplos se usa el método execute de la clase SQLServerCallableStatement para ejecutar el procedimiento almacenado. Se usa dicho método porque el procedimiento almacenado no ha devuelto ningún conjunto de resultados. En caso contrario, se usaría el método executeQuery.
Los procedimientos almacenados también pueden devolver recuentos de actualizaciones y múltiples conjuntos de resultados. El controlador JDBC de Microsoft SQL Server sigue la especificación de JDBC 3.0, que indica que se deben recuperar varios conjuntos de resultados y actualizaciones antes de que se recuperen los parámetros OUT. Es decir, la aplicación debería recuperar todos los objetos ResultSet y recuentos de actualizaciones antes de recuperar los parámetros OUT con los métodos CallableStatement.getter. De lo contrario, los objetos ResultSet y recuentos de actualizaciones que aún no se hayan recuperado se perderán cuando se recuperen los parámetros OUT. Para obtener más información acerca de los recuentos de actualizaciones y los conjuntos de resultados múltiples, veaUsar un procedimiento almacenado con un recuento de actualizaciones y Usar múltiples conjuntos de resultados.


viernes, 2 de septiembre de 2011

EJERCICIOS

EJERCICIOS

--1. Listar todos los funcionarios. 
SELECT F.*
FROM FUNCIONARIO F


--2. Listar las unidades que tengan el texto "EDUCACIÓN" en su descripción. 
SELECT *
FROM UNIDAD
WHERE descripcion like '%EDUCACION%'


--3. Listar el código del funcionario que tiene como nombre: "LUISA REYES". 
SELECT ITEM
FROM FUNCIONARIO
WHERE NOMBRE='LUISA REYES'


--4. Listar todos los distritos. 
SELECT * FROM DISTRITO


--5. Listar los proyectos que se iniciaron en fecha "03-30-2010". 
SELECT *
FROM PROYECTO
WHERE FECHAINICIO=2010-03-30


--6. Listar los distritos que tengan el texto "CALIDAD DE VIDA MEDIA". 
SELECT *
FROM DISTRITO
WHERE DESCRIPCION LIKE'%CALIDAD DE VIDA MEDIA%'


--7. Listar los ítems de funcionarios cuyos teléfonos se inicie con “732”. 
SELECT ITEM
FROM  TELEFONOF  
WHERE NROTELEFONO LIKE '732_____'


--8. Listar los proyectos cuyo código termine con “1?”.
SELECT *
FROM PROYECTO
WHERE CODP LIKE '%1'


--9. Listar los proyectos cuyo carnet empiece con “0000”.
SELECT *
FROM PROYECTO
WHERE CODP LIKE '0000%'


--10. Listar todas las unidades.


SELECT *
FROM UNIDAD


--11. Determinar la cantidad de pasos que siguió el proyecto  “000006” 
SELECT COUNT(*)
FROM ADJUDICACION 
WHERE CODPROY='000006'


--12. Determinar la cantidad de documentos con extension “aplicable” 
SELECT COUNT(*)
FROM DOCUMENTO
WHERE EXTENCION='APLICABLE'


--13. Determinar la cantidad de documentos tipo “Minuta Descriptiva” y extension “aplicable” 
SELECT COUNT(*)
FROM DOCUMENTO
WHERE TIPO_CONTENIDO='MINUTA DESCRIPTIVA'AND EXTENCION='MINUTA DESCRIPIVA'


--14. Listar todos los proyectos que se iniciaron a partir del ‘20/12/1990’
SELECT *
FROM PROYECTO 
WHERE FECHAINICIO>=1990-07-01


--15. Listar todos los documentos correspondientes al proyecto ‘000009’
SELECT D.*
FROM DOCUMENTO D INNER JOIN SEGUIMIENTO S ON CODD=CODDOC
WHERE S.CODPROY='000009'


--16. Cuantos y cuales son pasos en los que intervino el funcionario 146?.
SELECT count (*)
FROM SEGUIMIENTO s
WHERE s.ITEM=146


--17. Quién es el funcionario 104? 
SELECT NOMBRE
FROM FUNCIONARIO
WHERE ITEM=104


--18. Cuántos registros tiene la tabla unidad?
SELECT COUNT(*)
FROM UNIDAD


--19. El remanente del proyecto ‘000005’ esta correcto?
SELECT REMANENTE
FROM PRESUPUESTO
WHERE CODPROY='000005'


--20. Cuánto se presupuesto en todos los proyectos?
SELECT SUM(COSTOINI+COSTOFIN)
FROM PRESUPUESTO


--21. Cuántos proyectos se llevan a cabo en el distrito 0006? (4 filas)
SELECT COUNT(*)
FROM DIST_PROY
WHERE NRODIST='0006'


--22. Cuántos distritos son del tipo ‘CALIDAD DE VIDA BAJA’?
SELECT COUNT(*)
FROM DISTRITO
WHERE DESCRIPCION='CALIDAD DE VIDA BAJA'


--23. Mostrar los proyectos que se adjudico la empresa ‘Coca Cola’
SELECT DISTINCT P.*
FROM EMPRESA E,ADJUDICACION A,PROYECTO P
WHERE E.NOMBRE='COCA-COLA'


--24. Determinar el monto entre todos los proyectos adjudicados por la empresa ‘000008’?
SELECT SUM(PR.COSTOINI+PR.COSTOFIN)
FROM ADJUDICACION A,PROYECTO P,PRESUPUESTO PR
WHERE  A.NIT='000008'


--25. Cuántos son los proyectos presupuestados con mas de 15.000Bs? 
SELECT COUNT(*)
FROM PRESUPUESTO 
WHERE  COSTOINI+COSTOFIN>=15000


--26. Cuántos son los proyectos financiados por el Banco Mundial u ONG? 
SELECT COUNT(*)
FROM EMPRESA E,ADJUDICACION A
WHERE E.NOMBRE='BANCO MUNDIAL' OR E.NOMBRE='ONG'


--27. Mostrar los proyectos financiados por la empresa ‘SOBOCE’? 
SELECT DISTINCT P.*
FROM EMPRESA E,ADJUDICACION A,PROYECTO P
WHERE E.NOMBRE='SOBOCE'


--28. Determinar los proyectos con monto superior a 20.000 de costo inicial?
SELECT DISTINCT PROY.*
FROM PROYECTO PROY,PRESUPUESTO P
WHERE P.COSTOINI>=20000


--29. Determinar la cantidad de funcionarios de la unidad ’cobranzas’?
SELECT COUNT(*)
FROM FUNCIONARIO
WHERE NOMBREU='COBRANZAS'


--30. Mostrar la unidad en la que se encuentra el funcionario ‘MENDEZ PRIETO VICTOR’?
SELECT NOMBREU
FROM FUNCIONARIO
WHERE NOMBRE='MENDEZ PRIETO VICTOR'


--31. Determinar el numero de usuarios cuyo idUsuario empieza con el carácter ‘M’?
SELECT COUNT(*)
FROM USUARIO
WHERE IDUSUARIO LIKE 'M%'


--32. Determinar la cantidad de teléfonos del funcionario104? 
SELECT COUNT(*)
FROM TELEFONOF
WHERE ITEM=104


--33. Mostrar los números de teléfono de la empresa 524413?
SELECT NROTELEFONO
FROM TELEFONOE
WHERE NIT=524413