Search This Blog

Friday 19 April 2013

Oracle DDL Command with Examples(CREATE Table, CREATE Index, CREATE Constraints, CREATE Sequence, CREATE Triggers, CREATE Procedure, CREATE Function, CURSOR Looping)

====== DDL ======

Type                Storage     Range/Length               Comments
-----------------   ----------  --------------             -------------------
NUMBER              16          40 digit floating point
FLOAT               16          40 digit floating point
SMALLINT            16          40 digit floating point

NUMBER(a,b)         varies      a digits, b precision
FLOAT(a,b)          varies      a digits, b precision

DECIMAL             16          40 digit

INTEGER             16          40 digits
INTEGER(a)          varies      a digits

CHAR(a)             a           a=(1-255)
VARCHAR(a)          varies      1 - 255
VARCHAR2(a)         varies      1 - 2000

DATE                8           1/1/4217BC - 12/31/4712AD  precision to minutes


LONG                varies      0 - 2 GB                   stored inline, obsolete *
LONG RAW            varies      0 - 2 GB                   stored inline, obsolete *

LONG VARCHAR        varies      0 - 2 GB                   stored inline, obsolete *

BLOB                varies      0 - 4 GB                   stored separate from table
CLOB                varies      0 - 4 GB                   stored separate from table
NCLOB               varies      0 - 4 GB                   stored separate from table

BFILE               ??          ??                         pointer to O/S file

ROWID               8           n/a                        row identifier within block


* Long datatypes are discouraged in Oracle 8.  Note that are long and blob
  datatypes are incompatible.


====== PL-SQL data types (differences) ======

Type                Storage     Range/Length    Comments
-----------------   ----------  --------------  ----------------------------
NUMERIC

VARCHAR
VARCHAR2

BLOB                                             must be read in 32k chunks
CLOB
NCLOB






 

Creating a table


PCTFREE = Amount of space to leave in block during insert operations. Allows room for records to grow within the same area.
PCUSED = The threshold at which the block is placed back on the free block list.
INITIAL/NEXT = The initial disk allocated, and the next extent size.
LOGGING = Indicates whether operations are written to the redo logs.

CREATE TABLE EMPLOYEE (
EMP_ID     NUMBER(8),
LNAME      VARCHAR2(30),
FNAME      VARCHAR2(15),
HIRE_DT    DATE,
SALARY     NUMBER(8,2) )
  PCTFREE 20
  PCTUSED 50
STORAGE (
   INITIAL 200K NEXT 200K
   PCTINCREASE 0 MAXEXTENTS 50 )
TABLESPACE ts01
LOGGING ;





 

Creating indexes



CREATE UNIQUE INDEX EMP_IDX ON EMPLOYEE (EMP_ID) ;




 

Creating constraints



/* primary key constraint */

ALTER TABLE EMPLOYEE (
      CONSTRAINT EMP_PK
      PRIMARY KEY (EMP_ID)
);

/* foreign key constraint */

ALTER TABLE EMPLOYEE ADD (
      CONSTRAINT EMP_LOC_ASSIGN_FK
      FOREIGN KEY (EMP_ID,
                   LOC_CD)
      REFERENCES  LOC_REGISTRY (
                   EMP_ID,
                   LOC_CD)
);




 

Creating and using a sequence



/* create a sequence for employee ids */

CREATE SEQUENCE EMP_ID_SEQ
 INCREMENT BY 1
 NOMINVALUE
 NOMAXVALUE
 NOCYCLE
 CACHE 20
 NOORDER ;

/ * use the next emp id, and increment the sequence */

INSERT INTO EMPLOYEE(EMP_ID, LNAME, FNAME)
VALUES (EMP_ID_SEQ.NEXTVAL, 'SMITH', 'JIM') ;


/* get the current value of the sequence */

INSERT INTO EMPLOYEE(EMP_ID, LNAME, FNAME)
VALUES (EMP_ID_SEQ.CURRVAL, 'SMITH', 'JIM') ;




 

Creating triggers


The example below illustrates versioning of the EMP_RESUME table, which contains a blob field.

CREATE OR REPLACE TRIGGER EMP_RES_INS_TR
AFTER INSERT ON EMP_RES
FOR EACH ROW

DECLARE
 VER1   NUMBER ;
 EBLOB  BLOB ;
 VBLOB  BLOB ;

BEGIN
    EBLOB := EMPTY_BLOB();

    SELECT (COUNT(*) + 1) INTO VER1
    FROM VEMP_RES
    WHERE EMP_ID =:NEW.EMP_ID ;

    VBLOB := :NEW.RESUME ;

    INSERT INTO VEMP_RES
    ( EMP_ID, DOC_URL,
      A_USERID, D_MODIFIED, VER_NO, RESUME)
    VALUES (
      :NEW.EMP_ID, :NEW.DOC_URL,
      USER, SYSDATE, VER1, EBLOB ) ;

    SELECT RESUME
    INTO   EBLOB
    FROM  VEMP_RES
    WHERE EMP_ID =:NEW.EMP_ID AND
          VER_NO = VER1
    FOR UPDATE ;

    UPDATE VEMP_RES
    SET RESUME = VBLOB
    WHERE EMP_ID =:NEW.EMP_ID AND
          VER_NO = VER1 ;

END;




 

Using SQL-Plus


SQL-Plus is a query / command line utility which has some powerful formatting capabilities.

Getting Started

;                     Command line terminator
/                     Execute the current batch of commands
SET SERVEROUTPUT ON   Allow messages from PL-SQL to be displayed
SHOW ERRORS           Show errors from last batch
EDIT                  Run editor, and load buffer
CLEAR BUFFER          Clear buffer commands
&                     Prompt for value
@                     Run commands in @filename


/**** Examples ****/

/* prompt for process id, and kill */

alter system kill session '&Victim'
/


/* run commands in tables.sql */

@tables.sql
/





 

Creating a stored procedure


Below is a simple stored procedure which deletes an invoice.
Note:
- variable declaration placement
- the syntax for comments /* --- */
- ALL select statements must have an into statement for the result set. Oracle stored procedures must use "out" variables to return results to client programs.
- the declaration of INV_ID1 uses the column def as a prototype

CREATE OR REPLACE PROCEDURE PROC_DELETE_INVOICE
  ( USERID1 VARCHAR2,   INV_ID1 INVOICE.INV_ID%TYPE )
AS
    INV_COUNT     NUMBER ;

BEGIN

INV_COUNT := 0;

/* check if invoice exists */

SELECT COUNT(*)
  INTO INV_COUNT
  FROM INVOICE
  WHERE INV_ID = INV_ID1 ;

IF INV_COUNT > 0 THEN

   DELETE FROM INVOICE WHERE INV_ID = INV_ID1 ;
   COMMIT ;

   END IF ;

END ;




 

Displaying output


All SELECT statements in PL-SQL must have an INTO clause; therefore another method is needed to display output to the console.

DBMS_OUTPUT.PUT_LINE('TEST OUTPUT');

salary := 24000;

dbms_output.put_line(salary);




 

Output variables


Output variables are used to return data to another procedure, or to an external application which has invoked the stored procedure.

/* sample procedure header using output variables */

TYPE INV_ARRAY IS TABLE OF NUMBER(8)
  INDEX BY BINARY_INTEGER ;

CREATE OR REPLACE PROCEDURE PROC_GET_INV_NOS
  ( USERID1 IN VARCHAR2,   INV_IDS OUT INV_ARRAY)
AS

...




 

Arrays and structures


Arrays and structures are implemented thought the use of "tables" and "records" in PL-SQL.

/* EXAMPLE OF A SIMPLE RECORD TYPE */

TYPE INVOICE_REC_TYPE IS RECORD
   (INV_ID   INVOICE.INV_ID%TYPE,
    INV_DT   INVOICE.INV_DT%TYPE ) ;


/* ARRAY DECLARATION */

TYPE NAME_TABLE_TYPE IS TABLE OF VARCHAR2(20)
INDEX BY BINARY_INTEGER ;

NAME_TABLE    NAME_TABLE_TYPE ;


/* ARRAY SUBSCRIPTING */

I := I + 1;

NAME_TABLE(I) := 'JSMITH';





 

Conditionals


Sample formats of conditional branching are given below:

IF <condition> THEN <statement> ;

IF <condition> THEN
  <statements> ;
  END IF;

/* sample statement, note the pipes for concatenation */
IF (COUNT1 = 0) AND (COUNT2 > 0) THEN
   RETMSG := 'Security attributes have not been assigned, ' ||
               'you are restricted.';
ELSE
   RETMSG := 'You are OK';
END IF;





 

Looping



WHILE (I < 10)
LOOP
  /* ... SOME CMDS ... */

  I = I + 1;
END LOOP;





 

Cursors


The first example depicts dbase-style row processing ; the second a more traditional "fetch" approach.

PROCEDURE PROC_SCAN_INVOICES (EXPIRE_DT IN DATE)
IS

CURSOR INVOICE_CUR IS
   SELECT INV_ID, INV_DT  FROM INVOICE ;

TYPE INVOICE_REC_TYPE IS RECORD
   (INV_ID   INVOICE.INV_ID%TYPE,
    INV_DT   INVOICE.INV_DT%TYPE ) ;

INVOICE_REC   INVOICE_REC_TYPE ;

BEGIN

FOR INVOICE_REC1 IN INVOICE_CUR
  LOOP

  IF INVOICE_REC.INV_DT < EXPIRE_DT THEN

     DELETE FROM INVOICE
       WHERE INV_ID = INV_REC.INV_ID ;

     DBMS_OUTPUT.PUT_LINE('INVOICE DELETETED:');
     DBMS_OUTPUT.PUT_LINE(INV_REC.INV_ID);

     END

  END LOOP;

END;

/* ======================================= */


CREATE OR REPLACE PROCEDURE PROC_DOCEXPIRE_RPT  
   ( RPT_BODY  OUT LONG RAW )
IS  
   
   RPT_LINE      VARCHAR2(1900);
   RPT_PART      VARCHAR2(1900);
   RPT_LEAD      VARCHAR2(200);
   GLIB_ID1       NUMBER ;
   GLIB_ID2       VARCHAR(12);
   ORIG_LOC_CD1  VARCHAR2(12);
   AUTHOR_ID1    VARCHAR2(30);
   CONTRIBUTORS1 VARCHAR2(80); 
   TOPIC1        VARCHAR2(80);
   NBR_ACCESS1   NUMBER ;
   NBR_ACCESS2   VARCHAR2(12);
   TOT_EXPIRED1  NUMBER ;
   TOT_EXPIRED2  VARCHAR2(12);
   COUNT1        NUMBER ;
   RPT_BODY_PART LONG ;

CURSOR CUR1 IS
  SELECT GLIB_ID, ORIG_LOC_CD, AUTHOR_ID, CONTRIBUTORS, TOPIC, NBR_ACCESS
  FROM GEN_DOC
  WHERE EXPIRE_DT < (SYSDATE + 30)
  ORDER BY ORIG_LOC_CD, GLIB_ID ;

BEGIN

SELECT COUNT(*)
INTO   TOT_EXPIRED1
FROM   GEN_DOC
WHERE STAT_CD='90';

TOT_EXPIRED2 := TO_CHAR(TOT_EXPIRED1);

RPT_LEAD := '<H5>TOTAL EXPIRED DOCUMENT COUNT TO DATE: ... ' || 
        TOT_EXPIRED2 || '</H5><HR>' ;

RPT_LINE := '<HTML><BODY BGCOLOR=#FFFFFF>'  ||
 '<H6>ABC Corporation</H6>' ||
 '<H2>Gen Doc System - Documents Expiring Within 30 Days</H2><HR>' ||
 RPT_LEAD ;

COUNT1 := 0;

OPEN CUR1;

RPT_LINE := RPT_LINE || '<TABLE>'     ||
      '<TD><U>No. Accesses</U></TD>'  ||
      '<TD><U>Document #</U></TD>'    ||
      '<TD><U>Topic</U></TD>'         ||
      '<TD><U>Author</U></TD>' ;       

RPT_BODY := UTL_RAW.CAST_TO_RAW(RPT_LINE); 

RPT_LINE := '';

LOOP 
   COUNT1 := COUNT1 + 1;
   EXIT WHEN (COUNT1 > 500);
   EXIT WHEN (UTL_RAW.LENGTH(RPT_BODY) > 32000);

   FETCH CUR1 INTO 
      GLIB_ID1, ORIG_LOC_CD1, AUTHOR_ID1, CONTRIBUTORS1, TOPIC1, NBR_ACCESS1 ;
   EXIT WHEN CUR1%NOTFOUND ;

   RPT_PART := '<TR><TD>';
   NBR_ACCESS2 := TO_CHAR(NBR_ACCESS1);
   RPT_PART := CONCAT(RPT_PART,NBR_ACCESS2);
   RPT_PART := CONCAT(RPT_PART,'</TD><TD>');
   GLIB_ID2  := TO_CHAR(GLIB_ID1);

   RPT_PART := RPT_PART  || ORIG_LOC_CD1 || '-' || GLIB_ID2 ||
      '</TD><TD>' || TOPIC1  || '</TD><TD>' || 
          AUTHOR_ID1 || '</TD><TR>' ;
   
   RPT_LINE := CONCAT(RPT_LINE, RPT_PART);

   RPT_BODY_PART := UTL_RAW.CAST_TO_RAW(RPT_LINE);
   RPT_BODY      := UTL_RAW.CONCAT(RPT_BODY,RPT_BODY_PART);
   -- RPT_BODY   := RPT_BODY || RPT_LINE;
   RPT_LINE   := '';

END LOOP;
CLOSE CUR1 ;

RPT_LINE := '</TABLE></BODY></HTML>';

RPT_BODY_PART := UTL_RAW.CAST_TO_RAW(RPT_LINE);
RPT_BODY      := UTL_RAW.CONCAT(RPT_BODY, RPT_BODY_PART);

EXCEPTION
  WHEN OTHERS THEN
    BEGIN
    DBMS_OUTPUT.PUT_LINE('ERROR: PROC_DOCSTAT_RPT');
    GLIB_ID1 := UTL_RAW.LENGTH(RPT_BODY);
    DBMS_OUTPUT.PUT_LINE(GLIB_ID1);
    END;

END;





 

Packages


A package is a construct which bounds related procedures and functions together. Variables declared in the declaration section of a package can be shared among the procedures/functions in the body of the package.

/* package */

CREATE OR REPLACE PACKAGE INVPACK
IS

   FUNCTION COUNTINV (SALESREP IN VARCHAR2) RETURN INTEGER;

   PROCEDURE PURGEINV (INV_ID IN INTEGER) ;

END INVPACK;


/* package body */

CREATE OR REPLACE PACKAGE BODY INVPACK
IS

COUNT1 NUMBER;

   FUNCTION COUNTINV (SALESREP IN VARCHAR2) RETURN INTEGER
   IS
   BEGIN

   SELECT COUNT(*)
   INTO COUNT1
   FROM INVOICE
   WHERE SALES_REP_ID = SALESREP ;

   RETURN COUNT1 ;
   END COUNTINV;


   PROCEDURE PURGEINV (INV_ID1 IN INTEGER)
   IS
   BEGIN

   DELETE FROM INVOICE
   WHERE INV_ID = INV_ID1

   END PURGEINV;

/* initialization section for package */
BEGIN

COUNT1 := 0 ;

END INVPACK;




 

Exception Handling


The following block could appear at the end of a stored procedure:

EXCEPTION
  WHEN NO_DATA_FOUND THEN
     DBMS_OUTPUT.PUT_LINE('End of data !!);
  WHEN OTHERS THEN
    BEGIN
    DBMS_OUTPUT.PUT_LINE('OTHER CONDITION OCCURRED !');
    END;




 

Using Blobs


Blob variables require special handling in PL-SQL. When reading from a file to a blob, only one statement is required. When reading from a blob field to a PL-SQL variable, only 32k blocks can be processed, thus necessitating a loop construct.

/*---------------------------------------*/
/* Read a blob from a file, and write    */
/* it to the database.                   */
/*---------------------------------------*/

set serveroutput on size 500000 ;

truncate table image_test ;

create or replace directory image_dir as '/apps/temp/images' ;


create or replace procedure proc_imp_jpg  
(fname1 in varchar2, image_id1 in numeric) is

file1   bfile ;
lblob   blob ;
len     int ;
e_blob  blob ;

begin

  file1 := bfilename('IMAGE_DIR',fname1);

  e_blob := empty_blob();

  insert into image_test (image_id, image_data)
  values (image_id1, e_blob )
  returning image_data into lblob ;

  dbms_lob.fileopen(file1);

  len := dbms_lob.getlength(file1) ;

  dbms_lob.loadfromfile(lblob,file1,len);

  dbms_lob.filecloseall();

  commit;


exception
  when others then
    begin
    dbms_output.put_line(sqlerrm);
    dbms_lob.filecloseall();
    commit;
    end;

end  ;
/


call proc_imp_jpg('jada.jpg',101)
/


/*-----------------------------*/
/* determine the length of     */
/* a blob field                */
/* by reading it               */
/*-----------------------------*/
CREATE OR REPLACE PROCEDURE PROC_BLOB_LENGTH
   (PART_ID1  NUMBER)
IS
    SRC_LOB    BLOB;
    BUFFER     RAW(100);
    AMT        BINARY_INTEGER := 100;
    POS        INTEGER := 1;
    COUNTER    INTEGER :=0;

BEGIN
        SELECT PART_PHOTO INTO SCR_LOB
        FROM PARTS
        WHERE PART_ID=PART_ID1 ;


IF (SRC_LOB IS NOT NULL) THEN

    LOOP
        DBMS_LOB.READ (SRC_LOB, AMT, POS, BUFFER);
        POS := POS + AMT;
        COUNTER:=COUNTER+1;
    END LOOP;

ELSE
    DBMS_OUTPUT.PUT_LINE('** Source is null');
END IF;


EXCEPTION
        WHEN NO_DATA_FOUND THEN
            DBMS_OUTPUT.PUT_LINE('End of data, total bytes:');
            DBMS_OUTPUT.PUT_LINE(POS);
END;




 

Using the Context cartridge


Managing Context is an arduous task. The best approach is to use the command line utility as much as possible. Below is a code sample which creates a policy (a policy is a construct which informs context which column on what table to scan during a search operation). The next example illustrates how to perform a search, and stored the result keys in a table.

/* create a policy, on the emp_resume table */

ctx_svc.clear_all_errors;

dbms_output.put_line('Creating Policy ...');

ctx_ddl.create_policy(
   POLICY_NAME => 'EMP_RES_POLICY',
   COLSPEC => 'EMP_RES.RESUME',
   SOURCE_POLICY => 'CTXSYS.DEFAULT_POLICY',
   DESCRIPTION => 'EMP Policy',
   TEXTKEY => 'EMP_ID',
   DSTORE_PREF => 'CTXSYS.DEFAULT_DIRECT_DATASTORE',
   FILTER_PREF => 'CTXSYS.HTML_FILTER',
   LEXER_PREF => 'CTXSYS.DEFAULT_LEXER'
   );

dbms_output.put_line('Indexing Policy ...');

ctx_ddl.create_index('EMP_POLICY');


/* Run a Context query, place the result key values in a table */

/* first, this table needs to be created */

CREATE TABLE EMP_CTX_RESULTS(
   TEXTKEY   VARCHAR2(64),
   TEXTKEY2  VARCHAR2(64),
   SCORE     NUMBER,
   CONID     NUMBER );

/* this code can go in a stored proc */

POLICY1 := 'EMP_POLICY';
TABLE1  := 'EMP_CTX_RESULTS';
ID1     := 100 ;
QUERY1  := 'COBOL|FORTRAN';

CTX_QUERY.CONTAINS(POLICY1, QUERY1, TABLE1, 1, ID1);

/* the table will contain records with a CONID of 100 */
/* ... you can use ampersand or pipe as the conditional */


 

Sleep and Wait


Sometimes it is necessary to delay the execution of commands, for debugging, or batch runs.

/* Sleep 60 seconds */

execute dbms_lock.sleep(60);


/* Sleep one hour */

execute dbms_lock.sleep(3600);

 

Date Manipulation



/* display current time */

select to_char(sysdate, 'Dy DD-Mon-YYYY HH24:MI:SS') 
   as "SYSDATE"
from dual;


/* insert specific date/time into table */

insert into game_schedule 
   ( sched_id,  location, game_date )
values(2982, 'Chicago', to_date('2001/10/31:03:00:00PM', 'yyyy/mm/dd:hh:mi:ssam')) ;

No comments:

Post a Comment