desarrollo de aplicaciones base de datos oracle - departamento de...

31
Base de Datos Oracle: desarrollo de aplicaciones Interfaz OCI jul-04 Alberto M.F.A. [email protected] 2 Contenidos Tecnologías nativas ORACLE Plataforma Windows Plataforma JAVA

Upload: dangthuan

Post on 16-Oct-2018

215 views

Category:

Documents


0 download

TRANSCRIPT

Base de Datos Oracle: desarrollo de aplicaciones

Interfaz OCI

jul-04 Alberto M.F.A. [email protected] 2

Contenidos� Tecnologías nativas ORACLE� Plataforma Windows� Plataforma JAVA

jul-04 Alberto M.F.A. [email protected] 3

Tecnologías ORACLE� OCI � Oracle Call Interfaz

� 3GL� C/C++, COBOL, FORTRAN

� Precompiladores� Pro C/C++� Pro COBOL� Pro FORTRAN� SQLJ para java

jul-04 Alberto M.F.A. [email protected] 4

OCI� Interfaz de más bajo nivel disponible en

el cliente� Encima de Net8� OCI es un API procedural para

lenguajes de 3ª generación� C / C++� Cobol � Fortran

jul-04 Alberto M.F.A. [email protected] 5

OCI y Net8

jul-04 Alberto M.F.A. [email protected] 6

Características del API� Permite obtener mucho rendimiento� Pro-C, ODBC, OleDB, ADO, JDBC sobre OCI� Incluye funciones para:

� Control de sesiones� Transacciones� SQL dinámico� Acceso a Objetos Oracle� Arrays en sentencias SQL� Manejo de Threads (Thread Safe)

jul-04 Alberto M.F.A. [email protected] 7

Características avanzadas� Interfaces para estructuras internas� Gestión de varias sesiones concurrentes� Client-side Object cache� Maneja objetos con SQL o punteros C� Conversión entre tipos C y Oracle� OTT� Oracle Advanced Queing (OA)

jul-04 Alberto M.F.A. [email protected] 8

Inconvenientes� Muchas funciones en el API� Con muchos parámetros� Excesivo uso de void*� Para portabilidad tipos de datos C

Oracle � (cast)� API muy complejo

jul-04 Alberto M.F.A. [email protected] 9

Compilación

jul-04 Alberto M.F.A. [email protected] 10

Compilación� Ficheros de cabecera

� #include <oci.h>� $ORA_HOME/oci/include

� Librerías compiladas para ANSI C:� Borland C++ 5.0 � $ORA_HOME/oci/lib/bc� MVC++ 6.0 � $ORA_HOME/oci/lib/msvc

jul-04 Alberto M.F.A. [email protected] 11

Programación: pasos básicos� Crear variable de entorno� Crear handlers y estructuras� Conectar al servidor e iniciar

sesión� Ejecutar transacciones SQL y

procesar� Cerrar sesión y desconectar� Liberar handlers y estructuras

jul-04 Alberto M.F.A. [email protected] 12

Proceso y entorno� Todas las transacciones se ejecutan en

un entorno (OCIEnv)� Un Proceso OCI soporta múltiples

entornos

jul-04 Alberto M.F.A. [email protected] 13

Proceso y entorno

jul-04 Alberto M.F.A. [email protected] 14

Estructuras de datos OCI� Son áreas de datos opacas, ocultas al

programa, dentro de la librería.� Se referencian a través de *handlers.� Se crean con llamadas al API� Dos tipos:

� Handlers� Descriptores

jul-04 Alberto M.F.A. [email protected] 15

Handlers� Punteros a estructuras ocultas� Guardan información sobre:

� Contexto y conexión� Errores y funciones OCI

Solo Algunos...

jul-04 Alberto M.F.A. [email protected] 16

Handlers� Se pasan en todas las llamadas� La mayoría dependen del Handle de

entorno� Hay relación jerárquica entre ellos

� Creación de OCIEnv OCICreateEnv(...)

jul-04 Alberto M.F.A. [email protected] 17

Jerarquía de Handlers� Casi todos dependen de OCIEnv

jul-04 Alberto M.F.A. [email protected] 18

Creación de Handlers� De entorno OCIEnv:OCIEnvCreate(&Env,OCI_DEFAULT,...

� Resto de Handlers:OCIHandleAlloc(Env, &Error,OCI_HTYPE_ERROR, 0, NULL);

jul-04 Alberto M.F.A. [email protected] 19

Destrucción de handlers� Para todos

OCIHandleFree(...)

� Si se elimina el de entorno, todos liberados (jerarquía)

OCIHandleFree(Env, OCI_HTYPE_ENV)

jul-04 Alberto M.F.A. [email protected] 20

Handlers principales� Environment � OCIEnv� Error � OCIError� Service Context � OCISvcCtx

� Server � OCIServer� UserSesion � OCISesion

� Statement � OCIStmt� Bind � OCIBind� Define � OCIDefine

jul-04 Alberto M.F.A. [email protected] 21

Atributos de handlers� Cada atributo representa información

guardada en el handle� Cada handler tiene atrib. Especificos� Hay que Asociar explicitamente los

atributos al handlerOCIAttrSet(...)

OCIAttrGet(...)

jul-04 Alberto M.F.A. [email protected] 22

Uso de memoria OCI� OCICreateEnv, OCIHandleAlloc y

OCIDescriptorAlloc() permiten reservar memoria de la librería

� Útil para datos de cliente con mismo ciclo de vida que el handle

� Parámetro xtramem_sz� La librería la libera al eliminar el handle� Evita “leaks” de memoria

jul-04 Alberto M.F.A. [email protected] 23

Descriptores� Mantienen información sobre conceptos

“dentro” de la BD (¿metainformación?)� Funciones:OCIDescriptorAlloc(...)

OCIDescriptorFree(...)

jul-04 Alberto M.F.A. [email protected] 24

Tipos de descriptores� OCISnapshot � Instántanea� OCILOBLocator � CLOB, BLOB� OCIParam � describe calls� OCIRowid � bind-define rowids� OCINotify � publish-suscribe� OCIAQ... �mensajes

jul-04 Alberto M.F.A. [email protected] 25

Inicialización de la aplicación� Varios modos

� Shared Mode, cuando:� Varias instancias de la misma aplicación en la misma

máquina para distintos clientes� Se ejecuta la misma sentencia en la misma o distintas

conexiones� Es un driver SQL u otro middleware

� Threaded� Events� Default

jul-04 Alberto M.F.A. [email protected] 26

Inicialización� Los modos anteriores pueden

combinarse con el operador |:mode = (OCI_THREADED | OCI_OBJECT)

� Con las funciones:OCIEnvCreate(...)

OCIInitialize(...) ���� depre

jul-04 Alberto M.F.A. [email protected] 27

Conexión y sesión� Dos modos:

� Aplicaciones para único usuario y conexión por BDOCILogon(...)

� Múltiples sesiones o conexionesOCIServerAttach(...)

OCISessionBegin(...)

jul-04 Alberto M.F.A. [email protected] 28

Conexión sencillaOCIEnvCreate(&Env, ...)

OCIHandleAlloc(Env, &Error, ...)

OCILogon(Env, Error

, &Servicio ����

, “user”

, “pass”

, “database”)

jul-04 Alberto M.F.A. [email protected] 29

Conexión compleja� Crear entorno� Crear conexión� Crear sesión� Poner sesión en contexto de servicio

� Muchas posibilidades:� Conexión a varias máquinas� Varias sesiones por máquina� Migración de sesiones entre conexiones

jul-04 Alberto M.F.A. [email protected] 30

Entorno y conexiónOCIEnvCreate(&Env, ...)

OCIHandleAlloc(Env, &Error, ...)

OCIHandleAlloc(Env, &Server, ...)

OCIServerAttach(Server, “maquina”,...)

jul-04 Alberto M.F.A. [email protected] 31

Sesión y servicioOCIHandleAlloc(Env, &Sesion, ...)

OCIAttrSet(Sesion, “user”, ...)

OCIAttrSet(Sesion, “pass”, ...)

OCIHandleAlloc(Env, &Servicio, ...)

OCISessionBegin(Servicio, Sesion, ...)

OCIAttrSet(Servicio, Server, ...)

OCIAttrSet(Servicio, Sesion, ...)

jul-04 Alberto M.F.A. [email protected] 32

Ejecución de sentencias� Ubicar Handlers� Preparación� Bind de variables� Define de variables� Ejecutar� Fetch para recuperar datos (SELECT )� Liberar handlers

jul-04 Alberto M.F.A. [email protected] 33

Ejecución de sentencias

Caso complejo con SQL dinámico

jul-04 Alberto M.F.A. [email protected] 34

Creación de handlerOCIHandleAlloc(Env

, &hStmt ����

, OCI_HTYPE_STMT

, ...);

jul-04 Alberto M.F.A. [email protected] 35

Preparación� Se precompila

� Validación sintáctica y semántica� Preparación de estructuras en memoria� Se cachea la precompilación � importante si

muchas ejecuciones repetidas

OCIStmtPrepare(hStmt, Error, “Sentencia SQL”

, OCI_NTV_SYNTAX ���� Sintaxis, ...);

jul-04 Alberto M.F.A. [email protected] 36

Bind y Define� Bind: asociar variables de entrada a la

sentencia con variables del programa� Define: asociar variables de salida de la

sentencia a las del programaSELECT ename, sal, comm INTO:emp_name, :salary, :commission

FROM emp

WHERE ename = :emp_number;

jul-04 Alberto M.F.A. [email protected] 37

Placeholders� Marcadores dentro de la sentencia� Sintaxis :<nombre>� Solo validos para datos, no para

estructura

INSERT INTO :emp ���� InválidoVALUES (12345, ’OERTEL’,’WRITER’, 50000, 30)

jul-04 Alberto M.F.A. [email protected] 38

Placeholders� También en PL/SQL

char plsql_statement[] =

"BEGIN \

RAISE_SALARY(:emp_number,:new_sal); \

END;";

jul-04 Alberto M.F.A. [email protected] 39

Formas de Bind y Define� ByName

OCIBindByName(...)

OCIDefineByName(...)

� ByPosOCIBindByPos(...)

OCIDefineByPos(...)

jul-04 Alberto M.F.A. [email protected] 40

OCI<Bind/Define>ByName()status = OCIBindByName(hStmt

, &bnd1 � Handler, hError

, (text *)":ENAME” � Placeholder, strlen(":ENAME”) � sizeof(“:ename”), emplName � Puntero a var, EMPL_NAME_LENGTH + 1 � sizeof(variable), SQLT_STR � Tipo dato, NULL, NULL, NULL, 0, NULL

, OCI_DEFAULT );

jul-04 Alberto M.F.A. [email protected] 41

OCI<Bind/Define>ByPos()status = OCIDefineByPos(hStmt

, &dfn1 � Handler, Error

, 1 � Posición, deptName � Puntero a Var., sizeof(deptName)+1 � Tamaño, SQLT_STR � Tipo dato, NULL, NULL, NULL

, OCI_DEFAULT);

jul-04 Alberto M.F.A. [email protected] 42

sizeof(<B/D variable>)� Atención al tipo de dato (strings)

jul-04 Alberto M.F.A. [email protected] 43

Indicación de situaciones especiales� En BIND o DEFINE:

� Truncamientos por longitud� NULL’s

� En OCI<B/D>By<Name/Pos>() se puede dar un puntero a sb2� Tipo definido en algún .h de OCI

jul-04 Alberto M.F.A. [email protected] 44

Indicadores en Bind

jul-04 Alberto M.F.A. [email protected] 45

Indicadores en Define

jul-04 Alberto M.F.A. [email protected] 46

Ejemplo indicadoresOCIBindByName(hStmt

, bnd2

, Error

, (text *)":JOB"

, -1

, ud->emplJob

, EMPL_JOB_LENGTH + 1

, SQLT_STR

, &indB2 ���� Puntero a sb2, NULL, NULL, 0, NULL, OCI_DEFAULT);

jul-04 Alberto M.F.A. [email protected] 47

Empleo de indicadores� Al dar un dato a sentencia:

� Si NULL � ind = -1;

� Resto de casos � dato=3; ind=0;

� Al leer un resultado a sentencia:� Si NULL � ind == -1;

� Resto de casos �

if (ind >= 0) expr = dato * ...;

jul-04 Alberto M.F.A. [email protected] 48

Ejecución de sentenciasstatus = OCIStmtExecute(

SvcCtx � handler servicio, hStmt � handler sentencia, Error � handler de error, 1 � nº de iteraciones, 0 � index en array si iter, NULL � snap-in, NULL � snap-out, OCI_DEFAULT);� modo

jul-04 Alberto M.F.A. [email protected] 49

Lectura de resultados� Si la sentencia retorna un conjunto de

datos (cursor)� Hay que iterar por el resultado

� Si la sentencia devuelve una sola fila� OCIStatementExecute() ya deja los

resultados en las variables asociadas con OCIDefineBy<name/pos>() y actualiza los indicadores.

jul-04 Alberto M.F.A. [email protected] 50

Iteración por el resultadoOCIStatementExecute(...)

while (hay datos)

{

proceso de datos ...

OCIStmtFetch(...)

}

jul-04 Alberto M.F.A. [email protected] 51

Iteración por el resultadostatus = OCIStmtFetch(

hStmt

, Error

, 1 � Nº filas a recuperar

, OCI_FETCH_NEXT � Movimiento de cursor

, OCI_DEFAULT

);

jul-04 Alberto M.F.A. [email protected] 52

Ajustes de iteraciones� Para minimizar RoundTrips al servidor

se pueden ajustar cosas como:� Prefetch, cantidad de filas traídas en cada

lectura� Cantidad de memoria para prefetch

� Con OCIAttrSet(...)

jul-04 Alberto M.F.A. [email protected] 53

Transacciones� OCI soporta varios niveles de

transacción:� Simple local� Serializable o Read-only� Global

jul-04 Alberto M.F.A. [email protected] 54

Transacciones simples� Cada sentencia inicia una Trx� A OCIStatementExecute() se le

puede indicar que trabaje en modoOCI_COMMIT_ON_SUCCESS

� Si no (OCI_DEFAULT) hay que cerrar las transacciones explícitamente� Si éxito COMMIT� Si fallo ROLLBACK

jul-04 Alberto M.F.A. [email protected] 55

Trx Serializables o Read-only� Se inician explicitamente con

OCITransStart(...)

� Se debe parar el modo:� OCI_TRANS_SERIALIZABLE� OCI_TRANS_READONLY

jul-04 Alberto M.F.A. [email protected] 56

Trx globales� Son transacciones sofisticadas� Intervienen varios agentes� Pueden ser ramificadas� Commit en una o dos fases

� One-Phase commit� Two-Phase commit

jul-04 Alberto M.F.A. [email protected] 57

Commit y RollBack� OCITransCommit(...)

status = OCITransCommit(

SvcCtx, Error, OCI_DEFAULT);

� OCITransRollBack(...)status = OCITransCommit(

SvcCtx, Error, OCI_DEFAULT);

jul-04 Alberto M.F.A. [email protected] 58

Terminación de la aplicación� OCISessionEnd(...)

� OCIServerDetach(...)

� Para cada handle� OCIHandleFree(...)

� Alternativa:� OCIHandleFree(OCIEnv,...

jul-04 Alberto M.F.A. [email protected] 59

Manejo de errores� Cada llamada al API devuelve un status

status = OCI<funcion>(...

� Se debería verificar el status después de cada llamada� Puede dejar el código muy farragoso� Al menos chequear después de cada paso

importante� Acumular varios resultados (|| o |=)

jul-04 Alberto M.F.A. [email protected] 60

Si status != OCI_SUCCESS� Se puede llamar a OCIGetError() para

recuperar información adicional.

� Se puede llamar repetidamente a OCIGetError() para recuperar todos los mensajes.� Cuando no hay más:

(status = OCIGetError()) == OCI_NO_DATA

jul-04 Alberto M.F.A. [email protected] 61

Valores de status