Você está na página 1de 61

ProgramandoconPL/SQLenunaBasede

DatosOracle
Instructor:Ing.FranciscoRiccio.
OCAOracleDatabaseAdministrator10g
OCPOracleDatabaseAdministrator10g
OCPOracleDatabaseAdministrator11g
OCAOracleApplicationServer10g
OracleDatabase10gRACAdministratorCertifiedExpert
ManagingOracleonLinuxCertifiedExpert
OracleDatabaseSQLCertifiedExpert
OracleDatabase11gEssentialsForImplementors
MCTSSQLServer2005
Email:francisco@friccio.com

Contenido
ConsideracionesenlainstalacindelOracleXEyconfiguracindelOracleSQLDeveloper ................ 3
IntroduccinaPL/SQL ....................................................................................................................... 7
Declaracindevariables.................................................................................................................... 9
ManejodeEstructurasdeControl(IF/CASE/LOOP/WHILE/FOR) ...................................................... 14
ManejodeEstructurasComplejas................................................................................................... 19
(Registros/IndexBy/NestedTable/VArray)...................................................................................... 19
ManejodeCursores ........................................................................................................................ 25
ManipulacindeExcepciones.......................................................................................................... 30
ManejodeArchivos......................................................................................................................... 33
CreacindeStoredProceduresyFunciones.................................................................................... 36
CreacinPaquetes........................................................................................................................... 40
CreacindeTriggers ........................................................................................................................ 44
ConsideracionesenelDiseodeCdigoPL/SQL .............................................................................. 51
ProgramacinOrientadaaObjetosenPL/SQL ................................................................................. 58

Consideracionesen lainstalacindelOracleXEy
configuracindelOracleSQLDeveloper
Descargas
OracleXE:
http://www.oracle.com/technetwork/database/express
edition/downloads/index.html
OracleSQLDeveloper:
http://www.oracle.com/technetwork/developertools/sql
developer/downloads/index.html
Descargadoslosproductoseinstalados,seindicalospasosparapodergenerar
unaconexinhaciaunabasededatosdesdeelOracleSQLDeveloper.
DondeenNombredeConexinsecolocaunnombredeidentificacindela
conexinquepudierasercualquiernombre.
Enusuarioycontraseadebeserunusuariovlidodelabasededatosconsu
contrasea,enestecasoestamosutilizandoelusuarioSYSTEMqueexisteenla
basededatos.
EnloscamposdeNombredeHost,PuertoyNombredelServicio,sondatosque
hacenreferenciaallistenerdelabasededatos.Ellisteneresuncomponentede
labasededatosqueserresponsablederealizarlaconexinalabasededatos.
Estosdatospuedenserextradosenelservidordebasededatospublicandoel
comando:lsnrctlstatus,ejemplo:
Dondelomarcadoconrojosonlosdatosdellistenerquesoncolocadosenel
OracleDeveloper.
LuegopodemosdarclickenProbarydebesalirEstado:Correctoy
posteriormenteguardamoslosdatos.

IntroduccinaPL/SQL
PLSQLesunaextensindeprogramacinaSQL.
Esellenguajedeprogramacinde4tageneracinparabasededatosOracle.
Respectoasuarquitectura
TodocdigoPLSQLsecomponedecdigoPLSQL+sentenciasSQL.
DondeelcdigoPLSQLesejecutadoenunenginellamadoPLSQLylassecciones
quesonsentenciasSQLsonejecutadasenelSQLStatementExecutor(Oracle
DatabaseServer).
TodabasededatosOracletieneunPLSQLenginedeformainherente.Existe
otrosproductosquecuentanconunPLSQLenginecomoelOracleApplication
Serverensusproductos(OracleForms,OracleReports).
EnelcasodeaplicacionesconOracleFormsyReports,elPLSQLEnginese
ejecutarenelladodelclienteylasseccionesconsentenciasSQLson
ejecutadasenlabasededatos.
AlgunosBeneficios
Permitecrearprogramasmodulares.
IntegracinconherramientasdeOracle.
Portabilidad.
ManejaExcepciones.
UncdigoenPLSQLpuedeserdedostipos:cdigoannimoysubprogramas.
Uncdigoannimoesbsicamenteaquelqueelcdigofuenteresideenellado
clienteyunsubprogramaresideelcdigofuenteenelservidor.Los
subprogramaspuedenser:storedprocedures,funciones,triggersypaquetes.
Semuestralasdiferentesseccionesquecomponenlosdiferentestiposdecdigo
PLSQL.

Declaracindevariables
LaseccindedeclaracindevariablessedefineenlaseccinDECLAREejemplo:
DECLARE
mivar<tipo_dato>
LostiposdedatosenOracleDatabase11genPLSQL:
CHAR,VARCHAR,NUMBER,BINARY_INTEGER:
PLSQL_INTEGER,BOOLEAN,BINARY_FLOAT,BINARY_DOUBLE
DATE,TIMESTAMP,TIMESTAMPWITHTIMEZONE.
TIMESTAMPWITHLOCALTIMEZONE,INTERVALYEARTOMONTH,INTERVAL
DAYTOSECOND
Ejemplo#1:
SETSERVEROUTPUTON
DECLARE
V_MIVARIABLEVARCHAR(20):='HOLAMUNDO'
BEGIN
DBMS_OUTPUT.PUT_LINE(V_MIVARIABLE)
DBMS_OUTPUT.PUT_LINE('FINDELPROGRAMA')
END
/
Ejemplo#2
SETSERVEROUTPUTON
DECLARE
V_NUM1NUMBER(4,2):=10.2
V_NUM2NUMBER(4,2):=20.1
BEGIN
DBMS_OUTPUT.PUT_LINE('LASUMAES:'||TO_CHAR(V_NUM1+V_NUM2))
END
/
Castingentretiposdedatos:
Lasfuncionesdeconversinbsicason:TO_NUMBER,TO_CHARyTO_DATE.
Ejemplo:
Sideseamosconvertirdenmeroacaracter:TO_CHAR(20)
Sideseamosconvertirdecaracteranmero:TO_NUMBER('20')
Sideseamosconvertirdefechaacaracter:TO_CHAR(v_fecha, 'DDMMYYYY
HH24:MI:SS')
Mapeandovariablesatiposdedatosdecolumnasdetablas
Paraindicarqueeltipodedatodeunavariableserelquetieneunacolumna
deunatablasehacemedianteeloperador%type.
Ejemplo#3:
SETSERVEROUTPUTON
DECLARE
V_FECHAV$DATABASE.CREATED%TYPE
BEGIN
SELECTCREATEDINTOV_FECHAFROMV$DATABASE
DBMS_OUTPUT.PUT_LINE('LAFECHADECREACIONDELABASEDEDATOS
FUE:'||TO_CHAR(V_FECHA,'DDMMYYYY'))
END
/
Consideraciones
Laasignacindeunvalorsobreunavariableserealizamedianteel
operador:=ejemplo:v_mivariable:=20
TodainstruccindePLSQLfinalizaconpuntoycoma().
Siunquerydevuelveunasolafilayconuncampopuedeserasignadoa
unavariable,ejemplo:
SELECTCOUNT(*)INTOMI_VARIABLEFROMHR.EMPLOYEES
Siunquerydevuelveunasolafilaycon2omscampostambinpuede
serasignadoavariasvariables,ejemplo:
SELECTNAME,CREATEDINTOMI_VAR1,MI_VAR2FROMV$DATABASE

ManejodeEstructurasdeControl
(IF/CASE/LOOP/WHILE/FOR)
IF
Sintaxis:
IF(OPERACINLOGICA)THEN
ELSIFTHEN
ELSE
ENDIF
Ejemplo#4:
SETSERVEROUTPUTON
DECLARE
V_FECHAV$DATABASE.CREATED%TYPE
BEGIN
SELECTCREATEDINTOV_FECHAFROMV$DATABASE
IF(SYSDATEV_FECHA>30)THEN
DBMS_OUTPUT.PUT_LINE('LABASEDEDATOSFUECREADAHACEMSDE30
DIAS.')
ELSE
DBMS_OUTPUT.PUT_LINE('LABASEDEDATOSFUECREADAHACEMENOSDE
30DIAS.')
ENDIF
END
/
Ejemplo#5
SETSERVEROUTPUTON
DECLARE
V_FECHAV$DATABASE.CREATED%TYPE
BEGIN
SELECTCREATEDINTOV_FECHAFROMV$DATABASE
IF(SYSDATEV_FECHA>30)THEN
DBMS_OUTPUT.PUT_LINE('LABASEDEDATOSFUECREADAHACEMSDE30
DIAS.')
ELSIF(SYSDATEV_FECHA>15)AND(SYSDATEV_FECHA<30)THEN
DBMS_OUTPUT.PUT_LINE('LABASEDEDATOSFUECREADAHACEMSDE15
DIASYMENOSDE30DIAS.')
ELSE
DBMS_OUTPUT.PUT_LINE('LABASEDEDATOSFUECREADAHACEMENOSDE
15DIAS.')
ENDIF
END
/
CASE
Sintaxis:
CASE
WHENCONDICION1THEN
WHENCONDICION2THEN
ELSE
ENDCASE
Ejemplo#6:
SETSERVEROUTPUTON
DECLARE
V_TOTALNUMBER:=0
BEGIN
SELECTCOUNT(*)INTOV_TOTALFROMDBA_OBJECTS
CASE
WHENV_TOTAL<2000THEN
DBMS_OUTPUT.PUT_LINE('LABASEDEDATOSTIENEMENOSDE2000
OBJETOS.')
WHEN(V_TOTAL<4000)AND(V_TOTAL>2000)THEN
DBMS_OUTPUT.PUT_LINE('LABASEDEDATOSTIENEENTRE4000A2000
OBJETOS.')
ELSE
DBMS_OUTPUT.PUT_LINE('LABASEDEDATOSTIENEMASDE4000
OBJETOS.')
ENDCASE
END
/
LOOP
Permitegenerarbucles.
Sintaxis:
LOOP
EXITWHENCONDICION_SALIDA
ENDLOOP
Ejemplo#7:
Imprimiendolosprimeros10nmeros:
SETSERVEROUTPUTON
DECLARE
V_NUMNUMBER:=0
BEGIN
LOOP
V_NUM:=V_NUM+1
DBMS_OUTPUT.PUT_LINE('NUMERO:'||TO_CHAR(V_NUM))
EXITWHENV_NUM>=10
ENDLOOP
END
/
WHILE
Sintaxis:
WHILECONDICIONLOOP
ENDLOOP
Ejemplo#8:
SETSERVEROUTPUTON
DECLARE
V_NUMNUMBER:=1
BEGIN
WHILEV_NUM<11LOOP
DBMS_OUTPUT.PUT_LINE('NUMERO:'||TO_CHAR(V_NUM))
V_NUM:=V_NUM+1
ENDLOOP
END
/
FOR
Sintaxis:
FORVARIABLEININICIO..FINALLOOP
ENDLOOP
Ejemplo#9:
SETSERVEROUTPUTON
BEGIN
FORV_NUMIN1..10LOOP
DBMS_OUTPUT.PUT_LINE('NUMERO:'||TO_CHAR(V_NUM))
ENDLOOP
END
/
Nota:LavariableutilizadacomocontadorenelFORnorequiereserespecificada
enelDECLARE.

ManejodeEstructurasComplejas
(Registros/IndexBy/NestedTable/VArray)
Registros
Permitecrearestructurasquealberganunconjuntodetiposdedatos.
Porejemplo,podemoscrearelregistroPERSONAconloscamposcdigo,
nombreyedad,cadaunodeestoscamposcondiferentestiposdedatos.
Sintaxis:
TYPE<NOMBRE_REGISTRO>ISRECORD(
CAMPO1TIPO_DATO,
CAMPO2TIPO_DATO

)
Ejemplo#10:
SETSERVEROUTPUTON
DECLARE
TYPETPERSONAISRECORD(
CODIGONUMBER,
NOMBREVARCHAR(100),
EDADNUMBER
)
V_VAR1TPERSONA
BEGIN
V_VAR1.CODIGO:=1
V_VAR1.NOMBRE:='FRANCISCO'
V_VAR1.EDAD:=30
DBMS_OUTPUT.PUT_LINE('CODIGO:'||TO_CHAR(V_VAR1.CODIGO)||'
PERSONA:'||V_VAR1.NOMBRE||'EDAD:'||TO_CHAR(V_VAR1.EDAD)||'.')
END
/
Adicional:
Tambinpodemoscrearregistrosquemantenganlosmismoscamposytiposde
datosqueunatabla.
DECLARE
MIVARIABLEDBA_OBJECTS%ROWTYPE
IndexBy
IndexBypermitecreararreglosenPLSQL.
Sintaxis:
TYPE<NOMBRE_TIPO_LISTA>ISTABLEOF<TIPO_DATO_NODO>INDEXBY
BINARY_INTEGER|PLS_INTEGER|VARCHAR2(#)
Ejemplo#11:
SETSERVEROUTPUTON
DECLARE
TYPET_LISTAISTABLEOFNUMBERINDEXBYBINARY_INTEGER
V_LISTAT_LISTA
BEGIN
FORIIN1..10LOOP
V_LISTA(I):=I
ENDLOOP
FORIIN1..10LOOP
DBMS_OUTPUT.PUT_LINE(I)
ENDLOOP
END
/
ConsideracionesconlosINDEXBY:
Nopuedenseruntipodedatodeunacolumnadeunatabla.
NorequierenserinicializadoslasvariablesdetipoINDEXBY.
Losnodosdelarreglonorequierenserinicializados.
NestedTable
LosNestedTabletambinpermitecreararreglosenPLSQL.
Sintaxis:
TYPE<NOMBRE_TIPO_LISTA>ISTABLEOF<TIPO_DATO_NODO>
Ejemplo#12:
SETSERVEROUTPUTON
DECLARE
TYPET_LISTAISTABLEOFNUMBER
V_LISTAT_LISTA:=T_LISTA()
BEGIN
FORIIN1..10LOOP
V_LISTA.EXTEND
V_LISTA(I):=I
ENDLOOP
FORIIN1..10LOOP
DBMS_OUTPUT.PUT_LINE(I)
ENDLOOP
END
/
Ejemplo#13:
CREATETYPET_TELEFONOSISTABLEOFCHAR(7)
/
CREATETABLEPERSONA(CODIGONUMBER,NOMBREVARCHAR(25),LISTA
T_TELEFONOS)
NESTEDTABLELISTASTOREASTAB_LISTA
INSERTINTOPERSONAVALUES
(1,'FRANCISCO',T_TELEFONOS('1234567','7654321'))
COMMIT
SELECT*FROMPERSONA
ConsideracionesconlosNESTEDTABLE:
Puedeseruntipodedatodeunacolumnadeunatabla,peroseguarda
enotrosegmento,esdecirnoseguardaenlamismatablafsicamente.
RequiereserinicializadoslasvariablesdetipoNESTEDTABLE.
Porcadanodonuevodelarreglodebepreviamenteelarregloauto
extenderse.
VARRAY
LosVARRAYtambinpermitencreararreglosenPLSQL,perotienenuntamao
limitadodesdesuespecificacin.
Sintaxis:
TYPE<NOMBRE_TIPO_LISTA>ISVARRAY(#NODOS)OF<TIPO_DATO_NODO>
Ejemplo#14:
SETSERVEROUTPUTON
DECLARE
TYPET_LISTAISVARRAY(10)OFNUMBER
V_LISTAT_LISTA:=T_LISTA()
BEGIN
FORIIN1..10LOOP
V_LISTA.EXTEND
V_LISTA(I):=I
ENDLOOP
FORIIN1..10LOOP
DBMS_OUTPUT.PUT_LINE(I)
ENDLOOP
END
/
Ejemplo#15:
CREATETYPET_TELEFONOSISVARRAY(2)OFCHAR(7)
/
CREATETABLEPERSONA(CODIGONUMBER,NOMBREVARCHAR(25),LISTA
T_TELEFONOS)
INSERTINTOPERSONAVALUES
(1,'FRANCISCO',T_TELEFONOS('1234567','7654321'))
COMMIT
SELECT*FROMPERSONA
ConsideracionesconlosVARRAY:
Puedeseruntipodedatodeunacolumnadeunatablaysiesguardado
enlamismatablafsicamente.
RequiereserinicializadoslasvariablesdetipoVARRAY.
Porcadanodonuevodelarreglodebepreviamenteelarregloauto
extenderse.
Los3tiposdearreglostienenmtodosquepodemosutilizarennuestros
cdigos.
Selistaalgunodelosmtodos:

ManejodeCursores
CadasentenciaSQLqueesejecutadaenlabasededatossiempretiene
asociadouncursor.LoscursoressondefinidosenelPGA(Memoriaprivadapor
cadaserverprocess).
LoscursorespuedenserdefinidiosporOracledeformaexplcitaoimplcita.
ImplcitasignificaqueOracleDatabaseesresponsabledecrearelcursor,abrirlo
recorrerloycerrarlo.Deformaexplcitanosotrossomosresponsablesdelas
actividadesmencionadas.
Elcontroldeuncursorsedefineenelsiguientegrfico:
Sintaxis:
DECLARE
CURSORMICURSORIS<QUERY>
BEGIN
OPENMICURSOR
FETCHMICURSORINTOVARIABLES_PLSQL
CLOSEMICURSOR
END
/
Ejemplo#16:
SETSERVEROUTPUTON
DECLARE
CURSORMICURSORISSELECTFIRST_NAME,LAST_NAMEFROM
HR.EMPLOYEES
V_NOMBREHR.EMPLOYEES.FIRST_NAME%TYPE
V_APELLIDOHR.EMPLOYEES.LAST_NAME%TYPE
BEGIN
OPENMICURSOR
LOOP
FETCHMICURSORINTOV_NOMBRE,V_APELLIDO
EXITWHENMICURSOR%NOTFOUND
DBMS_OUTPUT.PUT_LINE('NOMBRE:'||V_NOMBRE||',APELLIDO:
'||V_APELLIDO)
ENDLOOP
CLOSEMICURSOR
END
/
Ejemplo#17:
Otraformaderecorrerloscursors:
SETSERVEROUTPUTON
DECLARE
CURSORMICURSORISSELECTFIRST_NAME,LAST_NAMEFROM
HR.EMPLOYEES
BEGIN
FORCINMICURSORLOOP
DBMS_OUTPUT.PUT_LINE('NOMBRE:'||C.FIRST_NAME||',APELLIDO:
'||C.LAST_NAME)
ENDLOOP
END
/
Enestecaso,elFORautomticamenteaperturaelcursorylocierra.
Loscursorestienenatributosquepuedenayudarnosenelcontroldelmismo.
Trabajandoconcursoresconparmetros:
Permitecrearuncursorquepermitemanejarparmetros,demodoqueel
mismocursorpodemosutilizarloenvariasocasionesreemplazandoelvalordel
parmetro.
Sintaxis:CURSOR<NOMBRE_CURSOR>(PARAMETROTIPO_DATO)IS
<QUERY>
Ejemplo#17:
SETSERVEROUTPUTON
DECLARE
CURSORMICURSOR(COD_DEPNUMBER)ISSELECTFIRST_NAME,LAST_NAME
FROMHR.EMPLOYEESWHEREDEPARTMENT_ID=COD_DEP
BEGIN
FORCINMICURSOR(100)LOOP
DBMS_OUTPUT.PUT_LINE('NOMBRE:'||C.FIRST_NAME||',APELLIDO:
'||C.LAST_NAME)
ENDLOOP
END
/
WHERECURRENTOF
ElWHERECURRENTOFpermiteactualizarunafilaquelotenemosactualmente
apuntandoennuestrocursor.Comocondicinelcursordebeteneruna
sentenciaSELECTFORUPDATE.
Ejemplo#18:
SETSERVEROUTPUTON
DECLARE
CURSORMICURSOR(COD_DEPNUMBER)ISSELECTFIRST_NAME,LAST_NAME
FROMHR.EMPLOYEESWHEREDEPARTMENT_ID=COD_DEPFORUPDATE
BEGIN
FORCINMICURSOR(100)LOOP
DBMS_OUTPUT.PUT_LINE('NOMBRE:'||C.FIRST_NAME||',APELLIDO:
'||C.LAST_NAME)
UPDATEHR.EMPLOYEES
SETSALARY=1
WHERECURRENTOFMICURSOR
ENDLOOP
COMMIT
END
/
ManejodecursoresGenricos
Permitecrearuncursordondeentiempodeejecucinseasignarelqueryque
elcursordebemanejar.
Sintaxis:
TYPE<NOMBRE_TIPO>ISREFCURSOR
VARIABLE<NOMBRE_TIPO>
Ejemplo#19:
SETSERVEROUTPUTON
DECLARE
TYPET_CURSORISREFCURSOR
MICURSORT_CURSOR
V_APELLIDOHR.EMPLOYEES.LAST_NAME%TYPE
BEGIN
OPENMICURSORFOR'SELECTLAST_NAMEFROMHR.EMPLOYEES'
LOOP
FETCHMICURSORINTOV_APELLIDO
EXITWHENMICURSOR%NOTFOUND
DBMS_OUTPUT.PUT_LINE('APELLIDO='||V_APELLIDO)
ENDLOOP
CLOSEMICURSOR
END
/

ManipulacindeExcepciones
Frenteaerroresdeejecucinquenomanejadasautomticamentenuestro
cdigoterminarconerror.Podemosmanejarloserroresyhaceruntrabajo
respectivofrenteaunproblemaesperadoonoesperado.
Sintaxis:
EXCEPTION
WHENERRORTHEN
<ACCION>
LostiposdeerroresyaexistenalgunospreestablecidosporOracleDatabase(20
aproximadamente)peronocubrentodoslosescenarios.Lomejoresdefinir
nuestrospropioserrores.
Sintaxis:
DECLARE
E1EXCEPTION
PRAGMAEXCEPTION_INIT(E1,#_ERROR)
BEGIN
EXCEPTION
WHENE1THEN
<ACCION>
END
Nota:ElPRAGMAEXCEPTIONpermiteasociarlavariableexceptionconun
cdigodeerrordeOracleDatabase.
Ejemplo#20:
SETSERVEROUTPUTON
DECLARE
E1EXCEPTION
PRAGMAEXCEPTION_INIT(E1,1422)
V_NOMBREHR.EMPLOYEES.LAST_NAME%TYPE
BEGIN
SELECTLAST_NAMEINTOV_NOMBREFROMHR.EMPLOYEES
EXCEPTION
WHENE1THEN
DBMS_OUTPUT.PUT_LINE('ELQUERYDEVUELVEMASDEUNAFILA')
END
/
Siqueremosasegurarnosquesiempremanejaremosunerrorapesarquenolo
hayamosidentificadoeneldiseo,podemosusarlaconstanteOTHERS.
Sintaxis:
EXCEPTION
WHENOTHERSTHEN
<ACCION>
Sideseamosrecibirelmensajedeerrorquedisparlaexcepcinsepuede
utilizarlasfunciones:SQLERRMySQLCODE.
RAISE_APPLICATION_ERROR:
Permitedispararexcepcionespersonalizadosalasaplicaciones.
Sintaxis:
RAISE_APPLICATION_ERROR(#_ERROR,'MENSAJE',FALSE|TRUE)
DondeOracleDatabasenosreservaloscdigosqueseencuentranenunrango
de20000a20999.
Eltercerparmetroqueesuntipodedatoboolean,pordefaultesFALSEelcual
reemplazacualquiererrorquesevengaarrastrandoyesreemplazadoporel
textoqueseindica.SiencasosecolocaTRUE,seimprimirlacoladeerrores
arrastradosincluidoelmensajepersonalizado.

ManejodeArchivos
ConOracleDatabasetenemoslaposibilidaddecrearprogramasquecreen
archivosyasimismoleerlos.Estolopodemosrealizargraciasalpaquete
UTL_FILEquenosproporcionaOracle.
Semuestrauncuadrogeneraldelflujodetrabajoconelmanejodearchivos.
Comorequisitoobligatoriodebemoscrearunobjetodirectorioelcualapuntara
undirectoriodelsistemaoperativodondesealojarnuestroarchivo.
Estolorealizamosconelcomando:CREATEORREPLACEDIRECTORY
Ejemplo#21:
Enesteejercicioseguardaralalistadetodoslosempleadosdelatabla
HR.EMPLOYEES.
CREATEORREPLACEDIRECTORYMIDIRECTORIOAS'C:\'
SETSERVEROUTPUT ON
DECLARE
ARCHIVOUTL_FILE.FILE_TYPE
CURSORMICURSORISSELECTLAST_NAMEFROMHR.EMPLOYEES
BEGIN
ARCHIVO:=UTL_FILE.FOPEN('MIDIRECTORIO','MIARCHIVO.TXT','W')
FORCINMICURSORLOOP
UTL_FILE.PUT_LINE(ARCHIVO,C.LAST_NAME)
UTL_FILE.NEW_LINE(ARCHIVO)
ENDLOOP
UTL_FILE.FCLOSE(ARCHIVO)
END
/
Ejemplo#22:
Enesteejercicioleeremoselarchivoquehemoscreadoenelejercicioanterior.
SETSERVEROUTPUTON
DECLARE
ARCHIVOUTL_FILE.FILE_TYPE
V_LINEAVARCHAR(250)
BEGIN
ARCHIVO:=UTL_FILE.FOPEN('MIDIRECTORIO','MIARCHIVO.TXT','R')
BEGIN
LOOP
UTL_FILE.GET_LINE(ARCHIVO,V_LINEA)
IF(V_LINEAISNOTNULL)THEN
DBMS_OUTPUT.PUT_LINE(V_LINEA)
ENDIF
ENDLOOP
EXCEPTION
WHENNO_DATA_FOUNDTHEN
DBMS_OUTPUT.PUT_LINE('FINDELARCHIVO')
END
UTL_FILE.FCLOSE(ARCHIVO)
END
/

CreacindeStoredProceduresyFunciones
Unstoredprocedureesunprocedimientocuyocdigoseguardaenlabasede
datosytienecomoobjetorealizarunaaccinespecfica.
Susintaxiseslasiguiente:
CREATEORREPLACEPROCEDURE<NOMBRE_PROCEDURE>(PARAMETROS)IS
<DEFINICION_VARIABLES>
BEGIN
<CODIGO_PLSQL>
END
Ejemplo#23:
SETSERVEROUTPUTON
CREATEORREPLACEPROCEDURESPU_SUMAR(XINNUMBER,YINNUMBER)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('LASUMAES:'||TO_CHAR(X+Y))
END
/
Probandoelstoredprocedure:
EXECUTESPU_SUMAR(2,3)
Losparmetrosquepuederecibirunstoredprocedurepuedenserde3tipos:
IN(Default):SiunparmetroesINnopuedesermodificadoenel
transcursodelcdigoPLSQL.
OUT:SiunparmetroesOUTsiemprellegaalcdigodelstoredprocedure
conelvalordeNULLycuandoterminaelcdigodePLSQLelparmetro
mantieneelvalordeformapersistente.
INOUT:Esunacombinacindeambos.
Ejemplo#24:
CREATEORREPLACEPROCEDURESPU_SUMAR(XINNUMBER,YINNUMBER,Z
OUTNUMBER)
IS
BEGIN
Z:=X+Y
END
/
Probandoelstoredprocedure:
SETSERVEROUTPUTON
DECLARE
V_SUMANUMBER:=0
BEGIN
SPU_SUMAR(1,3,V_SUMA)
DBMS_OUTPUT.PUT_LINE(V_SUMA)
END
/
Ejemplo#25:
CREATEORREPLACEPROCEDURESPU_SUMAR(XINOUTNUMBER,YINOUT
NUMBER,ZOUTNUMBER)
IS
BEGIN
Z:=X+Y
END
/
Probandoelstoredprocedure:
SETSERVEROUTPUTON
DECLARE
V_SUMANUMBER:=0
V_XNUMBER:=10
V_YNUMBER:=20
BEGIN
SPU_SUMAR(V_X,V_Y,V_SUMA)
DBMS_OUTPUT.PUT_LINE(V_SUMA)
END
/
Unafuncinaligualquelosstoredprocedures,sucdigoseguardaenlabase
dedatosytienecomofuncinrealizarunclculoydevolverunvalor.
Sintaxis:
CREATEORREPLACEFUNCTION<NOMBRE_FUNCTION>(PARAMETROS)
RETURN<TIPO_DATO>
IS
<DEFINICION_VARIABLES>
BEGIN
<CODIGO_PLSQL>
END
Ejemplo#26:
CREATEORREPLACEFUNCTIONGET_TOTAL_OBJ
RETURNNUMBER
IS
V_TOTALNUMBER:=0
BEGIN
SELECTCOUNT(*)INTOV_TOTALFROMDBA_OBJECTS
RETURNV_TOTAL
END
/
Probandolafuncin:
SELECTGET_TOTAL_OBJFROMDUAL
Restricciones
NopuedeserutilizadoenconstraintsdetipoCHECK.
Nopuedeserutilizadocomodefaultdeunacolumna.
EnsentenciasSQLquellamenafunciones,estasfuncionesestn
restringidasalosiguiente:
o EnsentenciasSELECT,lafuncinnopuedeejecutaruna
sentenciaDML.
o EnsentenciasDELETEoUPDATE,lafuncinnopuedeconsultar
omodificarlatablaqueestteniendoelDELETEoelUPDATE.
o EncualquiersentenciaSELECToDML,lafuncinnopueden
ejecutarunCOMMIToROLLBACK,niunaoperacinDDLniDCL
yaquegeneraunCOMMITimplcito.
Adicional,podemoscrearsubprogramas(funcionesystoredprocedures)que
inicienyfinalicenunatransaccinautnoma.
Sintaxis:
CREATEORREPLACEPROCEDURE<NOMBRE_PROCEDURE>
IS
PRAGMAAUTONOMOUS_TRANSACTION

CreacinPaquetes
Unpaqueteesunaagrupacinlgicadevariables,funcionesystored
procedures.
Sedividelgicamenteen2partescomosedetallaenelsiguientegrfico:
EspecificacinyBody.
Enlaespecificacinsedefinelasvariablesylossubprogramasquequeremos
publicaralaspersonasquedeseenutilizarnuestrosprogramas.
Enelbodyvalaimplementacindecadasubprogramadefinidoenla
especificacinyadicionalotrossubprogramasquequizsnonecesitamosquese
expongan.
Debemostenermuchocuidadosidefinimosvariablesgeneralesenla
especificacinoenbodyyaquesonpersistenteshastaquelasesinsalgadela
basededatos.
Unaventajadeutilizarpaquetesesquelaprimeravezqueunusuariollamaal
paquetetodalainformacindelpaquetesubeenmemoriaylainformacinde
losvaloresdelasvariablesqueutilizacadasesinseguardaenelUGAdecada
sesin.
Sintaxis:
CREATEORREPLACEPACKAGE<NOMBRE_PAQUETE>IS<CODIGO>END
CREATEORREPLACEPACKAGEBODY<NOMBRE_PAQUETE>IS<CODIGO>
END
Ejemplo#27:
Especificacin.
CREATEORREPLACEPACKAGEMIPAQUETE
IS
V_VARNUMBER:=0
FUNCTIONGET_SUMA(XNUMBER,YNUMBER)RETURNNUMBER
PROCEDURESPU_ACTUALIZA_STOCK
END
/
Body.
CREATEORREPLACEPACKAGEBODYMIPAQUETE
IS
V_VARNUMBER:=0
FUNCTIONGET_SUMA(XNUMBER,YNUMBER)RETURNNUMBER
IS
BEGIN
RETURNX+Y
END
PROCEDURESPU_ACTUALIZA_STOCK
IS
BEGIN
NULL
END
END
/
Paratrabajoslargosytemporalesdondeprobablementenorequerimostener
durantetodoelciclodevidadelasesinelvalordeunavariablepodemos
utilizarelPRAGMASERIALLY_REUSABLE.ConelPRAGMA,Oraclemudalas
variablesglobalesalSGA(LargePool)ylosmantieneah.Cadallamadadeun
subprogramaquedeseautilizarlavariable,Oraclerealizaunacopiadela
variablequeencuentraenelSGAalUGAdelusuarioymantieneelvalorenla
sesindelusuariohastaquesefinaliceelsubprogramaquellamalafuncin.
UnPRAGMAesunadirectivadecompilacin.
Ejemplo#28:
CREATEORREPLACEPACKAGEMIPAQUETEIS
PRAGMASERIALLY_REUSABLE
V_NUMNUMBER:=0
PROCEDUREINICIALIZAR(PNNUMBER)
PROCEDUREIMPRIMIR_VALOR
END
/
CREATEORREPLACEPACKAGEBODYMIPAQUETEIS
PRAGMASERIALLY_REUSABLE
PROCEDUREINICIALIZAR(PNNUMBER)IS
BEGIN
MIPAQUETE.V_NUM:=PN
DBMS_OUTPUT.PUT_LINE('NUMERO:'||TO_CHAR(MIPAQUETE.V_NUM))
END
PROCEDUREIMPRIMIR_VALORIS
BEGIN
DBMS_OUTPUT.PUT_LINE('NUMERO:'||TO_CHAR(MIPAQUETE.V_NUM))
END
END
/
Probando:
SETSERVEROUTPUTON
EXECUTEDBMS_OUTPUT.PUT_LINE('VALORVARIABLE:
'||TO_CHAR(MIPAQUETE.V_NUM))
EXECUTEMIPAQUETE.INICIALIZAR(20)
EXECUTEMIPAQUETE.IMPRIMIR_VALOR
EXECUTEDBMS_OUTPUT.PUT_LINE('VALORVARIABLE:
'||TO_CHAR(MIPAQUETE.V_NUM))

CreacindeTriggers
Lostriggerssonsubprogramasquesedisparanfrenteaeventosqueocurrenen
labasededatos.
Lostiposdetriggerson:
SimpleDMLtriggers(BEFORE,AFTERyINSTEADOF).
Compoundtriggers.
NonDMLtriggers(DDL&Databaseevents).
Lostriggersdetiposimpledmlserexplicadoacontinuacin.
Lostriggersdetiposimpledmlsonaquellosquesedisparancuandoocurreuna
operacinDMLydependiendodelmomentoquedeseemosquesedispareantes
odespusdelatransaccinoreemplazarlatransaccinporotrocdigo.
Sintaxis:
CREATEORREPLACETRIGGER<NOMBRE_TRIGGER>
INSTEADOF|BEFORE|AFTER
INSERT|DELETE|UPDATEOF<COLUMNAS>
ON<TABLA>
FOREACHROW
WHEN<CONDICION>
DECLARE
BEGIN
<CODIGO>
END
RespectoaFOREACHROW,significaqueeltriggersedispararporcadafila
queestsiendoafectadoporlatransaccin.
SedetallaunacomparacinentretenerynotenerhabilitadoelFOREACHROW.
Ejemplo#29:
SETSERVEROUTPUTON
CREATETABLETABLA_TG(CAMPO1NUMBER)
CREATEORREPLACETRIGGERTG_TABLA_01
BEFOREINSERTONTABLA_TG
DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE('CODIGOLIBERADOANTESDELINSERT.')
END
/
CREATEORREPLACETRIGGERTG_TABLA_02
AFTERINSERTONTABLA_TG
DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE('CODIGOLIBERADODESPUESDELINSERT.')
END
/
INSERTINTOTABLA_TGVALUES(1)
Ejemplo#30:
SETSERVEROUTPUTON
DELETEFROMTABLA_TG
ALTERTRIGGERTG_TABLA_01DISABLE
ALTERTRIGGERTG_TABLA_02DISABLE
CREATEORREPLACETRIGGERTG_TABLA_03
BEFOREINSERTONTABLA_TG
FOREACHROW
DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE('VALORINGRESADOANTESDELINSERT:
'||TO_CHAR(:NEW.CAMPO1))
:NEW.CAMPO1:=10
DBMS_OUTPUT.PUT_LINE('VALORMODIFICADOA10.')
END
/
CREATEORREPLACETRIGGERTG_TABLA_04
AFTERINSERTONTABLA_TG
FOREACHROW
DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE('VALORINGRESADODESPUESDELINSERT:
'||TO_CHAR(:NEW.CAMPO1))
END
/
INSERTINTOTABLA_TGVALUES(1)
SETSERVEROUTPUTON
DELETEFROMTABLA_TG
ALTERTRIGGERTG_TABLA_01DISABLE
ALTERTRIGGERTG_TABLA_02DISABLE
CREATETABLETABLA_TG(CAMPO1NUMBER)
CREATEORREPLACETRIGGERTG_TABLA_03
BEFOREINSERTONTABLA_TG
FOREACHROW
DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE('VALORINGRESADOANTESDELINSERT:
'||TO_CHAR(:NEW.CAMPO1))
:NEW.CAMPO1:=10
DBMS_OUTPUT.PUT_LINE('VALORMODIFICADOA10.')
END
/
CREATEORREPLACETRIGGERTG_TABLA_04
AFTERINSERTONTABLA_TG
FOREACHROW
DECLARE
BEGIN
DBMS_OUTPUT.PUT_LINE('VALORINGRESADODESPUESDELINSERT:
'||TO_CHAR(:NEW.CAMPO1))
END
/
INSERTINTOTABLA_TGVALUES(1)
Semuestraacontinuacinuncuadroquemuestracuandotenemosdisponibles
lasvariables:NEWy:OLD.
Lostriggersdetipo:INSTEADOFnospermitereemplazarunatransaccinpor
unaaccindiferente.
Ejemplo#31:
SETSERVEROUTPUTON
DELETEFROMTABLA_TG
ALTERTRIGGERTG_TABLA_01DISABLE
ALTERTRIGGERTG_TABLA_02DISABLE
ALTERTRIGGERTG_TABLA_03DISABLE
ALTERTRIGGERTG_TABLA_04DISABLE
CREATEVIEWVTABLA_TGASSELECTCOUNT(*)ASTOTALFROMTABLA_TG
CREATEORREPLACETRIGGERTG_TABLA_05
INSTEADOFINSERTONVTABLA_TG
BEGIN
DELETEFROMTABLA_TG
END
/
INSERTINTOVTABLA_TGVALUES(1)
COMMIT
SELECT*FROMTABLA_TG
Restricciones
LostriggersnopuedensercreadosenelesquemaSYS.
Lostriggersnopuedenconfirmaroanularunatransaccin

ConsideracionesenelDiseo deCdigoPL/SQL
EjecucindeOperacionesDDLyDCL
ConelcomandoEXECUTEIMMEDIATEpodemoscrearcdigodinmicoque
genereunatrasaccinDDLyDCL.
Sintaxis:
EXECUTEIMMEDIATE('<CODIGO_DDL_DCL')
Ejemplo#32:
SETSERVEROUTPUTON
BEGIN
EXECUTEIMMEDIATE('CREATETABLECODIGO_DDL(CAMPO1NUMBER)')
END
/
SELECT*FROMCODIGO_DDL
ConlamismainstruccinEXECUTEIMMEDIATEpodemosrealizarconsultasy
operacionesDMLdeformadinmica.
Sintaxis:
EXECUTEIMMEDAITE('<QUERY>')INTOVARIABLEUSINGVALOR_PARAMETRO
Ejemplo#33:
SETSERVEROUTPUTON
DECLARE
V_TOTALNUMBER:=0
BEGIN
EXECUTEIMMEDIATE('SELECTCOUNT(*)ASTOTALFROMHR.EMPLOYEES
WHEREDEPARTMENT_ID=:CODIGO')INTOV_TOTALUSING100
DBMS_OUTPUT.PUT_LINE('TOTALDEEMPLEADOSENELDEPARTAMENTO100:
'||TO_CHAR(V_TOTAL))
END
/
NOCOPY
PermitealcompiladorpasarparmetrosOUTyINOUTcomoreferenciaynopor
parmetroporvalorqueeseldefaultestoreduceeloverloadeneltiempode
copiadodelosparmetroscuandoseenvan.
Ejemplo#34:
CREATEORREPLACEPROCEDURESPU_SUMAR(XINOUTNOCOPYNUMBER,Y
INOUTNOCOPYNUMBER,ZOUTNOCOPYNUMBER)
IS
BEGIN
Z:=X+Y
END
/
Notieneefectoenlossiguientesescenarios:
ParmetrosquesonelementosdeunINDEXBY.
SobreparmetrosdefinidoscomoNOTNULL.
Sobreparmetrosquefuerondeclaradoscon%ROWTYPEo%TYPE.
Sielparmetrorequiereunaconversinimplcita.
BULKCOLLECT
ElBULKCOLLECTnospermitereducirenun50%eltiempodeaccesoalabase
dedatos.Sebasaenminimizarlacantidaddeswitchcontextqueocurrenal
utilizarcursores.UnswitchcontextesunviajedeidayvueltaentreelPLSQL
EngineyelOracleDatabaseServer.
Ejemplo#35:
Enesteejemplosehahechounsolocontextswitch,dondetodalainformacin
delatablaempleadoshasidocargadaenunarregloyhallegadoalPLSQL
Engine.SinohubiramosusadoBULKCOLLECTsehubierahechouncontext
switchporcadafetchqueserealizaenelcursor.
SETSERVEROUTPUTON
DECLARE
CURSORMICURSORISSELECT*FROMHR.EMPLOYEES
TYPETLISTAISTABLEOFHR.EMPLOYEES%ROWTYPE
LISTATLISTA
BEGIN
OPENMICURSOR
FETCHMICURSORBULKCOLLECTINTOLISTA
CLOSEMICURSOR
FORCIN1..LISTA.COUNTLOOP
DBMS_OUTPUT.PUT_LINE(LISTA(C).LAST_NAME)
ENDLOOP
END
/
Ejemplo#36:
Enesteejemploseesttrayendoencadacontextswitch25filas,elcualesuna
medidaoptimizasegnalgunosanlisisrealizados.Arribade25nodamayor
beneficiodeperformance.
SETSERVEROUTPUTON
DECLARE
CURSORMICURSORISSELECT*FROMHR.EMPLOYEES
TYPETLISTAISTABLEOFHR.EMPLOYEES%ROWTYPE
LISTATLISTA
BEGIN
OPENMICURSOR
LOOP
FETCHMICURSORBULKCOLLECTINTOLISTALIMIT25
FORCIN1..LISTA.COUNTLOOP
DBMS_OUTPUT.PUT_LINE(LISTA(C).LAST_NAME)
ENDLOOP
EXITWHENMICURSOR%NOTFOUND
ENDLOOP
CLOSEMICURSOR
END
/
FORALL
ConsisteigualqueelBULKCOLLECT,peroahoraestdireccionadopara
operacionesDMLqueseenvandesdeelPLSQLEnginehacialabasededatosen
unamenorcantidaddecontextswitch.
Ejemplo#37:
CREATETABLEEMPLEADO_BKASSELECT*FROMHR.EMPLOYEESWHERE1=2
SETSERVEROUTPUTON
DECLARE
CURSORMICURSORISSELECT*FROMHR.EMPLOYEES
TYPETLISTAISTABLEOFHR.EMPLOYEES%ROWTYPE
LISTATLISTA
BEGIN
OPENMICURSOR
LOOP
FETCHMICURSORBULKCOLLECTINTOLISTALIMIT25
FORALLIIN1..LISTA.COUNT
INSERTINTOEMPLEADO_BKVALUESLISTA(I)
EXITWHENMICURSOR%NOTFOUND
ENDLOOP
CLOSEMICURSOR
END
/
SELECT*FROMEMPLEADO_BK
Ejemplo#38:
SETSERVEROUTPUTON
DECLARE
CURSORMICURSORISSELECT*FROMHR.EMPLOYEES
TYPETLISTAISTABLEOFHR.EMPLOYEES%ROWTYPE
TYPETINDICEISTABLEOFNUMBERINDEXBYPLS_INTEGER
LISTA1TLISTA
LISTA2TINDICE
BEGIN
OPENMICURSOR
LOOP
FETCHMICURSORBULKCOLLECTINTOLISTA1LIMIT25
FORIIN1..LISTA1.COUNTLOOP
LISTA2(I):=LISTA1(I).EMPLOYEE_ID
ENDLOOP
FORALLIIN1..LISTA1.COUNT
UPDATEHR.EMPLOYEESSETSALARY=1000WHEREEMPLOYEE_ID=
LISTA2(I)
EXITWHENMICURSOR%NOTFOUND
ENDLOOP
CLOSEMICURSOR
END
/
SELECTLAST_NAME,SALARYFROMHR.EMPLOYEES
DERECHOSDEEJECUCIN
Cuandocreamosunsubprogramaeldueodelsubprogramaenelmomentode
sucreacinyejecucinelusuariopierdesusrolesysoloquedanpresentesus
privilegiosdeobjetoydesistema.
Asimismocuandocreamosunsubprogramapuedeserejecutadoconlos
derechosdelcreadoroporelejecutador.
Pordefaultseejecutaconlosderechosdelcreador.
Paracrearunsubprogramaqueseejecuteconlospermisosdelejecutadorse
debetenerpresentelasiguientesintaxis:
CREATEORREPLACEPROCEDURE<NOMBRE_PROCEDURE>(<PARAMETROS>)
AUTHIDCURRENT_USERIS <CODIGO>
Asimismotenerpresentealmomentodecrearunsubprogramaconlaopcinde
AUTHIDCURRENT_USER:
OperacionesDMLyprivilegiosdeobjetosobretablassonresueltaspor
losprivilegiosdelinvocadordelsubprograma.
Otrassentenciascomollamadasafunciones,procedures,paquetes
sonresueltosconlosderechosdelcreador.

ProgramacinOrientadaaObjetosenPL/SQL
PLSQLpermitetrabajarconprogramacinorientadaaobjetos,demodoque
podamosinclusoguardarobjetosentablasypoderloextraerconatributosy
mtodos.
Sintaxis:
Ejemplo#39:
CREATEORREPLACETYPEPERSONAASOBJECT
(
CODIGONUMBER,
NOMBREVARCHAR(20),
APELLIDOVARCHAR(25),
MEMBERFUNCTIONGET_NOMBRECOMPLETORETURNVARCHAR
)NOTFINAL
/
CREATEORREPLACETYPEBODYPERSONAIS
MEMBERFUNCTIONGET_NOMBRECOMPLETORETURNVARCHAR
IS
BEGIN
RETURNNOMBRE||''||APELLIDO
END
END
/
PordefaultlasclasessonFINAL,locualindicaquenopermiteusarseen
herencias.
Asimismopodemostrabajarconherencia.
Ejemplo#40:
EstamoscreandolaclaseEMPLEADOheredandoatributosymtodosdelaclase
PERSONA.
CREATEORREPLACETYPEEMPLEADOUNDERPERSONA
(
SUELDONUMBER,
OVERRIDINGMEMBERFUNCTIONGET_NOMBRECOMPLETORETURNVARCHAR,
MEMBERPROCEDURESPU_ACTUALIZAR_SUELDO(PSUELDONUMBER)
)NOTFINAL
/
CREATEORREPLACETYPEBODYEMPLEADOIS
OVERRIDINGMEMBERFUNCTIONGET_NOMBRECOMPLETORETURNVARCHAR
IS
BEGIN
RETURNLOWER(NOMBRE||''||APELLIDO)
END
MEMBERPROCEDURESPU_ACTUALIZAR_SUELDO(PSUELDONUMBER)IS
BEGIN
SUELDO:=PSUELDO
END
END
/
Overridingpermitelasobreescrituradeunsubprogramadelpadre.
Tambinestpermitidopolimorfismo.
Enlossiguientespasoscrearemosunatablabasadaennuestroobjeto
EMPLEADOylomanipularemos.
Ejemplo#41:
CREATETABLETEMPLEADOOFEMPLEADO
INSERTINTOTEMPLEADOVALUES(EMPLEADO(1,'FRANCISCO','RICCIO',8000))
SELECT*FROMTEMPLEADO
SELECTE.GET_NOMBRECOMPLETO(),E.*FROMTEMPLEADOE
SETSERVEROUTPUTON
DECLARE
V_OBJETOEMPLEADO
BEGIN
SELECTVALUE(E)INTOV_OBJETOFROMTEMPLEADOE
V_OBJETO.SPU_ACTUALIZAR_SUELDO(1000)
DBMS_OUTPUT.PUT_LINE('EMPLEADO:
'||V_OBJETO.GET_NOMBRECOMPLETO()||'SUELDO=
'||TO_CHAR(V_OBJETO.SUELDO))
END
/
SihubiramoscreadolavariableV_OBJETOcomoPERSONA,estaramos
trabajandoconpolimorfismo,demodoquelavariablesedeclaradeunaclase
baseysecreaconclasesderivadas.

Você também pode gostar