0% found this document useful (0 votes)
14 views24 pages

PLSQL

The document provides an extensive overview of SQL and PL/SQL operators, variable declarations, SQL commands, joins, functions, collections, cursors, packages, and dynamic SQL. It includes examples of various SQL operations, such as creating tables, inserting data, and using different types of joins, as well as detailed descriptions of PL/SQL data types and structures. Additionally, it covers the use of cursors and packages in PL/SQL programming, along with dynamic SQL execution methods.

Uploaded by

Marcelo Armocida
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views24 pages

PLSQL

The document provides an extensive overview of SQL and PL/SQL operators, variable declarations, SQL commands, joins, functions, collections, cursors, packages, and dynamic SQL. It includes examples of various SQL operations, such as creating tables, inserting data, and using different types of joins, as well as detailed descriptions of PL/SQL data types and structures. Additionally, it covers the use of cursors and packages in PL/SQL programming, along with dynamic SQL execution methods.

Uploaded by

Marcelo Armocida
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 24

OPERADORES

IN =ANY = SOME
IS EMPTY PARA VARRAY O TABLE
IS A SET PARA VARRAY O TABLE
MEMBER OF SOLO PARA COLECCIONES ESCALARES

VARIABLES

VARIABLE DECLARACION SIN DECLARE. PARA REFRERENCIAR, USAR : ANTES


END POINTS (PARA GOTO) SE DECLARAN <<END_POINT>>
CREATE TABLE XX AS SELECT SDKJFSDKLJFS FROM YYYY

INSERT ALL
WHEN CONDICION THEN
INTO TABLA (CAMPOS) VALUES (VALORES)
WHEN CONDICION THEN
INTO TABLA (CAMPOS) VALUES (VALORES)
ELSE
INTO TABLA (CAMPOS) VALUES (VALORES)
SELECT * FROM DUAL;
SQL

INNER JOIN
SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date
FROM suppliers
INNER JOIN orders -- REGISTROS DE LA PRIMERA Q ESTEN EN LA SEGUNDA
ON suppliers.supplier_id = orders.supplier_id;

LEFT OUTER JOIN


SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date
FROM suppliers -- REGISTROS DE LA PRIMERA AUNQUE NO ESTEN EN
SEGUNDA, IGUAL A SELECT CON (+)
LEFT OUTER JOIN orders
ON suppliers.supplier_id = orders.supplier_id;

RIGHT OUTER JOIN


SELECT orders.order_id, orders.order_date, suppliers.supplier_name
FROM suppliers -- REGISTROS DE LA 2DA AUNQUE NO ESTEN EN 1RA, IGUAL
A SELECT CON (+)
RIGHT OUTER JOIN orders
ON suppliers.supplier_id = orders.supplier_id;

FULL OUTER JOIN


SELECT suppliers.supplier_id, suppliers.supplier_name, orders.order_date
FROM suppliers -- TODOS LOS REGISTROS DE AMBAS TABLAS , IGUAL A
SELECT CON UNION
FULL OUTER JOIN orders
ON suppliers.supplier_id = orders.supplier_id;

NATURAL JOIN TOMA CAMPOS DEL MISMO NOMBRE


SELECT table1.column, table2.column
FROM table1
NATURAL JOIN table2
NONEQUIJOINS : cuando las tablas no tienen campo en comun, pero si una condicion
select a.x,b.y from a join b on a.x between b.a and b.b

PIVOT
SELECT * FROM
(
SELECT customer_ref, product_id
FROM orders
)
PIVOT
(
COUNT(product_id) - siempre una funcion de agrupacion.
FOR product_id IN (10, 20, 30) para estos productos
)
ORDER BY customer_ref;

LIKE
SELECT *
FROM jobs WHERE job_id LIKE 'SA\_%' ESCAPE '\'; (EL GUION BAJO REEMPLAZA UN CARACTER)

AMPERSAND Doble ampersand

SELECT employee_id, last_name, phone_number SELECT first_name, job_id, &&col


FROM employees FROM employees
WHERE last_name = &LASTNAME WHERE job_id IN ('MK_MAN','SA_MAN')
OR employee_id = &EMPNO; ORDER BY &col;

EL & VA A PEDIR UN PROMPT SET VERIFY ON|OFF. displaya mensajes


antes y despues de la sustitucion
SELECT &SELECT_CLAUSE
FROM &FROM_CLAUSE
SET DEFINE ON|OFF, DEFINE, DEFINE a:=b
WHERE &WHERE_CLAUSE
ORDER BY &ORDER_BY_CLAUSE

NVL2(original, ifnotnull, ifnull), COALESCE(expr1, expr2,…,exprn)


devuelve el primer param no null
NULLIF(ifunequal, comparison_term),si son SELECT
iguales, nada si no, el primero CASE substr(1234,1,3)
WHEN '134' THEN '1234 is a match'
WHEN '1235' THEN '1235 is a match'
WHEN concat('1','23') THEN concat('1','23')||' is a
match'
ELSE 'no match'
END
FROM dual;

SELECT last_name < ANY Less than the highest


FROM employees > ANY More than the lowest
WHERE salary > ALL = ANY Equivalent to IN
(SELECT salary > ALL More than the highest
FROM employees
WHERE last_name='Taylor') < ALL Less than the lowest
ORDER BY last_name;
UNION Returns the combined rows from INSERT ALL
two queries, sorting them and WHEN 1=1 THEN
removing duplicates. INTO emp_no_name
(department_id,job_id,salary,commission_pct,hire_date)
UNION ALL Returns the combined rows
VALUES (department_id,job_id,salary,commission_pct,hire_date)
from two queries without sorting WHEN department_id <> 80 THEN
or removing duplicates. INTO emp_non_sales (employee_id,department_id,salary,hire_date)
INTERSECT Returns only the rows that VALUES (employee_id,department_id,salary,hire_date)
occur in both queries’ result sets, WHEN department_id = 80 THEN
sorting them and removing duplicates. INTO emp_sales (employee_id,salary,commission_pct,hire_date)
MINUS Returns only the rows in the first VALUES (employee_id,salary,commission_pct,hire_date)
result set that do not appear in SELECT
employee_id,department_id,job_id,salary,commission_pct,hire_date
the second result set, sorting them and FROM hr.employees
removing duplicates.
WHERE hire_date > sysdate - 30;
MERGE INTO employees e
USING new_employees n
ON (e.employee_id = n.employee_id)
WHEN MATCHED THEN
UPDATE SET e.salary=n.salary
WHEN NOT MATCHED THEN
INSERT (employee_id, last_name, salary,
email, job_id)

VALUES (n.employee_id, n.last_name,


n.salary, n.email, n.job_id);
SELECT *
SAVEPOINT first;
FROM regions FOR UPDATE; lockea los registros queriados
ROLLBACK TO SAVEPOINT first;
FUNCIONES ANALITICAS

P.E. para no usar groupo by y poder traer todos los campos

select a.*,(select count(*) from tabla where campo=a.algo) from tabla a;

select a.*,count(*) over(partition by v_tipo),

count(*) over(partition by otro order by algo rows range between unbounded/1/2 preceding
and current row/ current and following rows) from varios a
DATA TYPE COMPUESTAS

PL/SQL Record Type


A PL/SQL record type is a record data structure, which means it is a row of data across two or
more fields of data. The following program creates a PL/SQL record type, assigns values to it, and
prints the output:

TYPE title_record IS RECORD


( title VARCHAR2(60) , subtitle VARCHAR2(60));

-- Declare a variable that uses the record structure.


lv_title_record TITLE_RECORD;
BEGIN
-- Assign values to the record structure.
lv_title_record.title := 'Star Trek';
lv_title_record.subtitle := 'Into Darkness';
-- Print the elements of the structure.
dbms_output.put_line('['||lv_title_record.title||']'||
'['||lv_title_record.subtitle||']');
END;
/

PL/SQL Table Type


TYPE population IS TABLE OF NUMBER -- Associative array type
INDEX BY VARCHAR2(64); -- indexed by string

city_population population; -- Associative array variable

SQL UDT
A SQL UDT is an object type. Like packages, object types have a specification and a body. The
specification is the type and includes a list of attributes (or fields) and methods. COMO EN C, JAVA

CREATE OR REPLACE TYPE hobbit IS OBJECT


( name VARCHAR2(20)
, CONSTRUCTOR FUNCTION hobbit RETURN SELF AS RESULT
, CONSTRUCTOR FUNCTION hobbit
( name VARCHAR2 ) RETURN SELF AS RESULT
, MEMBER FUNCTION get_name RETURN VARCHAR2
, MEMBER FUNCTION set_name (name VARCHAR2)
RETURN hobbit
, MEMBER FUNCTION to_string RETURN VARCHAR2 )
INSTANTIABLE NOT FINAL;
COLLECTIONS

Collections are arrays and lists. Arrays differ from lists in that they use a sequentially
numbered index, while lists use a nonsequential numeric or unique string index. Arrays are
densely populated lists because they have sequentially numbered indexes. While lists can
have densely populated numeric indexes, they can also be sparsely populated, meaning there
are gaps in a sequence or the indexes are not sequential.
Oracle supports three types of collections. Two are both SQL and PL/SQL data types,
depending on how you define them: varray and nested table (or table). The third collection
type is a PL/SQL-only data type, called an associative array. The associative array is also
known as a PL/SQL table or an index-by table.

collection may be a varray or nested table (Oracle uses the term nested table to
disambiguate the difference between a programming data type and a physical table) of
a scalar or composite data type. A collection of a scalar data type is an Attribute Data
Type (ADT), as qualified in Chapter 3, while a collection of a composite data type is a
user-defined type (UDT). Collections may use an object data type in a SQL context and a
record data type in a PL/SQL context.

An associative array (formerly called PL/SQL table or index-by table) is a set of key-value pairs.
Each key is a unique index, used to locate the associated value with the
syntax variable_name(index).

2 columnas

DECLARE

TYPE population IS TABLE OF NUMBER -- Associative array type


INDEX BY VARCHAR2(64); -- indexed by string

city_population population; -- Associative array variable


i VARCHAR2(64); -- Scalar variable

BEGIN
-- Add elements (key-value pairs) to associative array:

city_population('Smallville') := 2000;
city_population('Midland') := 750000;
city_population('Megalopolis') := 1000000;
-- Change value associated with key 'Smallville':
city_population('Smallville') := 2001;
-- Print associative array:
i := city_population.FIRST; -- Get first element of array
WHILE i IS NOT NULL LOOP
DBMS_Output.PUT_LINE
('Population of ' || i || ' is ' || city_population(i));
i := city_population.NEXT(i); -- Get next element of array
END LOOP;
END;

------ otro ejemplo

DECLARE
TYPE sum_multiples IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER;
n PLS_INTEGER := 5; -- number of multiples to sum for display
sn PLS_INTEGER := 10; -- number of multiples to sum
m PLS_INTEGER := 3; -- multiple
FUNCTION get_sum_multiples ( multiple IN PLS_INTEGER, num IN PLS_INTEGER ) RETURN sum_multiples IS
s sum_multiples;
BEGIN
FOR i IN 1..num LOOP
s(i) := multiple * ((i * (i + 1)) / 2); -- sum of multiples
END LOOP;
RETURN s;
END get_sum_multiples;

A varray (variable-size array) is an array whose number of elements can vary from zero (empty) to
the declared maximum size.

TYPE Foursome IS VARRAY(4) OF VARCHAR2(15); -- VARRAY type


-- varray variable initialized with constructor:
team Foursome := Foursome('John', 'Mary', 'Alberto', 'Juanita'); largo es fijo

a nested table is a column type that stores an unspecified number of rows in no particular order.
TYPE Roster IS TABLE OF VARCHAR2(15); -- nested table type

-- nested table variable initialized with constructor:

names Roster := Roster('D Caruso', 'J Hamil', 'D Piro', 'R Singh');
Anidados:

DECLARE
TYPE tb1 IS TABLE OF VARCHAR2(20); -- nested table of strings
vtb1 tb1 := tb1('one', 'three');

TYPE ntb1 IS TABLE OF tb1; -- nested table of nested tables of strings


vntb1 ntb1 := ntb1(vtb1);

TYPE tv1 IS VARRAY(10) OF INTEGER; -- varray of integers


TYPE ntb2 IS TABLE OF tv1; -- nested table of varrays of integers
vntb2 ntb2 := ntb2(tv1(3,5), tv1(5,7,3));

BEGIN
vntb1.EXTEND;
vntb1(2) := vntb1(1);
vntb1.DELETE(1); -- delete first element of vntb1
vntb1(2).DELETE(1); -- delete first string from second table in nested table
END;

DELETE Procedure Deletes elements from collection.

TRIM Procedure Deletes elements from end of varray or nested


table.

TRIM(M) Procedure Deletes M elements from end of varray or


nested table.

EXTEND Procedure Adds elements to end of varray or nested table.

EXISTS(M) Function Returns TRUE if and only if specified element of


varray or nested table exists.

FIRST Function Returns first index in collection.

LAST Function Returns last index in collection.

COUNT Function Returns number of elements in collection.


LIMIT Function Returns maximum number of elements that
collection can have.

PRIOR Function Returns index that precedes specified index.

NEXT Function Returns index that succeeds specified index.


CURSORES

VARIABLE: REF cursor, no atado a una query especifica y puede pasarse entre programas

CREATE OR REPLACE FUNCTION get_direct_reports(


in_manager_id IN employees.manager_id%TYPE)
RETURN SYS_REFCURSOR AS

c_direct_reports SYS_REFCURSOR;
BEGIN
OPEN c_direct_reports FOR SELECT employee_id, etc FROM employees
WHERE algo;
RETURN c_direct_reports;
END;

ATRIBUTOS

%FOUND Returns TRUE only when a DML statement has changed a row.
%ISOPEN Always returns FALSE for any implicit cursor.
%NOTFOUND Returns TRUE when a DML statement fails to change a row.
%ROWCOUNT Returns the number of rows changed by a DML statement or the number

DECLARE
lv_id item.item_id%TYPE;
lv_title VARCHAR2(60);
CURSOR c IS
SELECT item_id , item_title FROM item;

BEGIN
OPEN c;
LOOP
FETCH c INTO lv_id , lv_title;
EXIT WHEN c%NOTFOUND;
dbms_output.put_line('Title ['||lv_title||']');
END LOOP;
CLOSE c;
END;
PACKAGES

CREATE PACKAGE name AS -- specification (visible part)


-- public type and item declarations
-- subprogram specifications
END [name];

CREATE PACKAGE BODY name AS -- body (hidden part)


-- private type and item declarations
-- subprogram bodies
[BEGIN
-- initialization statements]
END [name];
SQL DINAMICO
Dynamic SQL is a programming methodology for generating and running SQL statements at run
time.

DBMS_SQL para SQL Dyn. Sino usamos SQL nativo (EXECUTE IMMEDIATE) o ambos.

DBMS_SQL.OPEN_CURSOR(sec_level,treat_as_client) RETURN INTEGER;


DBMS_SQL.PARSE ( cursor,sentencia)
DBMS_SQL.BIND_VARIABLE (cursor,':nombre',tipo(par))
DBMS_SQL.BIND_ARRAY ( cursor,':nombre',tipo(tabla),1ro,ultimo)
. Para asignar placeholders para los inputs que tenga la llamada. el parse se puede hacer muchas veces
y si recibimos un array, se ejecuta una vez por posicion del array.

DBMS_SQL.DEFINE_COLUMN (cursor,posicion,tipo)
DEFINE_COLUMN_LONG(cursor,posicion)
DEFINE_ARRAY( cursor,posicion,tipo): definen variables como un select into
el array es la coleccion de las columnas en las que queremos meter las filas ,traidas con FETCH_ROWS).

Cuando hacemos fetch las filas se copian a buffer hasta que hacemos COLUMN_VALUE, ahi se copian a
la tabla que se paso como argumento de COLUMN_VALUE.

DBMS_SQL.EXECUTE(cursor) / DBMS_SQL.EXECUTE_AND_FETCH

DBMS_SQL.FETCH_ROWS(cursor)

VARIABLE_VALUE, VARIABLE_PKG, COLUMN_VALUE or COLUMN_VALUE_LONG


DBMS_SQL.COLUMN_VALUE (cursor,posicion,valor out)
DBMS .CLOSE_CURSOR(cursor)

EJEMPLOS

CREATE OR REPLACE PROCEDURE demo(salary IN NUMBER) AS


cursor_name INTEGER;
rows_processed INTEGER;
BEGIN
cursor_name := dbms_sql.open_cursor;
DBMS_SQL.PARSE(cursor_name, 'DELETE FROM emp WHERE sal > :x',
DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(cursor_name, ':x', salary);
rows_processed := DBMS_SQL.EXECUTE(cursor_name);
DBMS_SQL.CLOSE_CURSOR(cursor_name);
EXCEPTION
WHEN OTHERS THEN
DBMS_SQL.CLOSE_CURSOR(cursor_name);
END;
-------
CREATE OR REPLACE PROCEDURE copy ( source IN VARCHAR2, destination IN VARCHAR2) IS
id_var NUMBER;
name_var VARCHAR2(30);
birthdate_var DATE;
source_cursor INTEGER;
destination_cursor INTEGER;
ignore INTEGER;

BEGIN

source_cursor := dbms_sql.open_cursor;
DBMS_SQL.PARSE(source_cursor,
'SELECT id, name, birthdate FROM ' || source,
DBMS_SQL.NATIVE);
DBMS_SQL.DEFINE_COLUMN(source_cursor, 1, id_var);
DBMS_SQL.DEFINE_COLUMN(source_cursor, 2, name_var, 30);
DBMS_SQL.DEFINE_COLUMN(source_cursor, 3, birthdate_var);
ignore := DBMS_SQL.EXECUTE(source_cursor);

destination_cursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(destination_cursor,
'INSERT INTO ' || destination ||
' VALUES (:id_bind, :name_bind, :birthdate_bind)',
DBMS_SQL.NATIVE);

LOOP
IF DBMS_SQL.FETCH_ROWS(source_cursor)>0 THEN
-- get column values of the row
DBMS_SQL.COLUMN_VALUE(source_cursor, 1, id_var);
DBMS_SQL.COLUMN_VALUE(source_cursor, 2, name_var);
DBMS_SQL.COLUMN_VALUE(source_cursor, 3, birthdate_var);

-- Bind the row into the cursor that inserts into the destination table.
DBMS_SQL.BIND_VARIABLE(destination_cursor, ':id_bind', id_var);
DBMS_SQL.BIND_VARIABLE(destination_cursor, ':name_bind', name_var);
DBMS_SQL.BIND_VARIABLE(destination_cursor, ':birthdate_bind',
birthdate_var);
ignore := DBMS_SQL.EXECUTE(destination_cursor);
ELSE
EXIT;
END IF;
END LOOP;

COMMIT;
DBMS_SQL.CLOSE_CURSOR(source_cursor);
DBMS_SQL.CLOSE_CURSOR(destination_cursor);
EXCEPTION
WHEN OTHERS THEN
IF DBMS_SQL.IS_OPEN(source_cursor) THEN
DBMS_SQL.CLOSE_CURSOR(source_cursor);
END IF;
IF DBMS_SQL.IS_OPEN(destination_cursor) THEN
DBMS_SQL.CLOSE_CURSOR(destination_cursor);
END IF;
RAISE;
END;
/
Example 4: RETURNING clause

With this clause, INSERT, UPDATE, and DELETE statements can return values of expressions in bind
variables.

If a single row is inserted, updated, or deleted, then use DBMS_SQL.BIND_VARIABLE to bind these
outbinds. To get the values in these bind variables, call DBMS_SQL.VARIABLE_VALUE

Note:This process is similar to DBMS_SQL.VARIABLE_VALUE, which must be called after running a PL/SQL
block with an outbind inside DBMS_SQL.
i) Single-row insert

CREATE OR REPLACE PROCEDURE single_Row_insert


(c1 NUMBER, c2 NUMBER, r OUT NUMBER) is
c NUMBER;
n NUMBER;
begin
c := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(c, 'INSERT INTO tab VALUES (:bnd1, :bnd2) ' ||
'RETURNING c1*c2 INTO :bnd3', DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(c, 'bnd1', c1);
DBMS_SQL.BIND_VARIABLE(c, 'bnd2', c2);
DBMS_SQL.BIND_VARIABLE(c, 'bnd3', r);
n := DBMS_SQL.EXECUTE(c);
DBMS_SQL.VARIABLE_VALUE(c, 'bnd3', r); -- get value of outbind variable
DBMS_SQL.CLOSE_CURSOR(c);
END;
/

-- CREATE OR REPLACE PROCEDURE updarray


(tab IN VARCHAR2,
keycol IN VARCHAR2,
valcol IN VARCHAR2,
keylist IN DBMS_SQL.NUMBER_TABLE,
vallist IN DBMS_SQL.NUMBER_TABLE)
IS
cur INTEGER := DBMS_SQL.OPEN_CURSOR;
fdbk INTEGER;
mytab DBMS_SQL.NUMBER_TABLE;
BEGIN
DBMS_SQL.PARSE
(cur,
'UPDATE ' || tab ||
' SET ' || valcol || ' = :vals ' ||
' WHERE ' || keycol || ' = :keys',
DBMS_SQL.NATIVE);

DBMS_SQL.BIND_ARRAY (cur, 'keys', keylist);


DBMS_SQL.BIND_ARRAY (cur, 'vals', vallist);

fdbk := DBMS_SQL.EXECUTE (cur);

DBMS_SQL.CLOSE_CURSOR (cur);
END;
/
Now I can execute this "update by array" procedure for the sal column of the emp table.

DECLARE
emps DBMS_SQL.NUMBER_TABLE;
sals DBMS_SQL.NUMBER_TABLE;
BEGIN
emps (1) := 7499;
sals (1) := 2000;
emps (2) := 7521;
sals (2) := 3000;

updarray ('emp', 'empno', 'sal', emps, sals);


END;
SQL NATIVO
The EXECUTE IMMEDIATE statement is the means by which native dynamic SQL processes most
dynamic SQL statements.

sqlstring := q'{insert into x values( ' || i || ')}'; ESCAPE COMILLAS

execute immediate sqlstring;

EXECUTE IMMEDIATE 'UPDATE abcd ' ||


'SET efgh = :text_string WHERE efgh = :second_string'
USING 'qrst', 'mnop';

DECLARE
l_sql VARCHAR2(100);
l_ename emp.ename%TYPE;
BEGIN
l_sql := 'SELECT ename FROM emp WHERE empno = :empno';
EXECUTE IMMEDIATE l_sql INTO l_ename USING 1234;
END;
/

Dynamic Cursors
Sometimes the definition of the cursor may not be known until runtime. The following example shows
this along with access of an object that it not currently present. It should compile in any schema as
there are no direct references to database objects until runtime.

CREATE OR REPLACE
PROCEDURE DynamicCursor (p_parameter IN VARCHAR2) IS
TYPE cur_typ IS REF CURSOR;
c_cursor cur_typ;
l_query VARCHAR2(1000);
l_text VARCHAR2(100);
BEGIN

IF Length(p_parameter) > 10 THEN


l_query := 'SELECT ''The parameter ('' || :parameter || '') is too long'' AS text FROM dual';
ELSE
l_query := 'SELECT first_name || '' '' || last_name FROM users WHERE user_type = :parameter';
END IF;

OPEN c_cursor FOR l_query USING p_parameter;


LOOP
FETCH c_cursor INTO l_text;
EXIT WHEN c_cursor%NOTFOUND;
-- process row here
END LOOP;
CLOSE c_cursor;
END;

UTL_FILE
Subprogram Description

FCLOSE Procedure Closes a file


UTL_FILE.FCLOSE ( file IN OUT FILE_TYPE)
Subprogram Description

FCLOSE_ALL Procedure Closes all open file handles


UTL_FILE.FCLOSE_ALL;

FCOPY Procedure Copies a contiguous portion of a file to a newly created file

FFLUSH Procedure Physically writes all pending output to a file

FGETATTR Procedure Reads and returns the attributes of a disk file

FGETPOS Function Returns the current relative offset position within a file, in bytes

FOPEN Function Opens a file for input or output

UTL_FILE.FOPEN ( location IN VARCHAR2, filename IN VARCHAR2,


open_mode IN VARCHAR2, max_linesize IN BINARY_INTEGER)
RETURN file_type;

FOPEN_NCHAR Function Opens a file in Unicode for input or output

FREMOVE Procedure Deletes a disk file, assuming that you have sufficient privileges
UTL_FILE.FREMOVE ( location IN VARCHAR2, filename IN VARCHAR2);

FRENAME Procedure Renames an existing file to a new name, similar to the


UNIX mv function

FSEEK Procedure Adjusts the file pointer forward or backward within the file by the
number of bytes specified

GET_LINE Procedure Reads text from an open file


UTL_FILE.GET_LINE (
file IN UTL_FILE.FILE_TYPE,
buffer OUT VARCHAR2,
len IN BINARY_INTEGER DEFAULT NULL);

GET_LINE_NCHAR Procedure Reads text in Unicode from an open file

GET_RAW Function Reads a RAW string value from a file and adjusts the file pointer
ahead by the number of bytes read

IS_OPEN Function Determines if a file handle refers to an open file


UTL_FILE.IS_OPEN (
file IN UTL_FILE.FILE_TYPE)
RETURN BOOLEAN;

NEW_LINE Procedure Writes n line terminators to a file


UTL_FILE.NEW_LINE ( file IN UTL_FILE.FILE_TYPE, lines IN
BINARY_INTEGER := 1);

PUT Procedure Writes a string to a file (sin salto)


UTL_FILE.PUT ( file IN UTL_FILE.FILE_TYPE, buffer IN VARCHAR2);

PUT_LINE Procedure Writes a line to a file, + salto.


UTL_FILE.PUT_LINE (
file IN UTL_FILE.FILE_TYPE,
buffer IN VARCHAR2,
autoflush IN BOOLEAN DEFAULT FALSE);

PUT_LINE_NCHAR Procedure Writes a Unicode line to a file

PUT_NCHAR Procedure Writes a Unicode string to a file


Subprogram Description

PUTF Procedure A PUT procedure with formatting, puede venir con \n and %s
UTL_FILE.PUTF (
file IN UTL_FILE.FILE_TYPE,
format IN VARCHAR2,
[arg1 IN VARCHAR2 DEFAULT NULL,
...
arg5 IN VARCHAR2 DEFAULT NULL]);

PUTF_NCHAR Procedure A PUT_NCHAR procedure with formatting, and writes a Unicode


string to a file, with formatting

PUT_RAW Function Accepts as input a RAW data value and writes the value to the
output buffer

F1 := UTL_FILE.FOPEN('UTL_FILE_TEMP','u12345.tmp','R');
UTL_FILE.GET_LINE(F1,V1);
DBMS_OUTPUT.PUT_LINE('Get line: ' || V1);
UTL_FILE.FCLOSE(F1);

declare
handle utl_file.file_type;
my_world varchar2(4) := 'Zork';
begin
handle := utl_file.fopen('UTL_FILE_TEMP','u12345.tmp','a');
utl_file.putf(handle, '\nHello, world!\nI come from %s with %s.\n', my_world,
'greetings for all earthlings');
utl_file.fflush(handle);
utl_file.fclose(handle);
end;
JSON

DECLARE
je JSON_ELEMENT_T;
jo JSON_OBJECT_T;
BEGIN
je := JSON_ELEMENT_T.parse('{"name":"Radio controlled plane"}');
IF (je.is_Object) THEN
jo := treat(je AS JSON_OBJECT_T);
jo.put('price', 149.99);
END IF;
DBMS_OUTPUT.put_line(je.to_string);
END;

DECLARE
jo JSON_OBJECT_T;
ja JSON_ARRAY_T;
keys JSON_KEY_LIST;
keys_string VARCHAR2(100);
BEGIN
ja := new JSON_ARRAY_T;
jo := JSON_OBJECT_T.parse('{"name":"Beda",
"jobTitle":"codmonki",
"projects":["json", "xml"]}');
keys := jo.get_keys;
FOR i IN 1..keys.COUNT LOOP
ja.append(keys(i));
END LOOP;
keys_string := ja.to_string;
DBMS_OUTPUT.put_line(keys_string);
END;
/
You can use BULK COLLECT in all these forms:

SELECT column(s) BULK COLLECT INTO collection(s)


FETCH cursor BULK COLLECT INTO collection(s)
EXECUTE IMMEDIATE query_string BULK COLLECT INTO collection(s)
Here's a block of code that fetches all rows in the employees table with a single context switch, and
loads the data into a collection of records that are based on the table.

DECLARE
TYPE employee_info_t IS TABLE OF employees%ROWTYPE;
l_employees employee_info_t;
BEGIN
SELECT *
BULK COLLECT INTO l_employees
FROM employees
WHERE department_id = 50;
DBMS_OUTPUT.PUT_LINE (l_employees.COUNT);
END;
If you do not want to retrieve all the columns in a table, create your own user-defined record type and
use that to define your collection. All you have to do is make sure the list of expressions in the SELECT
match the record type's fields.

DECLARE
TYPE two_cols_rt IS RECORD (
employee_id employees.employee_id%TYPE,
salary employees.salary%TYPE
);

TYPE employee_info_t IS TABLE OF two_cols_rt;

l_employees employee_info_t;
BEGIN
SELECT employee_id, salary
BULK COLLECT INTO l_employees
FROM employees
WHERE department_id = 50;
DBMS_OUTPUT.PUT_LINE (l_employees.COUNT);
END;
Quick Tip

You can avoid the nuisance of declaring a record type to serve as the type for the collection through the
use of a "template cursor." This cursor should have the same select list as the BULK COLLECT query. You
can, however, leave off the WHERE clause and anything else after the FROM clause, because it will
never be used for anything but a %ROWTYPE declaration. Here's an example:

DECLARE
CURSOR employee_info_c IS
SELECT employee_id, salary
FROM employees ;

TYPE employee_info_t IS TABLE OF employee_info_c%ROWTYPE;

l_employees employee_info_t;
BEGIN
SELECT employee_id, salary
BULK COLLECT INTO l_employees
FROM employees
WHERE department_id = 10;
END;

CREATE OR REPLACE PROCEDURE procesamiento_masivo


AS
TYPE matriz_rowid IS TABLE OF ROWID;
TYPE matriz_col1 IS TABLE OF tabla_enorme.col1%TYPE;
TYPE matriz_col2 IS TABLE OF tabla_enorme.col2%TYPE;

CURSOR cur IS SELECT rowid, col1, col2


FROM tabla_enorme;
m_rowid matriz_rowid;
m_col1 matriz_col1;
m_col2 matriz_col2;
contador NUMBER := 100;

BEGIN
OPEN cur;
LOOP
FETCH cur BULK COLLECT
INTO m_rowid, m_col1, m_col2 LIMIT contador;
FOR i IN 1 .. m_rowid.count
LOOP
m_col1(i) := calculos(m_col1(i), m_col2(i));
END LOOP;
FORALL i IN 1 .. m_rowid.count
UPDATE tabla_enorme
SET col1 = m_col1(i)
WHERE rowid = m_rowid(i);
EXIT WHEN cur%NOTFOUND;
END LOOP;
CLOSE cur;
END;

Un cambio que puede mejorar el rendimiento aún mas, es que que en el FORALL, sustituir el
m_rowid.count, por m_rowid.last.
DECLARE
type clientes_array is table of XXX%rowtype index by binary_integer;
registros clientes_array;
errores NUMBER;
dml_errores EXCEPTION;
contador_errores number := 0;
PRAGMA exception_init(dml_errores, -24381);
cursor c is select * from XXX;
BEGIN
open c;
loop
fetch c BULK COLLECT INTO registros LIMIT 1000;
begin
FORALL i IN 1 .. registros.count SAVE EXCEPTIONS
insert into TRASPASO_BD_CLIENTE values registros(i);
EXCEPTION
WHEN dml_errores THEN
errores := SQL%BULK_EXCEPTIONS.COUNT;
contador_errores := contador_errores + errores;
FOR i IN 1..errores LOOP
dbms_output.put_line
(‘Se encontro el error ‘||;SQL%BULK_EXCEPTIONS(i).ERROR_INDEX ||
‘:’||SQL%BULK_EXCEPTIONS(i).ERROR_CODE);
end loop;
end;
exit when c%notfound;
END LOOP;
close c;
dbms_output.put_line( contador_errores );
end;
NOVEDADES EN 12

CREATE TABLE essay


2 ( essay_name VARCHAR2(30) DEFAULT essay_s.nextval
3 , essayist VARCHAR2(30) invisible
4 , published DATE DEFAULT TRUNC(SYSDATE)

id NUMBER GENERATED ALWAYS AS IDENTITY

SELECT i.item_title
2 FROM FABLE i WHERE XXXXX ORDER BY XXXXX
3 (OFFSET 20 ROWS ) / FETCH FIRST/NEXT N ROWS ONLY / FETCH FIRST 20 PERCENT ROWS
ONLY / WITH TIES, ONLY trae los N registros sean sus valores del order by iualrd o no. WITH TIES tae todos los
empatados tambien

You might also like