MERCADOS FINANCIEROS

lunes, 30 de abril de 2018

Backing Up in NOARCHIVELOG Mode: Example

SQL> SHUTDOWN IMMEDIATE;

SQL> STARTUP FORCE DBA;
SQL> SHUTDOWN IMMEDIATE;

RMAN> STARTUP MOUNT;
RMAN> BACKUP COPIES 2 INCREMENTAL LEVEL 0 MAXSETSIZE 10M DATABASE; RMAN> ALTER DATABASE OPEN;
 

miércoles, 4 de abril de 2018

.PROFILE ORACLE SINGLE

export AWT_TOOLKIT=XToolkit
export ORACLE_BASE=/u01/app/oracledb
export ORACLE_HOME=/u01/app/oracledb/product/11.2.0/db_1
export ORACLE_SID=USCS90TS
export TZ=America/Bogota
export PATH=$ORACLE_HOME/bin:$ORACLE_HOME/OPatch:/usr/sbin:/bin:/usr/X11/bin:/usr/dt/bin:/usr/openwin/bin:/usr/ccs/bin:/usr/local/bin::/usr/local/bin:/home/oracle:.
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$ORACLE_HOME/oracm/lib
export CLASSPATH=$ORACLE_HOME/jdbc:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib$ORACLE_HOME/network/jlib
export NLS_DATE_FORMAT='DD/MM/YYYY HH24:MI:SS'
export TNS_ADMIN=/u01/app/oracledb/product/11.2.0/db_1/network/admin
export TEMP=/tmp
export TMPDIR=/tmp
ulimit -n 65536
# Alias
alias sql='sqlplus / as sysdba'

martes, 20 de marzo de 2018

Relacion de Confianza Solaris 11

Relación de confianza SSH

Este articulo se refiere a la creación de un certificado SSH para poder conectarnos a maquina unix sin necesidad de clave

1. Conectarse al solaris con el usuario oracle
2. Crear una llave de tipo DSA con una longitud de 1024 bits para el protocolo SSHv2 con una frase de paso (passphrase) nula (ingresar ENTER cuando se solicite la frase de paso):
Ejecutar el siguiente comando y seguir los pasos :
ssh-keygen -t dsa -b 1024
Generating public/private dsa key pair.
Enter file in which to save the key (/export/home/usuario/.ssh/id_dsa): [ENTER]
Created directory '/export/home/usuario/.ssh'.
Enter passphrase (empty for no passphrase): [ENTER]
Enter same passphrase again: [ENTER]
Your identification has been saved in /export/home/usuario/.ssh/id_dsa.
Your public key has been saved in /export/home/usuario/.ssh/id_dsa.pub.
The key fingerprint is:
18:c8:a8:80:32:bf:12:d3:4b:1d:f6:ae:35:d7:e4:e0 usuario@servidor
Este comando genera una llave privada contenida en el archivo $HOME/.ssh/id_dsa y una llave pública contenida en el archivo $HOME/.ssh/id_dsa.pub.
3. Transferir de forma segura la llave pública creada en el servidor y colocarla en el directorio .ssh recién creado:
cd .ssh
scp id_dsa.pub usuario@cliente:.ssh/id_dsa.pub
id_dsa.pub           100% |*************************|   600       00:00
4. Acceder al cliente con el usuario por ssh y crear el archivo authorized_keys. Este archivo debe contener la llave id_dsa.pub (y el resto de las llaves, en caso de que se requiera configurar más de una):
ssh usuario@cliente
cd .ssh
cat id_dsa.pub >> authorized_keys
chmod 600 authorized_keys
rm id_dsa.pub
5. Probar el acceso al servidor desde el cliente:
ssh usuario@servidor
The authenticity of host 'solaris' can't be established.
RSA key fingerprint in md5 is: 77:83:db:48:12:ea:15:70:04:ec:8c:22:36:de:b4:15
Are you sure you want to continue connecting(yes/no)? yes

martes, 27 de febrero de 2018

CREAR ALERTAS ENTERPRISE MANAGER

Forzamos la generación de alertas cargando el número de cursores abiertos en una sesión en OEM. Para ello ejecutamos el siguiente fragmento de código que genera 250 cursores, y esperaremos a que aparezca la alerta crítica en OEM.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
DECLARE
CURSOR my_cursor IS
  SELECT level, CURSOR(SELECT dummy FROM dual) FROM dual CONNECT BY level < 250;
  l_level USER_TABLES.TABLE_NAME%TYPE;
  l_outer_count PLS_INTEGER := 0;
  l_inner_count PLS_INTEGER := 0;
  l_dummy VARCHAR2(20);
  c_dummy SYS_REFCURSOR;
BEGIN
  OPEN my_cursor;
  LOOP
    FETCH my_cursor INTO l_level, c_dummy;
    EXIT WHEN my_cursor%NOTFOUND;
    l_outer_count := l_outer_count + 1;
    DBMS_OUTPUT.PUT_LINE('Outer Loop Count: ' || l_outer_count || ', Level: ' || l_level);
 
    l_inner_count := 0;
    LOOP
      FETCH c_dummy  INTO l_dummy;
      EXIT WHEN c_dummy%NOTFOUND;
      l_inner_count := l_inner_count + 1;
      DBMS_OUTPUT.PUT_LINE('Inner Loop Count: ' || l_inner_count || ', Level: ' || l_level);
    END LOOP;
 
  END LOOP;
  DBMS_LOCK.SLEEP(600);
  CLOSE my_cursor; -- Closes all cursor resources here (c_dummy and my_cursor)
END;
/
En un intervalo de 5 minutos aparecera en la página principal de OEM la alerta con severidad Crítica. Una vez hemos comprobado que funciona correctamente y nuestro script ha terminado, podemos reevaluar la alerta manualmente para hacer que desaparezca.
En la página principal de OEM ->
-> Click Alerta “Maxium Cursor Usage (value = ###)” ->
-> Click “Reevaluate Alert”
Borrar las métricas definidas por usuario es trivial.
Click “User-Defined Metrics” ->
-> Seleccionamos nuestra alerta “Cursor Usage” ->
-> Click “Delete” ->
-> Click “Yes”
5. Además de las métricas por defecto y las que podemos definir nosotros (Métricas Definidas por Usuario), también podemos definir umbrales para métricas basadas en BASELINES. Son las llamadas ADAPTIVE METRICS. Ya haremos pruebas con BASELINES en la sección de “Performance Management”, así que en este ejercicio definiremos los umbrales para una métrica de ejemplo “Number of Transactions (per second)”. El BASELINE que utilizaremos será el de la ventana activa en movimiento correspondiente a la ventana de retención de las estadísticas de AWR.
En la Página principal de OEM ->
-> Click “Baseline Metric Thresholds” ->
-> View = “Basic Metrics” ->
-> Click “Number of Transactions (per second)” ->
-> Critical = “Very High (0.99)” ->
-> Warning = “High (0.95)” ->
-> Ocurrences = 1 ->
-> Click “Preview” (veremos los umbrales sobre la gráfica) ->
-> Click “Apply Thresholds”
Ejecutamos el siguiente script en la BD de OEM para generar un número elevado de transacciones por segundo. Mi sistema acepta hasta 10.000 transacciones por segundo (TPS). Para una BD sin apenas transacciones por segundo, un número superior a 100 TPS debería ser suficiente para forzar la alerta.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
-- Borramos la tabla de pruebas "TEST"
DROP TABLE test PURGE;
CREATE TABLE test (
    c NUMBER
) TABLESPACE USERS;
 
-- Configuración entorno
SET ECHO OFF
SET FEEDBACK OFF
SET VERIFY OFF
 
-- PL/SQL para generar n TPS
DECLARE
    tps NUMBER := &1;
BEGIN
    tps := (tps / 2);
    FOR i IN 1..180
    LOOP
    FOR i IN 1..tps
        LOOP
            INSERT INTO test VALUES(1);
            COMMIT;
            DELETE test WHERE rownum < 2;
            COMMIT;
        END LOOP;
    DBMS_LOCK.SLEEP(1);
END LOOP;
END;
/
Al cabo de unos minutos veremos una alerta con severidad crítica en la página principal de la BD de OEM (HOME). Este tipo de alertas es muy interesante para monitorizar situaciones anómalas en base al rendimiento “habitual” de la BD.
1
2
-- Borramos la tabla de pruebas
DROP TABLE TEST PURGE;

miércoles, 17 de enero de 2018

Oracle Limits

Logical Database Limits

ItemType of LimitLimit Value
IndexesMaximum per tableUnlimited
IndexesTotal size of indexed column75% of the database block size minus some overhead
ColumnsPer table1000 columns maximum
ColumnsPer index (or clustered index)32 columns maximum
ColumnsPer bitmapped index30 columns maximum
ConstraintsMaximum per columnUnlimited
SubqueriesMaximum levels of subqueries in a SQL statementUnlimited in the FROM clause of the top-level query
255 subqueries in the WHERE clause
PartitionsMaximum length of linear partitioning key4 KB - overhead
PartitionsMaximum number of columns in partition key16 columns
PartitionsMaximum number of partitions allowed per table or index1024K - 1
SubpartitionsMaximum number of subpartitions in a composite partitioned table1024K - 1
RowsMaximum number per tableUnlimited
System Change Numbers (SCNs)Maximum281,474,976,710,656, which is 281 trillion SCNs
Stored PackagesMaximum sizeApproximately 6,000,000 lines of code.
Trigger Cascade LimitMaximum valueOperating system-dependent, typically 32
Users and RolesMaximum2,147,483,638
TablesMaximum per clustered table32 tables
TablesMaximum per databaseUnlimited
A.2 Physical Database Limits
ItemType of LimitLimit Value
Database Block SizeMinimum2048 bytes; must be a multiple of operating system physical block size
Database Block SizeMaximumOperating system dependent; never more than 32 KB
Database BlocksMinimum in initial extent of a segment2 blocks
Database BlocksMaximum per datafilePlatform dependent; typically 222 - 1 blocks
ControlfilesNumber of control files1 minimum; 2 or more (on separate devices) strongly recommended
ControlfilesSize of a control fileMaximum of 201031680 logical blocks
Database filesMaximum per tablespaceOperating system dependent; usually 1022
Database filesMaximum per database65533
May be less on some operating systems
Limited also by size of database blocks and by the DB_FILES initialization parameter for a particular instance
Database extentsMaximum per dictionary managed tablespace4 GB * physical block size (with K/M modifier); 4 GB (without K/M modifier)
Database extentsMaximum per locally managed (uniform) tablespace2 GB * physical block size (with K/M modifier); 2 GB (without K/M modifier)
Database file sizeMaximumOperating system dependent. Limited by maximum operating system file size. See the Bigfile Tablespaces and Smallfile (traditional) Tablespaces rows for more information about the maximum database file size in these types of tablespaces.
MAXEXTENTSDefault valueDerived from tablespace default storage or DB_BLOCK_SIZE initialization parameter
MAXEXTENTSMaximumUnlimited
Redo Log FilesMaximum number of logfilesLimited by value of MAXLOGFILES parameter in the CREATE DATABASE statement
Control file can be resized to allow more entries; ultimately an operating system limit
Redo Log FilesMaximum number of logfiles per groupUnlimited
Redo Log File SizeMinimum size4 MB
Redo Log File SizeMaximum SizeOperating system limit; typically 2 GB
TablespacesMaximum number per database64 K
Number of tablespaces cannot exceed the number of database files because each tablespace must include at least one file
Bigfile TablespacesNumber of blocksA bigfile tablespace contains only one datafile or tempfile, which can contain up to approximately 4 billion ( 232 ) blocks. The maximum size of the single datafile or tempfile is 128 terabytes (TB) for a tablespace with 32 K blocks and 32 TB for a tablespace with 8 K blocks.
Smallfile (traditional) TablespacesNumber of blocksA smallfile tablespace is a traditional Oracle tablespace, which can contain 1022 datafiles or tempfiles, each of which can contain up to approximately 4 million (222) blocks.
External Tables fileMaximum sizeDependent on the operating system.
An external table can be composed of multiple files.

lunes, 23 de octubre de 2017

ORACLE FECHA HORA DIFERENTES BASES DE DATOS

root@USBLDMD1012:~# date
Thursday, January 26, 2017 03:54:10 PM COT
root@USBLDMD1012:~# date -u
Thursday, January 26, 2017 08:54:14 PM GMT
srvctl setenv database -d ORCL -t "TZ=America/Bogota"
srvctl setenv database -d ACME -t "TZ=America/New_york"
srvctl setenv listener -l listener -t "TZ=America/Bogota"

export TZ=America/Bogota

select * from nls_database_parameters

martes, 3 de octubre de 2017

UTL_CALL_STACK

UTL_CALL_STACK : Get Detailed Information About the Currently Running Subprogram in Oracle Database 12c Release 1 (12.1)

Oracle database 12c introduced the UTL_CALL_STACK package to allow programmatic access to the call stack and error stack, giving much greater flexibility for debugging and error handling of PL/SQL code. This is only a replacement for the existing functionality if you need the extra level of control. The existing functionality in the DBMS_UTILITY package is still available and has not been deprecated.

Call Stack

The call stack allows you to identify exactly where you are in the currently running code, which includes information about nesting of subprogram calls. In previous releases this information was displayed using the DBMS_UTILITY.FORMAT_CALL_STACK function, as shown below.
-- Procedure to display the call stack.
CREATE OR REPLACE PROCEDURE display_call_stack AS
BEGIN
  DBMS_OUTPUT.put_line('***** Call Stack Start *****');
  DBMS_OUTPUT.put_line(DBMS_UTILITY.format_call_stack);
  DBMS_OUTPUT.put_line('***** Call Stack End *****');
END;
/

-- Test package to show a nested call.
CREATE OR REPLACE PACKAGE test_pkg AS
  PROCEDURE proc_1;
  PROCEDURE proc_2;
  PROCEDURE proc_3;
END;
/

CREATE OR REPLACE PACKAGE BODY test_pkg AS

  PROCEDURE proc_1 AS
  BEGIN
    proc_2;
  END;

  PROCEDURE proc_2 AS
  BEGIN
    proc_3;
  END;

  PROCEDURE proc_3 AS
  BEGIN
    display_call_stack;
  END;

END;
/


-- Run the test.
SET SERVEROUTPUT ON
EXEC test_pkg.proc_1;
***** Call Stack Start *****
----- PL/SQL Call Stack -----
  object      line  object
  handle    number
name
0xb6d4ac18         4  procedure TEST.DISPLAY_CALL_STACK
0xb6d14298
15  package body TEST.TEST_PKG
0xb6d14298        10  package body
TEST.TEST_PKG
0xb6d14298         5  package body TEST.TEST_PKG
0xb99fe7c8
1  anonymous block

***** Call Stack End *****

PL/SQL procedure successfully completed.

SQL>
As you can see, the output from the DBMS_UTILITY.FORMAT_CALL_STACK function is rather ugly and we have no control over it, other than to manually parse it.
The UTL_CALL_STACK package contains APIs to display the contents of the call stack in a more readable form.
  • DYNAMIC_DEPTH : The number of subprograms on the call stack, starting at the current position in the call stack, to the initial call.
  • LEXICAL_DEPTH : Lexical depth of the subprogram within the current call.
  • UNIT_LINE : Line number in the subprogram of the current call.
  • SUBPROGRAM : Subprogram name associated with the current call.
  • CONCATENATE_SUBPROGRAM : Returns the UNIT.SUBPROGRAM.LOCAL_SUBPROGRAM form of the subprogram name.
  • OWNER : The owner of the subprogram associated with the current call.
  • CURRENT_EDITION : The edition of the subprogram associated with the current call.
The following example recreates the DISPLAY_CALL_STACK procedure to use the UTL_CALL_STACK package, then re-runs the test.
-- Procedure to display the call stack.
CREATE OR REPLACE PROCEDURE display_call_stack AS
  l_depth PLS_INTEGER;
BEGIN
  l_depth := UTL_CALL_STACK.dynamic_depth;

  DBMS_OUTPUT.put_line('***** Call Stack Start *****');

  DBMS_OUTPUT.put_line('Depth     Lexical   Line      Owner     Edition   Name');
  DBMS_OUTPUT.put_line('.         Depth     Number');
  DBMS_OUTPUT.put_line('--------- --------- --------- --------- --------- --------------------');

  FOR i IN 1 .. l_depth LOOP
    DBMS_OUTPUT.put_line(
      RPAD(i, 10) ||
      RPAD(UTL_CALL_STACK.lexical_depth(i), 10) ||
      RPAD(TO_CHAR(UTL_CALL_STACK.unit_line(i),'99'), 10) ||
      RPAD(NVL(UTL_CALL_STACK.owner(i),' '), 10) ||
      RPAD(NVL(UTL_CALL_STACK.current_edition(i),' '), 10) ||
      UTL_CALL_STACK.concatenate_subprogram(UTL_CALL_STACK.subprogram(i))
    );
  END LOOP; 

  DBMS_OUTPUT.put_line('***** Call Stack End *****');
END;
/


-- Run the test.
SET SERVEROUTPUT ON
EXEC test_pkg.proc_1;
***** Call Stack Start *****
Depth     Lexical   Line      Owner     Edition   Name
.         Depth     Number
--------- --------- --------- --------- --------- --------------------
1         0          13       TEST                DISPLAY_CALL_STACK
2         1          15       TEST                TEST_PKG.PROC_3
3         1          10       TEST                TEST_PKG.PROC_2
4         1           5       TEST                TEST_PKG.PROC_1
5         0           1                           __anonymous_block
***** Call Stack End *****

PL/SQL procedure successfully completed.

SQL>
Starting with the call to DISPLAY_CALL_STACK, we can work back through all the nested calls to the original anonymous block. The output includes the procedure names in the package as well as the associated line numbers of the calls. If we wanted to, we could have displayed the output in reverse order, starting at the top-level call.
-- Procedure to display the call stack.
CREATE OR REPLACE PROCEDURE display_call_stack AS
  l_depth PLS_INTEGER;
BEGIN
  l_depth := UTL_CALL_STACK.dynamic_depth;

  DBMS_OUTPUT.put_line('***** Call Stack Start *****');

  DBMS_OUTPUT.put_line('Depth     Lexical   Line      Owner     Edition   Name');
  DBMS_OUTPUT.put_line('.         Depth     Number');
  DBMS_OUTPUT.put_line('--------- --------- --------- --------- --------- --------------------');

  FOR i IN REVERSE 1 .. l_depth LOOP
    DBMS_OUTPUT.put_line(
      RPAD(i, 10) ||
      RPAD(UTL_CALL_STACK.lexical_depth(i), 10) ||
      RPAD(TO_CHAR(UTL_CALL_STACK.unit_line(i),'99'), 10) ||
      RPAD(NVL(UTL_CALL_STACK.owner(i),' '), 10) ||
      RPAD(NVL(UTL_CALL_STACK.current_edition(i),' '), 10) ||
      UTL_CALL_STACK.concatenate_subprogram(UTL_CALL_STACK.subprogram(i))
    );
  END LOOP; 

  DBMS_OUTPUT.put_line('***** Call Stack End *****');
END;
/


-- Run the test.
SET SERVEROUTPUT ON
EXEC test_pkg.proc_1;
***** Call Stack Start *****
Depth     Lexical   Line      Owner     Edition   Name
.         Depth     Number
--------- --------- --------- --------- --------- --------------------
5         0           1                           __anonymous_block
4         1           5       TEST                TEST_PKG.PROC_1
3         1          10       TEST                TEST_PKG.PROC_2
2         1          15       TEST                TEST_PKG.PROC_3
1         0          13       TEST                DISPLAY_CALL_STACK
***** Call Stack End *****

PL/SQL procedure successfully completed.

SQL>
You now have programmatic control to interrogate and display the call stack if you need to.

Error Stack

Exceptions are often handled by exception handlers and re-raised. In some cases, exceptions in nested calls result in different errors being produced by the error handler of the calling routine. The error stack allows you to display chains of errors, making it easier to determine the real cause of the issue. In previous releases this information was displayed using the DBMS_UTILITY.FORMAT_ERROR_STACK function, as shown below.
-- Procedure to display the call stack.
CREATE OR REPLACE PROCEDURE display_error_stack AS
BEGIN
  DBMS_OUTPUT.put_line('***** Error Stack Start *****');
  DBMS_OUTPUT.put_line(DBMS_UTILITY.format_error_stack);
  DBMS_OUTPUT.put_line('***** Error Stack End *****');
END;
/

-- Test package to show a nested call.
CREATE OR REPLACE PACKAGE test_pkg AS
  PROCEDURE proc_1;
  PROCEDURE proc_2;
  PROCEDURE proc_3;
END;
/

CREATE OR REPLACE PACKAGE BODY test_pkg AS

  PROCEDURE proc_1 AS
  BEGIN
    proc_2;
  EXCEPTION
    WHEN OTHERS THEN
      display_error_stack;
  END;

  PROCEDURE proc_2 AS
  BEGIN
    proc_3;
  EXCEPTION
    WHEN OTHERS THEN
      RAISE DUP_VAL_ON_INDEX;
  END;

  PROCEDURE proc_3 AS
  BEGIN
    RAISE NO_DATA_FOUND;
  EXCEPTION
    WHEN OTHERS THEN
      RAISE TOO_MANY_ROWS;
  END;

END;
/


-- Run the test.
SET SERVEROUTPUT ON
EXEC test_pkg.proc_1;
***** Error Stack Start *****
ORA-00001: unique constraint (.) violated
ORA-06512: at "TEST.TEST_PKG", line
16
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512:
at "TEST.TEST_PKG", line 24
ORA-01403: no data found

***** Error Stack End *****

PL/SQL procedure successfully completed.

SQL>
The output from DBMS_UTILITY.FORMAT_ERROR_STACK function is fine, but there are occasional formatting errors and we can't order the output to suit our taste.
The UTL_CALL_STACK package contains APIs to display the contents of the error stack.
  • ERROR_DEPTH : The number of errors on the error stack.
  • ERROR_MSG : The error message associated with the current line in the error stack.
  • ERROR_NUMBER : The error number associated with the current line in the error stack.
The following example recreates the DISPLAY_ERROR_STACK procedure to use the UTL_CALL_STACK package, then re-runs the test.
-- Procedure to display the call stack.
CREATE OR REPLACE PROCEDURE display_error_stack AS
  l_depth PLS_INTEGER;
BEGIN
  l_depth := UTL_CALL_STACK.error_depth;

  DBMS_OUTPUT.put_line('***** Error Stack Start *****');

  DBMS_OUTPUT.put_line('Depth     Error     Error');
  DBMS_OUTPUT.put_line('.         Code      Message');
  DBMS_OUTPUT.put_line('--------- --------- --------------------');

  FOR i IN 1 .. l_depth LOOP
    DBMS_OUTPUT.put_line(
      RPAD(i, 10) ||
      RPAD('ORA-' || LPAD(UTL_CALL_STACK.error_number(i), 5, '0'), 10) ||
      UTL_CALL_STACK.error_msg(i)
    );
  END LOOP; 

  DBMS_OUTPUT.put_line('***** Error Stack End *****');
END;
/


-- Run the test.
SET SERVEROUTPUT ON
EXEC test_pkg.proc_1;
***** Error Stack Start *****
Depth     Error     Error
.         Code      Message
--------- --------- --------------------
1         ORA-00001 unique constraint (.) violated

2         ORA-06512 at "TEST.TEST_PKG", line 16

3         ORA-01422 exact fetch returns more than requested number of rows

4         ORA-06512 at "TEST.TEST_PKG", line 24

5         ORA-01403 no data found

***** Error Stack End *****

PL/SQL procedure successfully completed.

SQL>
In the previous example, the display order matches the DBMS_UTILITY.FORMAT_ERROR_STACK output, which reports last to first in the chain. We could easily reverse it to display first to last.
-- Procedure to display the call stack.
CREATE OR REPLACE PROCEDURE display_error_stack AS
  l_depth PLS_INTEGER;
BEGIN
  l_depth := UTL_CALL_STACK.error_depth;

  DBMS_OUTPUT.put_line('***** Error Stack Start *****');

  DBMS_OUTPUT.put_line('Depth     Error     Error');
  DBMS_OUTPUT.put_line('.         Code      Message');
  DBMS_OUTPUT.put_line('--------- --------- --------------------');

  FOR i IN REVERSE 1 .. l_depth LOOP
    DBMS_OUTPUT.put_line(
      RPAD(i, 10) ||
      RPAD('ORA-' || LPAD(UTL_CALL_STACK.error_number(i), 5, '0'), 10) ||
      UTL_CALL_STACK.error_msg(i)
    );
  END LOOP; 

  DBMS_OUTPUT.put_line('***** Error Stack End *****');
END;
/


-- Run the test.
SET SERVEROUTPUT ON
EXEC test_pkg.proc_1;
***** Error Stack Start *****
Depth     Error     Error
.         Code      Message
--------- --------- --------------------
5         ORA-01403 no data found

4         ORA-06512 at "TEST.TEST_PKG", line 24

3         ORA-01422 exact fetch returns more than requested number of rows

2         ORA-06512 at "TEST.TEST_PKG", line 16

1         ORA-00001 unique constraint (.) violated

***** Error Stack End *****

PL/SQL procedure successfully completed.

SQL>

Backtrace

Backtrace shows a walk through the call stack from the line where the exception was raised, to the last call before the exception was trapped. This shows the propagation of the exception, which allows you to identify the actual line that caused the problem. In previous releases this information was displayed using the DBMS_UTILITY.FORMAT_ERROR_BACKTRACE function, as shown below.
-- Procedure to display the call stack.
CREATE OR REPLACE PROCEDURE display_backtrace AS
BEGIN
  DBMS_OUTPUT.put_line('***** Backtrace Start *****');
  DBMS_OUTPUT.put_line(DBMS_UTILITY.format_error_backtrace);
  DBMS_OUTPUT.put_line('***** Backtrace End *****');
END;
/

-- Test package to show a nested call.
CREATE OR REPLACE PACKAGE test_pkg AS
  PROCEDURE proc_1;
  PROCEDURE proc_2;
  PROCEDURE proc_3;
END;
/

CREATE OR REPLACE PACKAGE BODY test_pkg AS

  PROCEDURE proc_1 AS
  BEGIN
    proc_2;
  EXCEPTION
    WHEN OTHERS THEN
      display_backtrace;
  END;

  PROCEDURE proc_2 AS
  BEGIN
    proc_3;
  END;

  PROCEDURE proc_3 AS
  BEGIN
    RAISE NO_DATA_FOUND;
  END;

END;
/


-- Run the test.
SET SERVEROUTPUT ON
EXEC test_pkg.proc_1;
***** Backtrace Start *****
ORA-06512: at "TEST.TEST_PKG", line 18
ORA-06512: at "TEST.TEST_PKG", line
13
ORA-06512: at "TEST.TEST_PKG", line 5

***** Backtrace End *****

PL/SQL procedure successfully completed.

SQL>
With the exception of some minor formatting issues, this output is fine and will probably be OK for most situations.
The UTL_CALL_STACK package contains APIs to display the backtrace.
  • BACKTRACE_DEPTH : The number of backtrace messages on the error stack.
  • BACKTRACE_LINE : Line number in the subprogram of the current call.
  • BACKTRACE_UNIT : Subprogram name associated with the current call.
The following example recreates the DISPLAY_BACKTRACE procedure to use the UTL_CALL_STACK package, then re-runs the test.
-- Procedure to display the call stack.
CREATE OR REPLACE PROCEDURE display_backtrace AS
  l_depth PLS_INTEGER;
BEGIN
  l_depth := UTL_CALL_STACK.backtrace_depth;

  DBMS_OUTPUT.put_line('***** Backtrace Start *****');

  DBMS_OUTPUT.put_line('Depth     BTrace     BTrace');
  DBMS_OUTPUT.put_line('.         Line       Unit');
  DBMS_OUTPUT.put_line('--------- --------- --------------------');

  FOR i IN 1 .. l_depth LOOP
    DBMS_OUTPUT.put_line(
      RPAD(i, 10) ||
      RPAD(TO_CHAR(UTL_CALL_STACK.backtrace_line(i),'99'), 10) ||
      UTL_CALL_STACK.backtrace_unit(i)
    );
  END LOOP; 

  DBMS_OUTPUT.put_line('***** Backtrace End *****');
END;
/


-- Run the test.
SET SERVEROUTPUT ON
EXEC test_pkg.proc_1;
***** Backtrace Start *****
Depth     BTrace     BTrace
.         Line       Unit
--------- --------- --------------------
1           5       TEST.TEST_PKG
2          13       TEST.TEST_PKG
3          18       TEST.TEST_PKG
***** Backtrace End *****

PL/SQL procedure successfully completed.

SQL>
There is very little you can do with the backtrace, other than reordering it. The "ORA-06512" error is not included, but this is implied because it is a backtrace message. The following example shows the backtrace in reverse order.
-- Procedure to display the call stack.
CREATE OR REPLACE PROCEDURE display_backtrace AS
  l_depth PLS_INTEGER;
BEGIN
  l_depth := UTL_CALL_STACK.backtrace_depth;

  DBMS_OUTPUT.put_line('***** Backtrace Start *****');

  DBMS_OUTPUT.put_line('Depth     BTrace     BTrace');
  DBMS_OUTPUT.put_line('.         Line       Unit');
  DBMS_OUTPUT.put_line('--------- --------- --------------------');

  FOR i IN REVERSE 1 .. l_depth LOOP
    DBMS_OUTPUT.put_line(
      RPAD(i, 10) ||
      RPAD(TO_CHAR(UTL_CALL_STACK.backtrace_line(i),'99'), 10) ||
      UTL_CALL_STACK.backtrace_unit(i)
    );
  END LOOP; 

  DBMS_OUTPUT.put_line('***** Backtrace End *****');
END;
/


-- Run the test.
SET SERVEROUTPUT ON
EXEC test_pkg.proc_1;
***** Backtrace Start *****
Depth     BTrace     BTrace
.         Line       Unit
--------- --------- --------------------
3          18       TEST.TEST_PKG
2          13       TEST.TEST_PKG
1           5       TEST.TEST_PKG
***** Backtrace End *****

PL/SQL procedure successfully completed.

SQL>

DBMS_UTILITY.EXPAND_SQL_TEXT

DBMS_UTILITY.EXPAND_SQL_TEXT : Expand SQL References to Views in Oracle Database 12c Release 1 (12.1)

Views can be a useful way to hide complexity from developers, but that can in turn cause problems. It's easy to write apparently simple statements, that result in extremely complex SQL being sent to the server. The DBMS_UTILITY.EXPAND_SQL_TEXT procedure expands references to views, turning them into subqueries in the original statement. A simple example of this is shown below.
Create a view containing a join.
CONN scott/tiger@pdb1

CREATE OR REPLACE VIEW emp_v AS
SELECT e.empno,
       e.ename,
       e.job,
       e.mgr,
       e.hiredate,
       e.sal,
       e.comm,
       e.deptno,
       d.dname
FROM   emp e
       JOIN dept d ON e.deptno = d.deptno;
The view has hidden the complexity of the join, allowing us to use an extremely simple query.
SELECT * FROM emp_v;
We can see the real SQL statement processed by the server by expanding the statement.
SET SERVEROUTPUT ON 
DECLARE
  l_clob CLOB;
BEGIN
  DBMS_UTILITY.expand_sql_text (
    input_sql_text  => 'SELECT * FROM emp_v',
    output_sql_text => l_clob
  );

  DBMS_OUTPUT.put_line(l_clob);
END;
/

SELECT "A1"."EMPNO" "EMPNO",
       "A1"."ENAME" "ENAME",
       "A1"."JOB" "JOB","A1"."MGR" "MGR",
       "A1"."HIREDATE" "HIREDATE",
       "A1"."SAL" "SAL",
       "A1"."COMM" "COMM",
       "A1"."DEPTNO" "DEPTNO",
       "A1"."DNAME" "DNAME"
FROM   (SELECT "A2"."EMPNO_0" "EMPNO",
               "A2"."ENAME_1" "ENAME",
               "A2"."JOB_2" "JOB",
               "A2"."MGR_3" "MGR",
               "A2"."HIREDATE_4" "HIREDATE",
               "A2"."SAL_5" "SAL",
               "A2"."COMM_6" COMM",
               "A2"."QCSJ_C000000000400000_7" "DEPTNO",
               "A2"."DNAME_9" "DNAME"
         FROM  (SELECT "A4"."EMPNO" "EMPNO_0",
                       "A4"."ENAME" "ENAME_1",
                       "A4"."JOB" "JOB_2",
                       "A4"."MGR" "MGR_3",
                       "A4"."HIREDATE" "HIREDATE_4",
                       "A4"."SAL" "SAL_5",
                       "A4"."COMM" "COMM_6",
                       "A4"."DEPTNO" "QCSJ_C000000000400000_7",
                       "A3"."DEPTNO" "QCSJ_C000000000400001",
                       "A3"."DNAME" "DNAME_9"
                FROM   SCOTT."EMP" "A4",
                       SCOTT."DEPT" "A3"
                WHERE  "A4"."DEPTNO"="A3"."DEPTNO") "A2"
       ) "A1"

PL/SQL procedure successfully completed.

SQL>

sábado, 30 de septiembre de 2017

AUTHID CURRENT (USER - DEFINER)


AUTHID CURRENT_USER
Specify CURRENT_USER to indicate that the package executes with the privileges of CURRENT_USER. This clause creates an invoker's rights package.
This clause also specifies that external names in queries, DML operations, and dynamic SQL statements resolve in the schema of CURRENT_USER. External names in all other statements resolve in the schema in which the package resides.

AUTHID DEFINER

Specify DEFINER to indicate that the package executes with the privileges of the owner of the schema in which the package resides and that external names resolve in the schema where the package resides. This is the default and creates a definer's rights package.


WARNING: Writing PL/SQL code with the default authid definer, can facilitate SQL injection attacks, because an intruder would get privileges that they would not get if they used authid current_user.


PL/SQL Function Result Cache

On the PL/SQL Function Result Cache

By Steven Feuerstein Oracle Employee ACE 

Best practices—and preparation—for PL/SQL in Oracle Database 11g
I have been reading that Oracle is launching the 11th release of its database. Very exciting! But here's the problem: I don't think I'll be able to use it for another two years. So why should I even care about the new PL/SQL features of this future (for me) release?
Ah, yes, the real world. Oracle comes out with a new database release, and by the time it does so, its developers are already focused on the next new release. People like me start writing about, demonstrating, and even training on the newer release. And then there's almost everybody else: still on older releases, hoping and praying that someday maybe their management will see fit to catch up.
I feel your pain.
Having said that, I do think it makes an awful lot of sense to learn now about what Oracle Database 11g will have to offer you and your company in the future. The reason is very simple: once you see what is going to be available in Oracle Database 11g, you will probably change the way you write your code now !
I would say that the single most important new PL/SQL feature in Oracle Database 11g is thePL/SQL function result cache . Quite a mouthful, but then it is quite a feature.
I offer in this answer a quick overview of this feature, and I conclude by discussing how knowing about this feature should affect the way you write PL/SQL programs for earlier Oracle Database releases.
Suppose I am on a team that is building a human resources application. The employees table is one of the key structures, holding all the data for all the employees. Hundreds of users execute numerous programs in the application that read from this table—and read from it very often. Yet the table changes relatively infrequently, perhaps once or twice an hour. As a result, the application code repeatedly retrieves from the block buffer cache what is mostly static data, enduring the overhead of checking to see if the particular query has already been parsed, finding the data in the buffer, and returning it.
The team needs to improve the performance of querying data from the employees table. Currently, we use the following function to return a row from the employees table: 
FUNCTION one_employee (employee_id_in 
IN employees.employee_id%TYPE)
   RETURN employees%ROWTYPE
IS
    l_employee   employees%ROWTYPE;
BEGIN
   SELECT *
      INTO l_employee
      FROM employees
    WHERE employee_id = employee_id_in;

    RETURN l_employee;
EXCEPTION
    WHEN NO_DATA_FOUND
    THEN
       /* Return an empty record. */
       RETURN l_employee;
END one_employee;

In Oracle Database 11g, however, we can add a line to the header of this function as follows:  
FUNCTION one_employee (employee_id_in 
IN employees.employee_id%TYPE)
   RETURN employees%ROWTYPE
   RESULT_CACHE RELIES_ON (employees)
IS
    l_employee   employees%ROWTYPE;
BEGIN
.
.
.
 
This RESULT_CACHE clause tells Oracle Database that it should remember (store in a special in-memory result cache) each record retrieved for a specific employee ID number. And when a session executes this function and passes in an employee ID that was previously stored, the PL/SQL runtime engine will not execute the function body, which includes that query.
Instead, it will simply retrieve the record from the cache and return that data immediately. The result is much faster retrieval.
In addition, by specifying RELIES_ON (employees), we inform Oracle Database that if any session commits changes to that table, any data in the result cache drawn from the table must be invalidated. The next call to the one_employee function would then have to execute the query and retrieve the data fresh from the table.
Because the cache is a part of the System Global Area (SGA), its contents are available to all sessions connected to the instance. Furthermore, Oracle Database will apply its "least recently used algorithm" to the cache, to ensure that the most recently accessed data will be preserved in the cache.
Prior to Oracle Database 11g, a similar kind of caching was possible with package-level collections, but this cache is session-specific and located in the Process Global Area (PGA). This means that if I have 1,000 different sessions running the application, I could use up an enormous amount of memory in addition to that consumed by the SGA.
The PL/SQL function result cache minimizes the amount of memory needed to cache and share this data across all sessions. This low memory profile, plus the automatic purge of cached results whenever changes are committed, makes this feature of Oracle Database 11g very practical for optimizing performance in PL/SQL applications.

Analyze Performance and PGA Memory Impact

To test the improvement in performance and the impact on PGA memory over repeated queries of the data, I put together a set of scripts, available at oracle.com/technetwork/oramag/oracle/07-sep/o57plsql.zip, that compares three different ways to retrieve a row of employee data:
1. Execute the query repeatedly
2. Cache all the rows of the employees table in a packaged collection and then retrieve the data from that cache
3. Use the PL/SQL function result cache to avoid repetitive querying
To try this out yourself, unzip the o57plsql.zip file and run the 11g_emplu.tst script. It should take about five or six seconds to complete, and then you should see results like this: 
PGA before tests are run:
session PGA:  910860 bytes

Execute query each time 
Elapsed: 4.5 seconds. 
session PGA:  910860 bytes

Cache table in PGA memory 
Elapsed: .11 seconds. 
session PGA: 1041932 bytes

Oracle Database 11
                               g result cache 
Elapsed: .27 seconds. 
session PGA: 1041932 bytes
                            
Here are my conclusions from this admittedly incomplete analysis: 
  • The Oracle Database 11g PL/SQL function result cache is, indeed, much faster than repetitive querying. In this test, it was over an order of magnitude faster.  
  • A packaged collection cache is even faster, most likely because the PL/SQL runtime engine can access the data from PGA memory rather than SGA memory. Unfortunately, this also means that the consumption of memory occurs on a per-session basis, which is not very scalable. 
  • The packaged collection approach consumed additional PGA memory, but the Oracle Database 11g function result cache did not.
And then, of course, there are the other key advantages of the function result cache: automatic invalidation of cache contents when a dependent table is changed, the fact that the cache is shared across sessions, and the application of the least recently used algorithm to the memory in the cache.

So Why Should You Care Now?

"All right," you may be saying to yourself, "It's cool. Super cool. But I still can't use it for two years or more, so what good does that do me now?"
You may not be able to use the PL/SQL function result cache yet, but you can write your code now so that when you eventually upgrade to Oracle Database 11g, you will be able to quickly and easily use this cache in your application code.
In other words, you can and should prepare now for this future feature.
How do you do that? By placing all your queries (at least those against tables that change infrequently but are queried often) inside functions, so that you can easily add the RESULT_CACHE clause.
Think about it: today you probably don't do that. Instead, whenever you need data from the database, you write the required query, right there in the application logic you are writing (whether that logic resides in the back end—other PL/SQL programs—or the front end—languages such as Java).

Next Steps



And that same query (or some minor variation on it) will likely appear in multiple places in your application code. Why not? It is so easy to write those SQL statements; that's one of the beauties of PL/SQL. But that ease of use in executing SQL inside PL/SQL makes us all take SQL for granted, and when you upgrade to Oracle Database 11g, you will pay the price.
If after upgrading, you want to take advantage of RESULT_CACHE, you will have to find every affected SQL statement and either put the RESULT_CACHE hint inside that query (that's right, this feature is available natively within SQL as well as for functions) or construct the function, put the query inside it, find each of the applicable queries, and replace the query with the function call.
Certainly both of these approaches are eminently doable, but they are also very unlikely to happen. IT managers are loathe to go into existing, working production code and upset the applecart by making lots of changes.
If, conversely, you start right now , in Oracle9i Database or Oracle Database 10g, to place your queries inside functions, you will almost instantly be able to upgrade your code to use this fantastic new feature when you upgrade to Oracle Database 11g.
And, best of all, the application code that calls the function will not have to be changed at all! Your manager will be very impressed.
And that is why you should learn about the new features of Oracle Database 11g. Today.