1 SQL en Entorno de Programación. 2 Motivación: SQL Interactivo vs. No Interactivo Hasta la fecha hemos considerado sólo consultas SQL en las que tecleamos.

Slides:



Advertisements
Presentaciones similares
FUNDAMENTALS OF THE JAVA PROGRAMMING LANGUAGE
Advertisements

Diseño de Bases de Datos
Acceso a Bases de Datos con Java
integridad referencial
BASE DE DATOS OBJETO RELACIONAL
PHP: Acceso a Bases de Datos
Acceso a bases de datos con MySQL y ODBC desde PHP
Acceso a bases de datos MySQL en PHP
Desarrollo de Aplicaciones para Internet
UNIVERSIDAD NACIONAL DE LOJA Carrera de Ingeniería en Sistemas
Conexión a Base de Datos con NetBeans
ACCESO A BASES DE DATOS ORACLE CON PHP
Programador en Plataforma Java y XML
Lenguaje de consulta de Hibernate
UNIVERSIDAD LATINA (UNILA) VI.- ARCHIVOS Y BASES DE DATOS
UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO
Francisco Moreno Bases de Datos II Universidad Nacional
PL/SQL Francisco Moreno Universidad Nacional.
Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2.
Envolviendo la API de Firebird/Interbase CoNaIISI 2013 UTN FRC Mg. Guillermo Cherencio.
4.3. Privilegios de usuarios
TECNOLOGÍA IDC Internet Database Connector Trinitario Gómez López.
Tema 3 J2EE Java Database Connectivity Temas Selectos de Cómputo Grupo 912.
Taller 5: Trabajo con Plantillas y uso de tecnología Ajax.
Funciones en lenguaje C
CI TEORIA semana 8 Subprogramas o funciones Definición de funciones.
PL/SQL Francisco Moreno Universidad Nacional.
Tema 6: Clases Antonio J. Sierra.
CURSORES Preparó: Ismael Castañeda Fuentes Fuentes: Manuales Sybase
MySQL M.C. Pedro Bello López.
16/04/ Sesión 11 Funciones y procedimientos Ing. Ricardo Inquilla.
Semana 5 Subprogramas..
PL/SQL Francisco Moreno Universidad Nacional.
D Copyright © 2010, Oracle y/o sus filiales. Todos los derechos reservados. Uso de SQL*Plus.
PL/SQL Francisco Moreno Universidad Nacional.
Archivos.
Ing. Ricardo Carlos Inquilla Quispe
Bases de datos en la Web n Las bases de datos permiten almacenar de una forma estructurada y eficiente toda la información de un sitio web n Ventajas –Proporcionar.
Componentes sintácticos
Una base de datos es un “almacén” que nos permite guardar grandes cantidades de información de forma organizada para que luego podamos encontrar y utilizar.
John Freddy Duitama M.U.de.A. Facultad de Ingeniería. Creación del esquema de Una Base de Datos. John Freddy Duitama Muñoz. Facultad de Ingeniería. U.de.A.
1 Asignación Dinámica de Memoria Agustín J. González Versión original de Kip Irvine ELO 329.
Aprenda MySQL en 120 minutos Tutorial. Dirigido a...
Diseñando la arquitectura de aplicaciones empresariales. Acceso al SQL Server.- Autenticación de usuario:
Fernando Alonso Nicolás Serrano Acceso a Bases de Datos con Java JDBC 01 de Abril de 2008.
ATAQUES POR INYECCION DE CODIGO SQL
JDBC Java Database Connectivity CC52N - Computación para el trabajo grupal Profesor: Nélson Baloian Por: Edgard Pineda.
Programación en C para electrónicos
Java Data Base Connectivity
Universidad de Chile - Tupper 2007, Santiago - Fono/Fax: (56 2) cec.uchile.cl Módulo ECI - 11: Fundamentos de Redes de Computadores.
Introducción al Lenguaje. ¿ Qué es PHP ? O Hypertext Pre-processoes (PHP) es un lenguaje de "código abierto" interpretado, de alto nivel, embebido en.
COLEGIO DE BACHILLERES PLANTEL 13 XOCHIMILCO-TEPEPAN MATERIA:TIC EQUIPO:21 PRESENTACION: BASE DE DATOS ALUMNAS: Adán Millán Sánchez.
CARACTERÍSTICAS Es un lenguaje de programación estructurado de propósito general. Está estrechamente asociado al sistema operativo UNIX, ya que el propio.
Lenguaje Estructurado de Consulta
Visual Basic FUNCIONES Y PROCEDIMIENTOS
INTRODUCCION A LA PROGRAMACION
Manual violento de Navicat
Se producen cuando una aplicación recibe datos no confiables y estos no han sido validados adecuadamente antes de procesarlos, lo cual puede llevar a que.
Tema 11 Bases de Datos y el Lenguaje SQL
Práctica Profesional PHP.
SQL (Structured Query Language) Lenguaje orientado a bases de datos y sobre todo, al manejo de consultas; el objetivo principal de SQL es la realización.
SQL es un estándar internacional para trabajar con bases de datos, que consta de dos partes: una parte para manipular datos y una parte para definir tipos.
JDBC. Definición Java Database Conectivity El acceso a bases de datos JDBC implica abrir una conexión ejecutar comandos SQL en un sentencia procesar los.
MEMORIA DINÁMICA.
DLM Transact SQL Sesión I Introducción al SQL Server Uso de las herramientas de consultas del Transact SQL.
Estructuras de control selectivas Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos Versión Práctica 3.
3 Cursores ORACLE Bases de datos II I-2014 Universidad del Cauca In. Wilson Ortega Bases de datos II I-2014 Universidad del Cauca In. Wilson Ortega.
Base de Datos I – Ing. Mary Carlota Bernal J.  Cada instrucción PL/SQL tiene asociado internamente un cursor  Los cursores en PL/SQL pueden ser de dos.
DML Transact SQL Sesión X Triggers. Duración 2 Horas.
Transcripción de la presentación:

1 SQL en Entorno de Programación

2 Motivación: SQL Interactivo vs. No Interactivo Hasta la fecha hemos considerado sólo consultas SQL en las que tecleamos en “psql” o “pgaccess” las ordenes que deseamos ejecutar. Esto se conoce como SQL Interactivo. SQL interactivo es ideal para: –Definir la estructura de la base de datos –Probar consultas –realizar prototipos El SQL interactivo no es una buena solución para la mayoría de las aplicaciones “reales” que requieren un interfaz con un usuario sin conocimientos de SQL. Para las cuales se necesita, además de SQL, un lenguaje de programación de alto nivel.

3 Más motivación (2,5 puntos) Diseñar razonadamente una base de datos (diagrama entidad...no redundante… (2,5 puntos) Dar razonadamente consultas en el álgebra relacional y en SQL que permitan obtener… (2,5 puntos) Dar razonadamente una función en C void f()…

4 Posibles formas de Conexión con la base de datos Embedded SQL Library (database API): ODBC (database independent, complex), JDBC (slow),...

5 SQL embebido Los comandos SQL deben seguir una sintaxis especial que los "aísla" del resto de las ordenes del programa – EXEC SQL SQL_statement Un precompilador se encargará de procesar estas ordenes y trasladarlas a llamadas a una librería (que se encarga de las comunicaciones). ecpg Finalmente el compilador nativo compila el programa. gcc

6 Precompilador SQL Editor Precompilador Compilador Lincador Programa “nativo” + SQL embebido Programa “nativo” + SQL traducido (ecpg)‏ Código objeto Librerías nativas Librerías DDBB Ejecutable

7 Un ejemplo rollback and commit Preprocesador para C y SQL embebido (ECPG)‏ #include /* Esta zona se descibirá más adelante */ EXEC SQL BEGIN DECLARE SECTION; int resultado; EXEC SQL END DECLARE SECTION; int main() { EXEC SQL CONNECT TO peliculas; EXEC SQL SELECT (1+1) INTO :resultado; printf("1+1=%d\n",resultado); return 0; } /* /home/roberto/Docencia/DDBB/SQL-Prog/Prog_2 /*/ /*ecpg 297.pgc -o 297.c; vi 297.c */ /*make -f 297.mak -n*/

8 Compartir Variables Es posible compartir variables entre el código SQL y el nativo. La definición se realiza usando la sintaxis: EXEC SQL begin declare section; varchar userid[ 10], password[ 10], cname[ 15]; int cno; EXEC SQL end declare section; Declaration section-> variables compartidas por SQL y lenguaje nativo ":" se antepone a las variables cuando se usan en SQL

9 Compartir variables: un ejemplo Declaration section-> variables compartidas por SQL y lenguaje nativo ":" se antepone a las variables cuando se usan en SQL EXEC SQL BEGIN DECLARE SECTION ; unsigned long num_enrolled; char crs_code; char SQLSTATE [6]; EXEC SQL END DECLARE SECTION ; ………. EXEC SQL SELECT C.NumEnrolled INTO :num_enrolled Course FROM Course AS C WHERE C.CrsCode = :crs_code; Variables compartidas “:” se usa para las variables en SQL

10 NULL SQL trata el “valor” NULL de forma muy especial que no es directamente exportable a otros lenguajes de programación. Hay unas variables llamadas “variables indicadoras” que contienen un código que “matiza” los valores devueltos por la base de datos: – 0 el valor de la variable “nativa” es correcto. – -1 el valor de la variable “nativa” debe tratarse como si fuera NULL. Su valor es irrelevante. –>0 el valor de la variable “nativa” ha sido procesado (probablemente un casting que ha producido una truncación o redondeo)‏ null jdbc> wasNull

11 Variables Indicadoras: Ejemplo EXEC SQL BEGIN DECLARE SECTION; charaddress[51]; short addressInd; EXEC SQL END DECLARE SECTION; addressInd = -1; EXEC SQL UPDATE PrivateOwner SET address = :address:addressInd WHERE ownerNo = ‘CO21'; 2 byte int Se sitúan inmediatamente después de la variable que “matizan”. address=NULL!!!

12 Ejemplo!!! saltarse clave primaria #include //create table pepinillo(id int,color text); //psql peliculas int main() ‏ { EXEC SQL BEGIN DECLARE SECTION; char resultado [11]; int resultadoInd ; EXEC SQL END DECLARE SECTION; //las variables indicadoras funcionan en las dos direcciones EXEC SQL CONNECT TO peliculas; resultadoInd = -1; strcpy( resultado,"rojo"); EXEC SQL INSERT INTO pepinillo (id,color) VALUES (1,:resultado:resultadoInd ); return 0; }//297b.pgc

13 Conexión Hasta la fecha hemos usado: EXEC SQL CONNECT TO peliculas; para conectarnos Obviamente faltan campos para: –usuario –password –servidor (dirección IP)‏ –puerto… En JDBC hay que especificar siempre la direccion

14 Ejemplo #include EXEC SQL INCLUDE sqlca; EXEC SQL BEGIN DECLARE SECTION; int resultado ; EXEC SQL END DECLARE SECTION; int main() ‏ { EXEC SQL CONNECT TO USER roberto/pepino; if (sqlca.sqlcode) ‏ {printf("%s\n", sqlca.sqlerrm.sqlerrmc); exit(1); } EXEC SQL SELECT (1+1) INTO :resultado ; printf("1+1=%d\n", resultado ); return 0; }

15 Errores Se puede acceder a la base de datos para conocer su estado (¿Ha habido algún error durante la ejecución? EXEC SQL include sqlca; El elemento más interesante de la estructura sqlca es sqlcode. El –0 consulta correcta. –>0 la consulta se ha realizado satisfactoriamente pero ha ocurrido una excepción (por ejemplo no hay más tuplas disponibles)‏ –< 0 ha ocurrido un error

16 Errores #include EXEC SQL INCLUDE sqlca; EXEC SQL BEGIN DECLARE SECTION; int resultado; EXEC SQL END DECLARE SECTION; int main() { EXEC SQL CONNECT TO basequenoexiste; if (sqlca.sqlcode)‏ {printf("Error: No puedo conectar a la base (%d)\n", sqlca.sqlcode); exit(1); } EXEC SQL SELECT (1+1) INTO :resultado; printf("1+1=%d\n",resultado); return 0; } /*300*/

17 Códigos de Error struct { char sqlcaid[8]; long sqlabc; long sqlcode; struct {int sqlerrml; char sqlerrmc[70];} sqlerrm; char sqlerrp[8]; long sqlerrd[6]; char sqlwarn[8]; char sqlstate[5]; } sqlca; ______________________________________________ ver 300.c; sqlca esta comentado ahí

18 WHENEVER Cada comando de SQL embebido puede (potencialmente) generar un error. Para aliviar el trabajo del programador existe la directiva WHENEVER que instruye al precompilador para que genere el código que procesará los errores La sintaxis de la directiva WHENEVER es: EXEC SQL WHENEVER

19 WHENEVER (cont)‏ La condición puede ser: –SQLERROR - genera código que se encargue de los errores (SQLCODE < 0). –SQLWARNING – genera codigo que se encarge de las advertencias (warnings) (SQLCODE > 0)‏ –NOT FOUND - genera código que se encargue del caso especial en que todas las tuplas obtenidas como resultado de la consulta ya se han transferido. –sqlprint – imprime mensaje de error

20 WHENEVER (CONT)‏ La acción puede ser: CONTINUE – ignora el error y continua la ejecución función – transfiere el error a la funcion que se encarga de procesar los error. DO BREAK – salte del bucle DO CONTINUE – continua con la interación siguiente (se supone dentro de un bucle) GOTO label - transfiere el control a otra parte del programa. STOP – Aborta transacción. SQLPRINT – imprime codigo error

21 WHENEVER: Ejemplo!!! #include int main() ‏ { EXEC SQL BEGIN DECLARE SECTION; int resultadoInd ; EXEC SQL END DECLARE SECTION; EXEC SQL CONNECT TO peliculas; EXEC SQL WHENEVER sqlerror sqlprint; // DO BREAK //STOP EXEC SQL INSERT INTO tablaquenoexiste (id,color) VALUES (1,2); printf(“El programa no ha abortado tras hacer sqlprint”); return 0; }//297c.pgc

22 SELECT SELECT es un comando de SQL potencialmente complicado de usar. Problema: los lenguajes de programación tradicionales están concebidos para procesar variables aisladas y no grandes tablas de dimensión virtualmente infinita SQL, por el contrario, puede procesar una gran cantidad de filas con un solo comando Aquellos SELECTs que devuelvan 0 o una tupla son fácilmente procesables pero... ¿qué hacer cuando ‘n’ tuplas son devueltas?

23 SELECT – Devuelve una sola tupla EXEC SQL SELECT fName, lName, address INTO :firstName, :lastName, :address:addressInd, FROM PrivateOwner WHERE ownerNo = ‘CO21'; Si se devuelve más de una tupla solo la primera de ellas es retenida ¿Sabrías escribir el código necesario para poder compilar el programa?

24 Cursores Si una consulta puede devolver un número arbitrario de tuplas, es necesario usar cursores. Los cursores permiten al lenguaje “nativo” acceder a una relación tupla a tupla. Los cursores se comportan como punteros a una tupla del resultado y pueden ser movidos de una tupla a la siguiente (se puede saltar hacia atrás y delante). Los cursores se deben declarar y “abrir” antes de que puedan ser usados. Una vez abiertos el comando fetch permite avanzar hasta la siguiente tupla

25 CURSOR - Ejemplo Flåklypa Grand Prix High and the Mighty, The votospuntuaciontítulo Consideremos la consulta: SELECT titulo, puntuacion,votos FROM pelicula WHERE puntuacion > 9.4;

26 Cursor: Declaración hacer paso a paso Los cursores se declara usando las palabras reservadas: – DECLARE CURSOR...CURSOR FOR –el nombre del cursor –y la consulta a realizar EXEC SQL DECLARE miprimercursor CURSOR FOR SELECT titulo, puntuación, votos FROM pelicula WHERE puntuacion > 9.4;

27 Cursors - OPEN La orden OPEN ejecuta la consulta y coloca un puntero apuntando hacia la primera tupla de la relación resultante EXEC SQL OPEN miprimercursor; Pointer Flåklypa Grand Prix High and the Mighty, The

28 Cursores - FETCH FETCH devuelve la siguiente tupla en la relación resultante de nuestra consulta y la coloca en una variable accesible por el lenguaje nativo EXEC SQL FETCH miprimercursor INTO :titulo, :puntuación, :votos FETCH se coloca normalmente dentro de un bucle que itera hasta que no se devuelven más filas. Esto es, SQLCODE es NOT FOUND.

29 Cursores: FETCH EXEC SQL WHENEVER NOT FOUND DO BREAK; while(1) { EXEC SQL FETCH miprimercursor INTO :titulo, :puntuación, :votos ; //MAS CODIGO AQUI } Fetch 1 Fetch Flåklypa Grand Prix High and the Mighty, The

30 CURSOR - CLOSE La orden CLOSE “cierra” el cursor activo. EXEC SQL CLOSE miprimercursor;

31 Un ejemplo de todo junto #include EXEC SQL INCLUDE sqlca; EXEC SQL BEGIN DECLARE SECTION; char titulo[256]; float fPuntuacion; int votos; char miquery[256]; EXEC SQL END DECLARE SECTION; EXEC SQL WHENEVER SQLERROR sqlprint; int main()‏ { // conectarse EXEC SQL CONNECT TO peliculas; if (sqlca.sqlcode)‏ {printf("Error: No puedo conectar a la base (%d)\n", sqlca.sqlcode); exit(1); }

32 // declara cursor EXEC SQL DECLARE micursor CURSOR FOR SELECT titulo, puntuacion, votos FROM pelicula WHERE puntuacion > 9.4; EXEC SQL OPEN micursor; EXEC SQL WHENEVER NOT FOUND DO BREAK; while (1)‏ { EXEC SQL FETCH IN micursor INTO :titulo, :fPuntuacion, :votos; printf("%s %f %d\n",titulo, fPuntuacion, votos); } EXEC SQL DISCONNECT; return 0; } //312.pgc

33 Modificar datos usando cursores Los cursores pueden ser declarados como “READ ONLY” o “UPDATE” Aquellos declarados como “UPDATE” pueden ser usados para modificar o borrar tuplas “READ ONLY” es la opción por defecto, para declarar un cursor que será usado para modificar la relación usese la sintaxis: EXEC SQL DECLARE misegundocursor CURSOR FOR SELECT titulo, puntuacion, votos FROM peliculas WHERE puntuacion < 5 FOR UPDATE OF titulo,puntuacion,votos;

34 Ejemplo: modificar relaciones usando cursores #include EXEC SQL INCLUDE sqlca; #define CHECKERR (CE_STR) if (sqlca.sqlcode != 0) {printf("%s failed. Reason %ld\n", CE_STR, sqlca.sqlcode); exit(1); } EXEC SQL WHENEVER SQLERROR sqlprint; int main() { EXEC SQL BEGIN DECLARE SECTION; char titulo[256]; float fPuntuacion; int votos; char miquery[256]; EXEC SQL END DECLARE SECTION; EXEC SQL CONNECT TO peliculas; CHECKERR ("CONNECT TO peliculas");

35 Ejemplo: modificar relaciones usando cursores-II /* Maniaco de Star Trek */ //LOCK table IN exclusive mode; EXEC SQL DECLARE micursor CURSOR FOR SELECT puntuacion, votos FROM pelicula WHERE titulo LIKE 'Star Trek%' FOR UPDATE OF puntuacion,votos; EXEC SQL OPEN micursor; CHECKERR ("OPEN CURSOR"); do { EXEC SQL FETCH micursor INTO :fPuntuacion, :votos; printf("%f %d\n",fPuntuacion,votos); if (SQLCODE != 0) break; if(fPuntuacion < 99999){ EXEC SQL UPDATE pelicula SET puntuacion = , votos = ; CHECKERR ("UPDATE pelicula"); } } while ( 1 ); EXEC SQL CLOSE micursor; EXEC SQL commit; } /* end of program 326 */

36 SQL Dinámico vs Estático Hasta el momento hemos visto SQL (embebido) estático SQL estático es, posiblemente, la formula más popular de programar con SQL pero sólo en usable si se conoce las consultas que una aplicación va a hacer durante la fase de diseño de la aplicación. Su principal limitación es que no permite decidir en tiempo real a que tablas o atributos (u otros objetos) nos queremos referir. Esto es: con SQL estático puedes decidir que valor va a tener un atributo en tiempo real pero no que atributo vas a cambiar (o a que base de datos vas a acceder)‏

37 EXECUTE IMMEDATELY La forma más sencilla de ejecutar una sentencia arbitraria en SQL consiste en usar la orden EXECUTE IMMEDIATE : EXEC SQL EXECUTE IMMEDIATE [cadena_con_la_consulta] Por ejemplo: EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "CREATE TABLE test1(...);"; EXEC SQL END DECLARE SECTION; EXEC SQL EXECUTE IMMEDIATE :stmt; No se pueden ejecutar sentencias que devuelvan datos de esta manera. (SELECT no esta permitido pero INSERT o UPDATE son posibles)‏

38 Ejemplo #include int main()‏ { EXEC SQL BEGIN DECLARE SECTION; char resultado[11]; int resultadoInd; EXEC SQL END DECLARE SECTION; EXEC SQL CONNECT TO peliculas; //Dos Declare secction estilo c++ EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "CREATE TABLE test1 (i int, f float);"; EXEC SQL END DECLARE SECTION; EXEC SQL EXECUTE IMMEDIATE :stmt; EXEC SQL COMMIT; return 0; }//immediate

39 PREPARE y EXECUTE La base de datos tiene que analizar, validar y optimizar cada sentencia SQL de tipo “EXECUTE IMMEDIATE”. Si se planea utilizar repetidamente la misma sentencia (o variantes parametrizadas de la misma) entonces combiene “preparar” las consultas previamente de forma que la validación, optimización y analisis se realice una única vez por “familia” de consultas. SQL dinámico cuenta con las intrucciones: PREPARE y EXECUTE para realizar esta tarea

40 Immediate vs Prepare/Execute

41 int main() {/*No se comprueban errores para ahorrar espacio*/ EXEC SQL BEGIN DECLARE SECTION; char dbname[64] = “peliculas”; char sql_string[1000]; int i; float f; EXEC SQL END DECLARE SECTION; /* Conectarse a la base de datos*/ EXEC SQL CONNECT TO :dbname; /*EXEC SQL SET AUTOCOMMIT TO ON; */ /* Preparara la orden INSERT */ strcpy(sql_string, "INSERT INTO test1 VALUES(?, ?)"); EXEC SQL PREPARE prep_ins FROM :sql_string; /* Insertar varias tuplas (en una sola transaccion*/ EXEC SQL BEGIN; for(i = 0; i < 3; i++) { switch(i) { case 0: f=0.; break; case 1: f=1.; break; case 2: f=2.; break; } EXEC SQL EXECUTE prep_ins USING :i, :f; } EXEC SQL COMMIT; } //400.pgc

42 falta ejemplo prepare execute con cursores

Use declare and prepare // first declare some variables EXEC SQL BEGIN DECLARE SECTION; char *stmt;const char *input; int num; EXEC SQL END DECLARE SECTION; // now construct your search query. This has to be stored in a non const char*. In this example I don't show any fancy construction code. stmt=strdup("select nr from table where name=?"); // prepare the cursor EXEC SQL PREPARE search FROM :stmt; EXEC SQL DECLARE curs SCROLL CURSOR FOR search;EXEC SQL OPEN curs USING :input;// now loop over our resultsEXEC SQL WHENEVER NOT FOUND DO break;while(true){ EXEC SQL FETCH NEXT FROM curs INTO :num; // do whatever need to be done with "num"}EXEC SQL CLOSE curs;EXEC SQL DEALLOCATE PREPARE search;free(stmt);

CREATE RULE update_grupo_46 AS ON UPDATE TO introducir_notas_teoria_grupo_46 DO INSTEAD UPDATE notas_teoria_46 SET parcial = new.parcial, febrero = new.febrero, septiembre = new.septiembre, nota_teoria = new.nota_teoria, nota_acta = new.nota_acta, aux1 = new.aux1, aux2 = new.aux2 WHERE (notas_teoria_46.dni = old.dni);

45 APIs para las bases de datos Hasta ahora hemos mencionado distintos métodos para “embeber” SQL en lenguajes de programación de alto nivel. (Con la excepción de JDBC) Normalmente todos las empresas que mantienen sistemas de bases de datos ofrecen APIs. De esta forma en lugar de “embeber” SQL los programadores tienen acceso a un conjunto de librerías que les permiten comunicarse con la base de datos.

46 Open Database Connectivity (ODBC)‏ Las distintas APIs desarrolladas por los diferentes vendedores representan un problema para los desarrolladores de aplicaciones ya que les fuerzan a rescribir el código para cada base de datos Entre las muchas estandarizaciones propuestas ODBC (originalmente propuesta por Microsoft) es uno de los estándares de facto. Probablemente el estándar que “es soportado” por más lenguajes y aplicaciones ODBC asume que las bases están basadas en SQL estandard.

47 Open Database Connectivity (ODBC)‏ ODBC (escrito en ‘C’) permite conectarse a las diversas bases de datos usando el mismo código y sin necesidad de recompilar. java -Djdbc.drivers=org.mysql.Driver myaplicacion Por lo tanto permite al desarrollador crear programas que no estén orientados hacia una base de datos en concreto. Se precisa de un driver (suministrado por la empresa que desarrolla el sistema de bases de datos) que hace de enlace entre el driver manager y la base de datos.

48 Ventajas de usar ODBC La aplicacion no depende de un API nativo (de una base de datos en particular). La aplicación puede ignorar las comunicaciones cliente servidor. Hay drivers que siguen el estandar ODBC para virtualmente cualquier lenguaje y cualquier sistema de bases de datos. Así pues una aplicación escrita con ODBC puede conectarse a virtualmente cualquier base de datos

49 ODBC: Arquitectura ODBC tiene cuatro componentes principales: –Aplicación –Driver Manager (parte del sistema operativo en windows)‏ –Driver –Base de Datos.

50 ODBC Architecture Applicacion – procesa los datos y realiza llamadas a funciones ODBC para emviar sentencias SQL o recibir datos de la BBDD Driver Manager – maneja los drivers “en representación” de la aplicación. Datos- Driver – procesan las llamadas a funciones ODBC, embian el as consultas SQL y recogen los resultados Los drivers pueden modificar las consultas para que se adecuen a la sintaxis que espera la base de datos.

51 ODBC: Limitaciones Las principales son: –Más lento que las alternativas usando drivers ‘nativos’ o SQL embebido –ODBC no puede explotar todas las funciones disponibles en la base de datos.

52 Conexión desde Access ip: base: peliculas username: roberto pasword: pepino port: 5432

53 Conexión desde Ooffice un interludio unixODBC cat /etc/odbcpsql.ini cat $HOME/.odbc.ini isql testodbc2 roberto pepino Tools -> Data Sources Data -> DataPilot -> Start –View -> DataSource -> Tables –Left click application->ODBC-Manager->odbc.ini- >odbcinst.ini->driver->database

54 ODBC: Fuentes de sabiduría

55 Ejemplo initializate.h #include SQLCHAR DSN[10] = "testodbc2"; // The following should be changed to your userid and password // and the length of the variable should be the actual length + 1 SQLCHAR DSN_userid[9] = "roberto"; SQLCHAR DSN_password[9] = "pepino"; int Initialize(HENV * phenv, HDBC * phdbc, HSTMT * phstmt); void cleanup(HENV henv, HDBC hdbc, HSTMT hstmt); // Allocate the environment, connection, statement handles int Initialize(SQLHANDLE * phenv, SQLHANDLE * phdbc, SQLHANDLE * phstmt)‏ { SQLINTEGER res; // Allocate an environment handle // 1. allocate Environment handle and register version res=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,phenv); // res = SQLAllocEnv(phenv); OLD odbc style if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "Unable to allocate environment handle (ret=%d)\n", res); exit(1); } // Requiere ODBC 3 res=SQLSetEnvAttr(*phenv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); if (res != SQL_SUCCESS)‏ { printf("Error SetEnv\n"); SQLFreeHandle(SQL_HANDLE_ENV, phenv); exit(0); }

56 Ejemplo (cont)‏ // Allocate a connection handle res = SQLAllocHandle(SQL_HANDLE_DBC, *phenv, phdbc); //res = SQLAllocConnect(*phenv, phdbc); OLD STYLE if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "Unable to allocate connection handle (ret=%d)\n", res); cleanup(*phenv, *phdbc, *phstmt); exit(1); } // The connection parameters printf("Connection Parameters: DSN='%s', UID='%s', PWD='%s'\n", DSN, DSN_userid, DSN_password); // Connect to the database res = SQLConnect(*phdbc, DSN, SQL_NTS, DSN_userid, SQL_NTS, DSN_password, SQL_NTS); //SQL_NTS -> Null Terminated String if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { fprintf(stderr, "Unable to connect to datasource (ret=%d)\n", res); cleanup(*phenv, *phdbc, *phstmt); exit(1); } // Allocate a statement handle res = SQLAllocHandle(SQL_HANDLE_STMT, *phdbc, phstmt); //res = SQLAllocStmt(*phdbc, phstmt); if (res != SQL_SUCCESS) { fprintf(stderr, "Unable to allocate statement handle (ret=%d)\n", res); cleanup(*phenv, *phdbc, *phstmt); exit(1); } printf("Handles initialized.\n"); return 0; }

57 Ejemplo (cont)‏ // Cleanup before exit void cleanup(HENV henv, HDBC hdbc, HSTMT hstmt)‏ { // Disconnect from the database and free all handles SQLFreeHandle(SQL_HANDLE_STMT, hstmt);//SQLFreeStmt(hstmt, SQL_CLOSE); SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc);//SQLFreeConnect(hdbc);; SQLFreeHandle(SQL_HANDLE_ENV, henv);//SQLFreeEnv(henv); return; }

58 Ejemplo (Cont) main file: ExecDiretc.c #include #include "Initialize.h" // gcc -lodbc -I/home/roberto/tmp/unixODBC /include ExecDirect.c -o ExecDirect int main(int argc, char *argv[])‏ { HENV henv; HDBC hdbc; HSTMT hstmt; SQLCHAR SelectStmt[255]; int res; if (argc != 2) { fprintf(stderr, "Usage: ExecDirect \n"); exit(1); } else { if (strlen (argv[1]) > 254) { fprintf(stderr, "SQL statement is longer than 254 characters\n"); exit(1); } strncpy((char *) SelectStmt, argv[1], 255); } // Allocate all handles res = Initialize(&henv, &hdbc, &hstmt); if (res != 0) { fprintf("Unable to initialize (ret=%d)\n", res); exit(1); }

59 Ejemplo Cont // Prepare and execute the user provided SQL statement res = SQLExecDirect(hstmt, SelectStmt, SQL_NTS); if (res != SQL_SUCCESS) { fprintf("Unable to execute statement directly (ret=%d)\n", res); // Disconnect from the database and free all handles cleanup(henv, hdbc, hstmt); exit(1); } printf("'%s' directly executed.\n", SelectStmt); cleanup(henv, hdbc, hstmt); return 0; }

60 Ejemplo: conexión // 2. allocate connection handle, set timeout V_OD_erg = SQLAllocHandle(SQL_HANDLE_DBC, V_OD_Env, &V_OD_hdbc); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))‏ { printf("Error AllocHDB %d\n",V_OD_erg); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } SQLSetConnectAttr(V_OD_hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0); // 3. Connect to the datasource "web" V_OD_erg = SQLConnect(V_OD_hdbc, (SQLCHAR*) “cia", SQL_NTS,//o nombre DSN (SQLCHAR*) “roberto", SQL_NTS,//username (SQLCHAR*) "", SQL_NTS);//passwd if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))‏ { printf("Error SQLConnect %d\n",V_OD_erg); SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc,1, V_OD_stat, &V_OD_err,V_OD_msg,100,&V_OD_mlen); printf("%s (%d)\n",V_OD_msg,V_OD_err); SQLFreeHandle(SQL_HANDLE_DBC, V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } printf("Connected !\n"); /* continued on next page */ “handle” para una conexión este “handle” cuelga de Env_hnd “handle” Para esta conexión fijar el timeout a 5 segundos.

61 Ejemplo: desconexión Para finalizar una conexión SQLDisconnect(V_OD_hdbc); Para liberar “handles” SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env);

62 Ejemplo: Consultas Tabla mitabla iduser dtname dtmaxSize 1 Christa Nicole 9000 Consulta SELECT dtname, iduser FROM mitabla ORDER BY iduser

63 Ejemplo Consulta SQLHSTMT V_OD_hstmt; // “Handle” para las consultas SQLINTEGER V_OD_err,V_OD_id;// codigo de error y sitio para dtmaxSize char V_OD_buffer[200];// sitio para el nombre dtname Now we can bind the variables: SQLBindCol(V_OD_hstmt,1,SQL_C_CHAR, &V_OD_buffer,200,&V_OD_err); SQLBindCol(V_OD_hstmt,2,SQL_C_ULONG,&V_OD_id,sizeof(V_OD_id),&V_OD_err); // Now we can execute the query by calling SQLExecDirect: V_OD_erg=SQLExecDirect(V_OD_hstmt, "SELECT dtname,iduser FROM tkeyuser order by iduser",SQL_NTS); if ((V_OD_erg != SQL_SUCCESS) && (V_OD_erg != SQL_SUCCESS_WITH_INFO))‏ { printf("Error Select %d\n",V_OD_erg); SQLGetDiagRec(SQL_HANDLE_DBC, V_OD_hdbc,1, V_OD_stat, &V_OD_err, V_OD_msg,100,&V_OD_mlen); printf("%s (%d)\n",V_OD_msg,V_OD_err); SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt); SQLDisconnect(V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); exit(0); } No Columna tipo variable donde almacenar la variable Codigo de error que por vagancia no se comprueba Codigo de Error Tamaño de la cadena

64 Ejemplo: procesar la consulta V_OD_erg=SQLFetch(V_OD_hstmt); while(V_OD_erg != SQL_NO_DATA)‏ { printf("Result: %d %s\n",V_OD_id,V_OD_buffer); V_OD_erg=SQLFetch(V_OD_hstmt); } ; SQLFreeHandle(SQL_HANDLE_STMT,V_OD_hstmt); SQLDisconnect(V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_DBC,V_OD_hdbc); SQLFreeHandle(SQL_HANDLE_ENV, V_OD_Env); return(0); Codigo de Error En colbind designamos estas dos variables como destino