FORMATEANDO
RESULTADOS
Usar la opcion SET con las siguientes opciones:
DEFINE = Me mostrará todos los valores almacenados y en que estado se encuentran.
ECHO ON/OFF = Muestra/Oculta lo que se va haciendo
FEEDBACK ON/OFF = Muestra/Oculta la cantidad de filas retornadas por uan query
HEADING OFF/ON = Si esta en OFF, no aparece el encabezado de cada columna
LINESIZE Nº = Cant. de caracteres por linea, este valor por defecto es de 80
NUMWIDTH Nº = Se lo puede usar para modificar el ancho por defecto que poseen todas las columnas numéricas. Este valor por defecto es 10
NUMFORMAT ...... = Le doy un formato a todos los números
por igual. Algunos formatos son:
999,999.99 Pondrá , y . Si aparece un null, pondrá null
$9990 Pondrá 0 si viene un null. El signo $ aparecerá
con todos los números
PAGESIZE Nº = Cant. de filas por pagina, este valor por defecto es de 66
SCAN = Pone la sustitucion de variables en ON u OFF
SHOW ALL o COMANDO = Muestra en que estado está configurado un comando o todos ellos.
SQLCASE UPPER = Hace que lo que se busque en la BD sea en mayúscula, aún cuando el usuario la escriba en minúscula.
TRIMSPOOL OFF/ON = Cuando hacemos un spool a un archivo, al definir el LINESIZE, si pusimos muchos tambien nos vendran varios espacios en blanco al final de cada linea. Para evitar eso, ponemos a TRIMSPOOL en ON.
TERMOUT OFF/ON = Muestra/Oculta la salida de un script a la pantalla. Generalmente se lo pone en OFF al principio del archivo, y se lo pone en ON inmediatamente después del SPOOL, para que se vean los resultados.
RECSEP ON/OFF = Por default el parametro RECSEP esta seteado
en WRAP. Esto hace que despues de cada "wrapped record" se insertara el
caracter en que se haya seteado RECSEPCHAR, que por defecto es un espacio
en blanco. Poniendolo en OFF se eliminara la linea en blanco entre los
registros.
The recsep command has basically two functions:
1. SQL> set recsep off (returns all rows single-spaced)
2. SQL> set recsep each
(inserts a linefeed between each row/double-spaced)
UNDEFINE = Saca una variable definida
UNDERLINE = Sirve para modificar lo que aparece debajoi del titulo de cada columna (el default es ---).Este ejemplo pondrá el signo =.
VERIFY ON/OFF = Muestra/Oculta las lineas reemplazadas
NOTA = Poner antes que ningún comando las instrucciones
siguientes, esto hace que si había algo en la memoria, se lo resetee.
CLEAR BREAKS
CLEAR COMPUTES
Interacción
con el SQL
Con PROMPT muestro comentarios o acciones a la salida
del programa.
Usaré el ACCEPT para cargarle valores a una variable;
también puedo usar el & 2 veces, de esa manera no pregunta varias
veces por un mismo valor.
Cuando uso estos, en mi Select lo debo usar con un & adelante y
entre comillas simples. Si no quiero que salgan comentarios, antes del
ACCEPT pongo ECHO OFF y VERIFY OFF.
Ej:
accept mes number prompt 'Ingrese Mes a Calcular: '
Títulos
de Reportes
A los reportes o salidas de Información, le puedo poner un título
abajo y arriba. Para eso uso:
Para el superior:
TTITLE (center, left o right) ‘mi Titulo’
TTITLE center ‘Un titulo’ skip 1 right ‘Otro Título’
skip 2
O sea que se pueden poner varios, pero todos deben estar definidos al mismo tiempo. Además le puedo agregar el comando SKIP, el cual me permite dejar renglones en blanco.
Para el inferior:
BTITLE con las mismas opciones.
También puedo definir varios títulos con variables.
Ejemplo:
DEFINE LINE1 = ‘Primera línea al centro‘
DEFINE LINE2 = ‘Segunda línea a la izquierda ‘
DEFINE LINE3 = ‘Tercera línea a la derecha ‘
TTITLE CENTER LINE1 SKIP 1 LEFT LINE2 SKIP1 RIGHT LINE3
Para mostrar los números de paginas uso la función SQL.PNO.
Ejemplo:
TTITLE LEFT ‘Reporte Mensual’ RIGHT ‘PAGINA:’ FORMAT 999 SQL.PNO
SKIP 2
Para suprimir los Títulos, hago:
TTITLE OFF
BTITLE OFF
Formateando
Resultados
COLUMN col_name HEADING ‘titulo’ FORMAT a15
Formatea la salida de esa columna que aparezca en el select. Si necesito un título más largo, entonces puedo usar el | (pipe) dentro de mi título. Esto hará que lo que esté después del | aparezca en otro renglón.
Puedo hacer que si un resultado es muy largo, el mismo ocupe mas de
un renglón. Para ello agrego al final de mi comando COLUMN las distintas
opciones:
WORD_WRAPPED = Continúa una palabra
en otro renglón
WRAPPED =
TRUNC = La trunca (si es mas larga que mi
formato)
Para ver como están los atributos que le puse a las columnas
uso el comando
COLUMN col_name
Y para resetearlo uso:
COLUMN col_name CLEAR
El formato del comando COLUMN es el siguiente:
COLUMN nom_col HEADING ‘mi titulo’ NEW_VALUE variable_que_va_al_ttitulo
NOPRINT NULL texto_a_mostrar_caso_de_null OLD_VALUE variable_a_btitulo
WORD_WRAPPED
WRAPPED
TRUNC
El NOPRINT con el NEW_VALUE hace que una variable se "esconda" para
que luego la pueda imprimir en otro lado (por ejemplo en un título).
Ej. :
COLUMN today NEW_VALUE xtoday NOPRINT
Esto crea una nueva variable xtoday que contendrá el valor de
la variable today (se supone que este valor se repite constantemente),
le digo que NO la muestre en el Select. Si esa variable la pienso usar
en el Título de abajo, por cuestión de velocidad, conviene
ponerle OLD_VALUE en vez de NEW_VALUE
Corte
por Columna
Para que no se me repitan valores cuando hago una consulta con el order
by (por ejemplo el código de departamento), puedo ponerle un break,
de esa forma si un valor viene repetido, no lo pone. Uso:
BREAK ON break_column
Esto hace que cuando cambie el ítem, corta y vuelve a poner
los títulos de las columnas.
Si quiero que antes de que venga un nuevo valor, me deje un espacio
en blanco o una hoja en blanco, entonces hago:
BREAK ON break_column SKIP (N_renglones o PAGE)
Para ver todos los BREAKS que puse pongo
BREAK
Y para sacar todos pongo:
CLEAR BREAKS
Cálculos
Uno de los comandos mas importantes es el COMPUTE. Este me permite
sacar totales parciales por un campo particular. Su formato es:
BREAK ON break_column (acá puedo ponerle las opciones
de renglones)
COMPUTE función OF col_a_aplicar_funcion ON col_de_agrupamiento
En el COMPUTE puedo poner varias columnas, NO las debo separar por comas.
Ej:
COMPUTE sum OF col1 col2 col3 ON campo o REPORT
Si quiero distintos subtotales entonces los pondré en el BREAK
desde el mayor group hasta el menor. Ej:
BREAK ON company ON division ON Departamento SKIP 1
Si hago
BREAK ON REPORT ON col1
COMPUTE SUM OF ...... ON .......... REPORT
Se calcularán no sólo los subtotales por grupo, sino
que se agregará un renglón al final de todo con el valor
total de todo.
Las distintas opciones del BREAK ON son:
COL =
ROW = Fuerza BREAK con cada fila
PAGE = Cuando se llena una página
REPORT = Cuando fin del reporte
Las distintas opciones del SKIP son:
‘n filas’ = Salta esa cantidad de renglones
PAGE = Salta hasta una nueva página
Las distintas opciones del COMPUTE son:
SUM – MIN – MAX – AVG – STD
VAR – COUNT – NUM (como el count, pero cuenta los nulos)
Single Row Functions
Type | Function | Returns |
Number | abs(n) | Absolute value of n. i.e. removes the sign. |
ceil(n) | Smallest integer >=n | |
floor(n) | Largest integer <=n | |
mod(n,m) | Remainder of n divided by m | |
power(n,m) | n raised to the power m | |
round(n[,m]) | n rounded to m digits to the right of the decimal point. m = 0 by default. | |
sign(n) | -1 if n<0
0 if n=0 1 if n>09 |
|
sqrt(n) | Ö n | |
trunc(n[,m]) | as round but there is no rounding up. | |
Character | chr(n) | the character corresponding to the decimal value e.g. In the ascii character set chr(10) is a new line character. |
concat(s1,s2) | s1||s2 (used for portability where the ‘|’ character may cause problems) | |
initcap(s) | s with the first letter of each word in upper case | |
lower(s) | s with all letters lower case | |
lpad(s,n[,c]) | s left-padded with c’s to a size of n | |
ltrim(s1[,s2]) | s1 with letters in s2 trimmed from left until a letter not in s2 is found. | |
replace(s1,s2[,s3]) | s1 with all instances of s2 replaced by s3 | |
rpad(s,n[,c]) | as lpad but to the right | |
rtrim(s1,n,[s2) | as ltrim but to the right | |
substr(s1,n,m) | the m character long substring of s1 beginning with character n | |
translate(s1,s2,s3) | s1 but with each character in s2 replaced by the corresponding letter from s3. | |
upper(s) | s with all letters upper case. | |
Character returning number | ascii(c) | returns the decimal value of c in the character set of the database (note that this may not be ascii!!) |
instr(s1,s2[,n[,m]]) | returns the character position of the mth occurrence of the string s2 in s1 beginning with the nth character. | |
length(s1) | the length of s1 | |
Date | add_months(d,n) | the date n days after d |
last_day(d) | the date of the last day of the month which d is in | |
months_between(d1,d2) | number of months between d1 and d2; this is expressed as a floating point number calculated on the basis if 31 days per month. | |
next_day(d, day) | e.g. if day=Monday then returns the date of the first Monday after d. | |
round(d,f) | returns d rounded to the nearest f (e.g. ‘Day’, ‘Month’, etc) | |
sysdate | the current database date and time | |
trunc(d,f) | as round but truncates rather than rounds. | |
Conversion | to_char(d,f)
to_char(n,f) |
Converts a date or a number to characters. |
to_date(s1,f) | Converts a character string in format f to a date | |
to_number(c,f) | Converts a character string in format f to a number | |
Other | greatest(e1,e2….) | Whichever of e1, e2, etc is the greatest |
least(e1,e2,….) | Whichever of e1, e2, etc is the least | |
nvl(e1, e2) | e1 unless it is null in which case e2 | |
user | the current database username | |
Decode | decode | decode is not strictly a function but rather a bit of non-standard SQL syntax (for that reason its available in SQL but not in PL/SQL). |
Simulating
IF/THEN/ELSE logic
There is no IF command in SQL*Plus. However, you can use some of the
techniques shown above along with the DECODE operator to simulate an IF
command.
In this example, the user is asked to enter the number of a script
to run. The user’s answer is evaluated and the appropriate script is run.
If the user entered an incorrect value, the badscript.sql script is run
to display an error message.
Prompt ’1 - script1.sql’
prompt ’2 - script2.sql’
prompt ’3 - script3.sql’
accept script_number prompt - ’Enter the number of the script to run:
’
@formatoff
column script_name noprint new_value script_name_var
select decode ( &script_number,
1, ’script1.sql’,
2, ’script2.sql’,
3, ’script3.sql’,
’badscript.sql’) script_name
from dual;
@formaton
@&script_name_var
Copy Command
Probably the easiest way to copy data from one table to another is
to use
INSERT INTO table1 SELECT * FROM table2;
This method doesn’t work well with large tables because this command is processed as a single unit of work. Since you can’t have ORACLE do a commit in the middle of the insert, you have to have a rollback segment large enough to handle the complete transaction. It also won’t work if the source table has a LONG datatype.
You could write a store procedure that opens a cursor, does the inserts,
and does a commit after a certain number of rows. This can get tedious
if you have a large number of columns in the table, since you will have
to refer to each one in the INSERT command.
The SQL*Plus COPY command allows you continue to use simple SQL to
define the data that you are copying. It also allows you to take occasional
COMMITS during the copy operation.
One really nice thing about COPY is that it will work with tables that have LONG datatypes. You can’t use CREATE TABLE or INSERT to move data from one table to another if one of the columns is LONG. When using COPY, the SET LONG command tells SQL*Plus how much of the LONG data to copy.
The commit frequency is controlled by the ARRAYSIZE and COPYCOMMIT settings in your SQL*Plus session. The ARRAYSIZE setting determines how many rows are in a ’batch’. The COPYCOMMIT setting determines how many batches to process before doing a commit.
The COPY command requires that at least one of the tables be a remote table. It expects a SQL*Net connect string to identify the remote database. To copy one local table to another local table, simply specify the connect string for the local database.
The COPY command allows you to CREATE, REPLACE, INSERT, or APPEND the destination table. CREATE will create the table. REPLACE removes any existing rows before inserting new data. INSERT requires that the table exists, but that it is empty. APPEND adds rows and does nothing with any existing rows.
The following example uses the COPY command to create the local table
mytable2 as a copy of the local table mytable1. A commit is taken after
every 1000 rows. Note that since COPY is a SQL*Plus command, not a SQL
command, you must use a ’-’ to continue the command to multiple lines.
Also, the COPY command is not stored in your edit buffer, so you’ll have
to retype the command if you make mistakes (or save the command in a script
file).
set arraysize 10
set copycommit 100
set long 3000
copy from myusername/mypassword@mydb create mytable2 using select *
from mytable1 ;
Array fetch/bind size is 10. (arraysize is 10)
Will commit after every 100 array binds. (copycommit is 100)
Maximum long size is 3000. (long is 3000)
Table MYTABLE2 created.
Displaying
Data from Multiple Tables
An outer join forces a query to return a row even if
the row in one table has no matching row in the other. i.e. it will return
at least as many rows as the corresponding equijoin and probably more (since
that’s the reason for writing it in the first place). e.g. the following
query lists one row for each order pplus one row for each customer who
has not placed any orders:
select c.name, o.order_date from customers c, orders o where o.cust_id = c.id (+);
Creating
Tables
The following command creates a table VOTER with:
create table VOTER id number(6) constraint pk_id primary key, name varchar2(30) not null constraint unq_name unique, sex varchar2(1) not null constraint m_or_f check (sex in (‘M’,’F’)), dob date not null, area varchar2(5) not null constraint fk_area references areas(code), dor date, constraint dor_after_dob check (dor > dob) );
Altering
Tables and Constraints
alter table voters add ( post_code varchar2(7));
alter table voters modify (post_code not null varchar2(7));
alter table voters add (constraint name_not_fred check (name != ‘Fred’));
alter table voters disable constraint name_not_fred;
alter table voters enable constraint name_not_fred;
alter table voters drop constraint name_not_fred;
alter table voters modify (post_code varchar2(8));
drop table voters cascade constraints;
truncate table voters; delete from voters;
rename wrinklies to senior_voters;
COMMENT ON COLUMN voters.sex IS ' Trans-sexuals have the sex on their birth certificate';
Creating
Sequences
create sequence cust_seq start with 1000 increment by 5 maxvalue 5000 cycle;
select cust_seq.nextval from dual;
select cust_seq.currval from dual;
alter sequence cust_seq increment 10;
drop sequence cust_seq;
Controlling
User Access
create role MANAGER_ROLE;
grant select, insert, update, delete on VOTERS to MANAGER_ROLE; grant select on STATS to MANAGER_ROLE;
create user fredg identified by xyz123 grant create session to fredg -- lets fredg connect to the db grant MANAGER_ROLE to fredg;
alter user fredg identified by changedpassword;
revoke select on stats from MANAGER_ROLE;
create synonym VOTERS for herbieg.voters;
create public synonym VOTERS for herbieg.voters;
Developing
a simple PL/SQL block
/* * A multi-line comment */ declare l_counter NUMBER := 12; Fixed_value CONSTANT NUMBER(6) := 999999; Var_Value NUMBER(4,2); l_string VARCHAR2(10) := ‘Dummy’; isittrue BOOLEAN := FALSE; begin l_counter := length(l_string); l_string := ‘Dummy’||’2’; isittrue := TRUE; -- A simple comment. end;
%ROWTYPE
and %TYPE
Used to inherit the data types from the underlying table
Avoids having PL/SQL fail if a column is modified, e.g.
CHAR(2) to CHAR(10)
ROWTYPE is whole row and
TYPE is for a single column
DECLARE
CURSOR
get_customer IS
SELECT * FROM customer;
cust_row
get_customer%ROWTYPE;
BEGIN
OPEN get_customer;
FETCH get_customer INTO cust_row;
DBMS_OUTPUT.PUT_LINE(cust_row.name);
CLOSE get_customer;
END;
/
DECLARE
CURSOR
get_customer IS
SELECT name FROM customer;
cust_name
customer.name%TYPE;
BEGIN
OPEN get_customer;
FETCH get_customer INTO cust_name;
DBMS_OUTPUT.PUT_LINE(cust_name);
CLOSE get_customer;
END;
/
Interacting with Oracle
/* * A multi-line comment */ declare l_voter voters%rowtype; begin select * into l_voter from voters v where rownum = 1; if SQL%FOUND then update stats s set times_executed = times_executed + 1 where year = ‘1999’; end if; end;
Controlling
Flow in PL/SQL Blocks
IF counter = 1 THEN DBMS_OUTPUT.PUT_LINE('counter is 1') ; ELSIF counter = 2 THEN DBMS_OUTPUT.PUT_LINE('counter is 2') ; ELSIF counter = 3 THEN DBMS_OUTPUT.PUT_LINE('counter is 3') ; ELSE DBMS_OUTPUT.PUT_LINE('counter is something else') ; END IF;
DECLARE x NUMBER ; BEGIN x :=0; LOOP x:=x+1; EXIT WHEN (x > 10) ; INSERT INTO TEST2 (COL21) VALUES (x) ; END LOOP; COMMIT ; END ;
DECLARE x NUMBER ; BEGIN x :=10 ; WHILE x > 0 LOOP INSERT INTO TEST2 (COL21) VALUES (x) ; x:=x-1 ; END LOOP ; COMMIT ; END ;
DECLARE x NUMBER ; BEGIN x := 0 ; FOR i IN 1..10 LOOP x := x+1 ; INSERT INTO test2 (col21) values (x) ; END LOOP ; COMMIT ; END ;
Processing
Queries by Using Explicit Cursors
DECLARE CURSOR get_customer IS SELECT name FROM customer; cust_name customer.name%TYPE; BEGIN OPEN get_customer; FETCH get_customer INTO cust_name; DBMS_OUTPUT.PUT_LINE(cust_name); CLOSE get_customer; end;
DECLARE CURSOR c1 IS SELECT col11,col12 FROM test1 ; BEGIN FOR cur1 IN c1 LOOP INSERT INTO test2 (col21,col22) VALUES (cur1.col11, cur1.col12); END LOOP ; COMMIT ; END ; /
DECLARE CURSOR c1 ( ws_col number ) IS SELECT col11, col12 FROM test1 WHERE col11 > c1.ws_col; -- tmp_rec c1%rowtype ; -- BEGIN OPEN c1(3) ; LOOP FETCH c1 INTO tmp_rec ; EXIT WHEN c1%NOTFOUND ; INSERT INTO test2 ( col21, col22 ) VALUES ( tmp_rec.col11, tmp_rec.col12 ) ; END LOOP; CLOSE c1 ; COMMIT ; END ; /
BEGIN IF SQL%FOUND THEN NULL ; END IF ; -- IF SQL%ISOPEN THEN NULL ; END IF ; -- IF SQL%FOUND THEN NULL ; END IF ; -- IF SQL%ROWCOUNT = 2 THEN NULL ; END IF ; END ; /
Error
Handling
procedure doubletill_over100 (p_in IN OUT NUMBER) -- define an exception too_big EXCEPTION; begin if p_in > 128 then raise too_big; else p_in := p_in * 2; end if; exception when too_big then p_in = 1; other statements; when others then DBMS_OUTPUT.PUT_LINE('Unkown error'); dbms_output.put_line(SQLERRM); raise; end;
Develop
PL/SQL Program Units
Developing Stored Procedures and Functions
Procedure | Function | |
Syntax |
create or replace procedure myproc ( p_vat_rate IN NUMBER DEFAULT 17.5, p_price IN OUT NUMBER, p_vat OUT NUMBER) is price_invalid EXCEPTION; begin if p_price <= 0.0 then raise price_invalid; end if; p_vat := (p_vat_rate/100) * p_price; p_price := p_price + p_vat; exception when price_invalid then raise_application_error(-20000, ’Price must be positive’); when others then raise_application_error(-20999, ’Unexpected error’); end; |
create or replace function vat ( vat_rate IN NUMBER, price IN NUMBER) is l_vat NUMBER; begin l_vat := (vat_rate/100) * price; return l_vat; end; |
sqlplus |
variable price number variable vat number exec myproc(15,:price,:vat) or exec myproc(p_vat=>:vat, p_price=>:price); |
variable price number variable rate number exec :price := :price + vat(:rate,:price); or select vat(15, p.price) from prices p where p.id=123; |
Parameters |
|
|
Notes |
declare invalid_price EXCEPTION; pragma exception_init(-20000,invalid_price); l_price NUMBER := 10; …… begin myproc(p_vat=>16, p_price=>l_price) exception when invalid_price then handle the error …. end; |
Developing
and using packages
An example package is shown below.
create or replace package pckcar as number_of_gets number := 0; procedure upd (pId in number, pDesc in varchar2); function getNumberOfUpds return number; function getManufacturer (pId number) return varchar2; pragma restrict_references (getManufacturer, WNDS); end; /
create or replace package body pckcar as number_of_upds number := 0; procedure inc_upd is begin number_of_upds := number_of_upds + 1; end; function getNumberOfUpds return number is begin return number_of_upds; end; procedure upd (pId in number, pDesc in varchar2) is begin update car set description = pDesc where id = pId; inc_upd; end; function getManufacturer (pId number) return varchar2 is lName maker.name%type; begin select m.name into lName from maker m, car c where m.id = c.fk_id and c.id = pId; number_of_gets := number_of_gets + 1; return lName; end; end; /
pragma restrict_references (getManufacturer, WNDS, WNPS);
alter package pckcar compile;
Running
Packaged Procedures
CREATE OR REPLACE
PROCEDURE RUN_PACKS IS
BEGIN
FIN_PACK.UPDATE_SAL (999999,
67500);
DBMS_OUTPUT.PUT_LINE(FIN_PACK.AVG_SAL);
END;
In SQL*Plus
set serveroutput on
EXECUTE run_packs.UPDATE_SAL(999999,67500);
Developing Database Triggers
CREATE OR REPLACE TRIGGER AUDCAR BEFORE INSERT OR DELETE OR UPDATE ON CAR DECLARE action varchar2(1); BEGIN IF INSERTING THEN action=’I’; ELSIF UPDATING THEN action=’I’; ELSIF DELETING THEN action=’I’; END IF; insert into action_audits values (‘CAR’,action,user); END;
alter trigger trgcar disable;
alter trigger trgcar enable;
alter table car disable all triggers;
Built
in Packages Available
- DBMS_OUTPUT displays to the screen
- DBMS_PIPE communicates between sessions
- DBMS_LOCK manages program locks
- DBMS_JOB allows you to schedule jobs
- UTL_FILE reads from and writes tp operating system
files
- DBMS_SQL for dynamic SQL and DDL
PL/SQL
Tables
Used to perform array processing, must contain Primary Key
DECLARE
TYPE cust_name IS TABLE OF
customer.name%TYPE
INDEX BY BINARY_INTEGER;
STORED_NAME
cust_name;
BEGIN
SELECT name INTO stored_name(1)
FROM customer
WHERE rownum = 1;
DBMS_OUTPUT.PUT_LINE(stored_name(1));
END;
Tables
using %ROWTYPE
Allows a PL/SQL table to inherit a tables definition
DECLARE
TYPE cust_rec IS TABLE OF customer.name%ROWTYPE
INDEX BY BINARY_INTEGER;
STORED_CUST cust_rec;
BEGIN
SELECT * INTO stored_cust(1) FROM customer
WHERE rownum = 1;
DBMS_OUTPUT.PUT_LINE(stored_name(1).name);
END;
PL/SQL
Table Methods
Assists with table handling
table_name.method(parameters) e.g. stored_cust.EXISTS(1)
BEGIN
SELECT * INTO stored_cust(1) FROM customer
WHERE rownum = 1;
IF stored_cust.EXISTS(1)
THEN
DBMS_OUTPUT.PUT_LINE(stored_name(1).name);
END IF;
END;
PL/SQL Table Methods
Methods available includes
stored_rec.COUNT -- Number
of elements in the table
stored_rec.FIRST
-- Goes to first record
stored_rec.LAST
-- Goes to last record
stored_rec.PRIOR (n) -- Returns the preceding
index number
stored_rec.NEXT (n) -- Returns the next
index number
stored_rec.TRIM
-- Removes the last element in table
stored_rec.TRIM(n) -- Removes the
last n elements in table
stored_rec.DELETE
-- Deletes all elements from table
stored_rec.DELETE(n) -- Deletes the nth
elements from table
stored_rec.DELETE(m, n) -- Deletes elements in range m to n
stored_rec.EXTEND
-- Appends one null row to table
stored_rec.EXTEND(n) -- Appends n null
rows to table
stored_rec.EXTEND(n, I) -- Appends n copies of the I row
to table