Tuesday, October 21, 2014

Bulk Collect


    This is used for array fetches
    With this you can retrieve multiple rows of data with a single round trip.
    This reduces the number of context switches between the pl/sql and sql engines. 
    You can use bulk collect in both dynamic and static sql.
    You can use bulk collect in select, fetch into and returning into clauses.
    SQL engine automatically initializes and extends the collections you reference in the bulk collect clause.
    You can fetch into multiple collections with one column each.
    You can use the limit clause of bulk collect to restrict the no of rows retrieved.
   


SELECT * FROM product_details;

-->-- Bulk collect in FETCH INTO --<--


DECLARE
  TYPE alldata_typ IS TABLE OF product_details%ROWTYPE;
  dta alldata_typ;
  CURSOR proddt_cur IS
    SELECT * FROM product_details;
BEGIN
  OPEN proddt_cur;
  FETCH proddt_cur BULK COLLECT
    INTO dta;
  CLOSE proddt_cur;

  FOR i IN dta.FIRST .. dta.COUNT LOOP
    dbms_output.put_line(dta(i).p_name || ' department id is ' || dta(i).p_id);
  END LOOP;
END;
/


-->-- Bulk collect in SELECT clause --<--

DECLARE
  TYPE alldata_typ IS TABLE OF product_details%ROWTYPE;
  dta alldata_typ;
BEGIN
  SELECT * BULK COLLECT INTO dta FROM product_details;
  FOR i IN dta.FIRST .. dta.LAST LOOP
    dbms_output.put_line(dta(i).p_name || ' department id is ' || dta(i).p_id);
  END LOOP;
END;



-->-- LIMIT in Bulk collect --<--

DECLARE
  TYPE alldata_typ IS TABLE OF product_details%ROWTYPE;
  dta alldata_typ;
  CURSOR proddt_cur IS
    SELECT * FROM product_details;
BEGIN
  OPEN proddt_cur;
  FETCH proddt_cur BULK COLLECT
    INTO dta LIMIT 30;
  CLOSE proddt_cur;

  FOR i IN dta.FIRST .. dta.COUNT LOOP
    dbms_output.put_line(dta(i).p_name || ' department id is ' || dta(i).p_id);
  END LOOP;
END;
/



-->-- Multiple fetches in INTO clause --<--

SELECT * FROM product_details;

DECLARE
  TYPE alldata_typ1 IS TABLE OF product_details.p_id%TYPE;
  TYPE alldata_typ2 IS TABLE OF product_details.p_name%TYPE;
  dta1 alldata_typ1;
  dta2 alldata_typ2;
  CURSOR proddt_cur IS
    SELECT p_id, p_name FROM product_details;
BEGIN
  OPEN proddt_cur;
  FETCH proddt_cur BULK COLLECT
    INTO dta1, dta2;
  CLOSE proddt_cur;

  FOR i IN dta1.FIRST .. dta1.COUNT LOOP
    dbms_output.put_line('Department Id : ' || dta1(i));
  END LOOP;

  FOR i IN dta2.FIRST .. dta2.COUNT LOOP
    dbms_output.put_line('Department Name : ' || dta2(i));
  END LOOP;

END;
/


DROP TABLE dep_details;

DROP TABLE product_details;

Ref Cursor



    This is unconstrained cursor which will return different types depends upon the user input.
    Ref cursors cannot be closed implicitly.
    Ref cursor with return type is called strong cursor.
    Ref cursor without return type is called weak cursor.
    You can declare ref cursor type in package spec as well as body.
    You can declare ref cursor types in local subprograms or anonymous blocks.


CREATE OR REPLACE PROCEDURE ref_c_sp(dep_det_c IN OUT SYS_REFCURSOR)
AS
BEGIN
  OPEN dep_det_c
  FOR
  SELECT * FROM dep_details d;
END;
/


DECLARE
   dep_det_c  SYS_REFCURSOR;
   tab_data   dep_details%ROWTYPE;
BEGIN
   ref_c_sp(dep_det_c);
 
   LOOP
      FETCH dep_det_c INTO tab_data;
      EXIT WHEN dep_det_c%NOTFOUND;
      dbms_output.put_line('Department Name : '|| tab_data.d_name);
   END LOOP;
   CLOSE dep_det_c;
END;


/*sample output*/

Department Name : Admin
Department Name : HR
Department Name : Sales
Department Name : Marketing


DROP PROCEDURE ref_c_sp;


Cursor


    


SQL Private work Area where the query get passed and executed.

Types
******
    Implicit(SQL)
    Explicit
        -->-- advanced cursor types --<--
    Parametrized Cursor
    Ref Cursor

Implicit

********

    ORACLE implicitly opens a cursor to process each SQL statement not associated with an explicitly declared cursor.
   
    PL/SQL lets you refer to the most recent implicit cursor as the SQL” cursor. So, although you cannot use the OPEN,
    FETCH, and CLOSE statements to control an implicit cursor, you can still use cursor attributes to access information
    about the most recently executed SQL statement.

Cursor Stages
**************


        OPEN cursor_name
        FETCH (with in loop)
        CLOSE cursor_name
 

Explicit

    The set of rows returned by a query can consist of zero, one, or multiple rows,
    depending on how many rows meet your search criteria. When a query returns multiple rows,
    you can explicitly define a cursor to process the rows. You use three commands to control the cursor

Cursor Attributes
*****************


    %FOUND
    %NOTFOUND
    %ISOPEN
    %ROWCOUNT
    %BULK_ROWCOUNT        --<-- used to handle error while using bulk collection.
    %BULK_EXCEPTIONS    --<-- used to handle error while using bulk collection.

Cursor Declaration

    DECLARE
        CURSOR <cursor_name>
            IS
        <SELECT statement>
        BEGIN
             --> some stmt
        END;
        /

Cursor Loop

  • Loop
  • While Loop
  • For Loop
Cursor Clauses
  • Return
  • For update
  • Where current of
  • Bulk collect


-->-- creating table

create table product_details
(
p_id        NUMBER,
p_name      VARCHAR2(30),
p_order_dt  DATE
);


-->-- Inserting data

BEGIN
  FOR i IN 1 .. 75 LOOP
    INSERT INTO product_details VALUES (i, 'prod_name_' || i, SYSDATE + i);
  END LOOP;
  commit;
END;


-->-- selecting data

SELECT * FROM product_details;

---------------------------------------------
p_id    p_name        p_order_dt
---------------------------------------------
1     prod_name_1     10/11/2014 3:48:32 PM
2     prod_name_2     10/12/2014 3:48:32 PM
3     prod_name_3     10/13/2014 3:48:32 PM
4     prod_name_4     10/14/2014 3:48:32 PM
5     prod_name_5     10/15/2014 3:48:32 PM
6     prod_name_6     10/16/2014 3:48:32 PM
7     prod_name_7     10/17/2014 3:48:32 PM
8     prod_name_8     10/18/2014 3:48:32 PM
9     prod_name_9     10/19/2014 3:48:32 PM
10    prod_name_10    10/20/2014 3:48:32 PM
11    prod_name_11    10/21/2014 3:48:32 PM
12    prod_name_12    10/22/2014 3:48:32 PM
13    prod_name_13    10/23/2014 3:48:32 PM
14    prod_name_14    10/24/2014 3:48:32 PM
15    prod_name_15    10/25/2014 3:48:32 PM
16    prod_name_16    10/26/2014 3:48:32 PM
17    prod_name_17    10/27/2014 3:48:32 PM
18    prod_name_18    10/28/2014 3:48:32 PM
19    prod_name_19    10/29/2014 3:48:32 PM
20    prod_name_20    10/30/2014 3:48:32 PM
---------------------------------------------


----------------------------------------------
Implicit Cursor
----------------------------------------------

         --will update soon

----------------------------------------------
Explicit Cursor
----------------------------------------------

**********************************************
Processing cursor data by using LOOP
**********************************************
   
DECLARE
  all_data product_details%ROWTYPE;
  --cursor declaration
  CURSOR prod_detail_cur IS
    SELECT * FROM product_details
    WHERE ROWNUM <=5;
BEGIN
  OPEN prod_detail_cur;
     LOOP
        FETCH prod_detail_cur
         INTO all_data;
         EXIT WHEN prod_detail_cur%NOTFOUND;  --<-- if next record not found means control will come out from the loop
         dbms_output.put_line('Product id : ' || all_data.p_id ||
                              ' Product Name :  ' || all_data.p_name ||
                              ' ( Orderd on : ' || TRIM(all_data.p_order_dt) || ' )');
     END LOOP;
  CLOSE prod_detail_cur;
END;


/*sample output*/

Product id : 1 Product Name :  prod_name_1 ( Orderd on : 11-OCT-14 )
Product id : 2 Product Name :  prod_name_2 ( Orderd on : 12-OCT-14 )
Product id : 3 Product Name :  prod_name_3 ( Orderd on : 13-OCT-14 )
Product id : 4 Product Name :  prod_name_4 ( Orderd on : 14-OCT-14 )
Product id : 5 Product Name :  prod_name_5 ( Orderd on : 15-OCT-14 )


DECLARE
  all_data product_details%ROWTYPE;
  --cursor declaration
  CURSOR prod_detail_cur IS
    SELECT * FROM product_details
    WHERE ROWNUM <=5;
BEGIN
  OPEN prod_detail_cur;
     LOOP
        FETCH prod_detail_cur
         INTO all_data;
         dbms_output.put_line('Product id : ' || all_data.p_id ||
                              ' Product Name :  ' || all_data.p_name ||
                              ' ( Orderd on : ' || TRIM(all_data.p_order_dt) || ' )');
         EXIT WHEN prod_detail_cur%FOUND;  --<-- if next record found means control will come out from the loop
     END LOOP;
  CLOSE prod_detail_cur;
END;


/*sample output*/

Product id : 1 Product Name :  prod_name_1 ( Orderd on : 11-OCT-14 )



DECLARE
  all_data product_details%ROWTYPE;
  --cursor declaration
  CURSOR prod_detail_cur IS
    SELECT * FROM product_details
    WHERE ROWNUM <=5;
BEGIN
  OPEN prod_detail_cur;
     LOOP
        FETCH prod_detail_cur
         INTO all_data;
         EXIT WHEN prod_detail_cur%NOTFOUND; 
         dbms_output.put_line('Product id : ' || all_data.p_id ||
                              ' Product Name :  ' || all_data.p_name ||
                              ' ( Orderd on : ' || TRIM(all_data.p_order_dt) || ' )');
     END LOOP;
  CLOSE prod_detail_cur;
 
  IF prod_detail_cur%ISOPEN THEN
     CLOSE prod_detail_cur;
     dbms_output.put_line('prod_detail_cur cursor closed');
  ELSE
     dbms_output.put_line('prod_detail_cur cursor Already closed');
  END IF;
  
END;


/*sample output*/

Product id : 1 Product Name :  prod_name_1 ( Orderd on : 11-OCT-14 )
Product id : 2 Product Name :  prod_name_2 ( Orderd on : 12-OCT-14 )
Product id : 3 Product Name :  prod_name_3 ( Orderd on : 13-OCT-14 )
Product id : 4 Product Name :  prod_name_4 ( Orderd on : 14-OCT-14 )
Product id : 5 Product Name :  prod_name_5 ( Orderd on : 15-OCT-14 )
prod_detail_cur cursor Already closed




DECLARE
  all_data product_details%ROWTYPE;
  --cursor declaration
  CURSOR prod_detail_cur IS
    SELECT * FROM product_details
    WHERE ROWNUM <=5;
BEGIN
  OPEN prod_detail_cur;
     LOOP
        FETCH prod_detail_cur
         INTO all_data;
         EXIT WHEN prod_detail_cur%NOTFOUND; 
         dbms_output.put_line('Product id : ' || all_data.p_id ||
                              ' Product Name :  ' || all_data.p_name ||
                              ' ( Orderd on : ' || TRIM(all_data.p_order_dt) || ' )');
     END LOOP;
  -->-- CLOSE prod_detail_cur;
 
  IF prod_detail_cur%ISOPEN THEN
     CLOSE prod_detail_cur;
     dbms_output.put_line('prod_detail_cur cursor closed');
  ELSE
     dbms_output.put_line('prod_detail_cur cursor Already closed');
  END IF;
  
END;


/*sample output*/

Product id : 1 Product Name :  prod_name_1 ( Orderd on : 11-OCT-14 )
Product id : 2 Product Name :  prod_name_2 ( Orderd on : 12-OCT-14 )
Product id : 3 Product Name :  prod_name_3 ( Orderd on : 13-OCT-14 )
Product id : 4 Product Name :  prod_name_4 ( Orderd on : 14-OCT-14 )
Product id : 5 Product Name :  prod_name_5 ( Orderd on : 15-OCT-14 )
prod_detail_cur cursor closed




**********************************************
Processing cursor data by using WHILE LOOP
**********************************************


DECLARE
  all_data product_details%ROWTYPE;
  --cursor declaration
  CURSOR prod_detail_cur IS
    SELECT * FROM product_details WHERE ROWNUM <= 5;
BEGIN
  OPEN prod_detail_cur;
  FETCH prod_detail_cur
    INTO all_data;
  WHILE prod_detail_cur%FOUND LOOP
 
    dbms_output.put_line('Product id : ' || all_data.p_id ||
                         ' Product Name :  ' || all_data.p_name ||
                         ' ( Orderd on : ' || TRIM(all_data.p_order_dt) || ' )');
    FETCH prod_detail_cur
      INTO all_data;
  END LOOP;
  CLOSE prod_detail_cur;
END;

/*sample output*/

Product id : 1 Product Name :  prod_name_1 ( Orderd on : 11-OCT-14 )
Product id : 2 Product Name :  prod_name_2 ( Orderd on : 12-OCT-14 )
Product id : 3 Product Name :  prod_name_3 ( Orderd on : 13-OCT-14 )
Product id : 4 Product Name :  prod_name_4 ( Orderd on : 14-OCT-14 )
Product id : 5 Product Name :  prod_name_5 ( Orderd on : 15-OCT-14 )


************************************************************
Processing cursor data by using FOR LOOP - CURSOR FOR LOOP
************************************************************

DECLARE
  --cursor declaration
  CURSOR prod_detail_cur IS
    SELECT * FROM product_details WHERE ROWNUM <= 5;
BEGIN
  FOR i IN prod_detail_cur
  LOOP
    dbms_output.put_line('Product id : ' || i.p_id ||
                         ' Product Name :  ' || i.p_name ||
                         ' ( Orderd on : ' || TRIM(i.p_order_dt) || ' )');
  END LOOP;
END;


/*sample output*/

Product id : 1 Product Name :  prod_name_1 ( Orderd on : 11-OCT-14 )
Product id : 2 Product Name :  prod_name_2 ( Orderd on : 12-OCT-14 )
Product id : 3 Product Name :  prod_name_3 ( Orderd on : 13-OCT-14 )
Product id : 4 Product Name :  prod_name_4 ( Orderd on : 14-OCT-14 )
Product id : 5 Product Name :  prod_name_5 ( Orderd on : 15-OCT-14 )



Parameterized Cursor
*********************

    This was used when you are going to use the cursor in more than one place with different values for the same where clause.
    Cursor parameters must be in mode.
    Cursor parameters may have default values.
    The scope of cursor parameter is within the select statement.



CREATE TABLE dep_details(d_id NUMBER,d_name VARCHAR2(30), location_id NUMBER);

BEGIN
INSRT INTO dep_details VALUES(001,'Admin',1010);
INSRT INTO dep_details VALUES(002,'HR',1010);
INSRT INTO dep_details VALUES(003,'Sales',1020);
INSRT INTO dep_details VALUES(004,'Marketing',1020);
commit;
END;

SELECT * FROM dep_details;

----------------------------
d_id   d_name    location_id
----------------------------
   1   Admin        1010
   2   HR           1010
   3   Sales        1020
   4   Marketing    1020
----------------------------


DECLARE
  -->--Declaring parameterized cursor
  CURSOR dep_det_c(p_location_id NUMBER) IS
    SELECT * FROM dep_details d WHERE d.location_id = p_location_id;

  all_data dep_details%ROWTYPE;
BEGIN
  dbms_output.put_line('-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-');
  OPEN dep_det_c(1010);
  LOOP
    FETCH dep_det_c
      INTO all_data;
    EXIT WHEN dep_det_c%NOTFOUND;
    dbms_output.put_line('Department id : ' || all_data.d_id ||
                         ' Department Name : ' || all_data.d_name);
  END LOOP;
  CLOSE dep_det_c;

  dbms_output.put_line('-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-'); 
  -->-- opening same cursor with different input value
 
  OPEN dep_det_c(1020);
  LOOP
    FETCH dep_det_c
      INTO all_data;
    EXIT WHEN dep_det_c%NOTFOUND;
    dbms_output.put_line('Department id : ' || all_data.d_id ||
                         ' Department Name : ' || all_data.d_name);
  END LOOP;
  CLOSE dep_det_c;
  dbms_output.put_line('-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-');
END;
/


/*sample output*/

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
Department id : 1 Department Name : Admin
Department id : 2 Department Name : HR
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
Department id : 3 Department Name : Sales
Department id : 4 Department Name : Marketing
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

Handling Exception


Error Handling in oracle

ERROR
    Any departure from the expected behavior of the system or program,
    which stops the working of the system is an error.

    Types : compile time error
        Run time error
EXCEPTION
    Any error or problem which one can handle and continue to work normally.

Handling Exception


    When exception is raised, control passes to the exception section of the block.

    i.e. EXCEPTION
        WHEN name_of_exception THEN

    Types : Pre Defined Exceptions
        User Defined Exceptions


Predefined Exception
*********************

    Oracle has predefined several exceptions that correspond to the most common oracle errors.

    ------------------------------------------------------------------------   
    Exception            Oracle Error         SQL Code Value
    ------------------------------------------------------------------------           
    ZERO_DIVIDE            ORA-01476        -1476
    NO_DATA_FOUND          ORA-01403        +100
    DUP_VAL_ON_INDEX       ORA-00001        -1
    TOO_MANY_ROWS          ORA-01422        -1422
    VALUE_ERROR            ORA-06502        -6502
    CURSOR_ALREADY_OPEN    ORA-06511        -6511
    OTHERS
   ------------------------------------------------------------------------


-->-- ZERO_DIVIDE  --<--

    Your program attempts to divide a number by zero.

    DECLARE
      v_result NUMBER;
    BEGIN
      SELECT 23 / 0 INTO v_result FROM dual;
    EXCEPTION
      WHEN ZERO_DIVIDE THEN
        dbms_output.put_line('Divisor is equal to zero');
    END;
   

-->-- NO_DATA_FOUND --<--

    Single row SELECT returned no rows or your program referenced a deleted element in a nested table
    or an uninitialized element in an associative array (index-by table).


    CREATE TABLE test_tb(id NUMBER PRIMARY KEY);

    DECLARE
      v_id NUMBER;
    BEGIN
      SELECT id INTO v_id FROM test_tb;
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        dbms_output.put_line('There is no data inside the table');
    END;


-->-- DUP_VAL_ON_INDEX --<--


    A program attempted to insert duplicate values in a column that is constrained by a unique index.

    INSERT INTO test_tb VALUES (1);
    INSERT INTO test_tb VALUES (2);
    commit;

    BEGIN
      INSERT INTO test_tb VALUES (2);
    EXCEPTION
      WHEN DUP_VAL_ON_INDEX THEN
        dbms_output.put_line('Duplicate values are not allowed');
    END;



-->-- TOO_MANY_ROWS --<--

    Single row SELECT returned multiple rows.

    DECLARE
      v_id NUMBER;
    BEGIN
      SELECT id INTO v_id FROM test_tb;
    EXCEPTION
      WHEN TOO_MANY_ROWS THEN
        dbms_output.put_line('Query returning more than one row');
    END;

    DROP TABLE test_tb;


-->-- VALUE_ERROR --<--

    An arithmetic, conversion, truncation, or size constraint error occurred.

    DECLARE
      num1 NUMBER(2);
    BEGIN
      num1 := 345;
    EXCEPTION
      WHEN VALUE_ERROR THEN
        dbms_output.put_line('check the size of the variable');
    END;


-->-- CURSOR_ALREADY_OPEN --<--

    A program attempted to open an already opened cursor.


    CREATE TABLE emp(id NUMBER, name VARCHAR2(30));

    BEGIN
       INSERT INTO emp VALUES(1,'Name1');
       INSERT INTO emp VALUES(2,'Name2');
       INSERT INTO emp VALUES(3,'Name3');
       INSERT INTO emp VALUES(4,'Name4');
       COMMIT;
    END;
   

    SELECT * FROM emp;

    DECLARE
      cursor emp_c IS
        SELECT * FROM emp;
      all_data emp%ROWTYPE;
    BEGIN
      OPEN emp_c;
      OPEN emp_c;
      NULL;
      CLOSE emp_c;
    EXCEPTION
      WHEN CURSOR_ALREADY_OPEN THEN
        dbms_output.put_line('Cursor already opened');
    END;

    DROP TABLE emp;


-->-- OTHERS --<--

        DECLARE
        v_result NUMBER;
      BEGIN
        SELECT 23 / 0 INTO v_result FROM dual;
      EXCEPTION
        WHEN CURSOR_ALREADY_OPEN THEN
          dbms_output.put_line('Cursor already opened');
        WHEN OTHERS THEN
          dbms_output.put_line('Some other error ' || SQLERRM);
      END;


User Defined Exception

**********************


    A user-defined exception is an error that is defined by the programmer.
    User-defined exceptions are declared in the declarative section of a PL/SQL block. Just like variables,
    exceptions have a type EXCEPTION and scope.


    DECLARE
      v_gender CHAR := '&gender';
      gender_ex EXCEPTION;
    BEGIN
      IF v_gender NOT IN ('M', 'F', 'm', 'f') THEN
        RAISE gender_ex;
      END IF;
      dbms_output.put_line('Gender : '||v_gender);
    EXCEPTION
      WHEN gender_ex THEN
        dbms_output.put_line('Please Enter valid gender');
    END;


    create table test_insert (id NUMBER, Name VARCHAR2(30));

    DECLARE
           abort_ex EXCEPTION;
    BEGIN
         FOR i IN 1..100
         LOOP
            BEGIN
                IF mod(i,10)=0 THEN
                   RAISE abort_ex;
                END IF;
            INSERT INTO test_insert VALUES(i, 'Name'||i);
            EXCEPTION
                    WHEN abort_ex THEN
                    NULL;
             END;
              END LOOP;
             COMMIT;
    END;

    SELECT * FROM test_insert;
 
    DROP TABLE test_insert;


SQLERRM and SQLCODE
********************

    SQLCODE returns the current error code, and SQLERRM returns the current error message text;
    For user-defined exception SQLCODE returns 1 and SQLERRM returns “user-defined exception”.
    SQLERRM will take only negative value except 100. If any positive value other than 100 returns non-oracle exception.


    CREATE TABLE test_tb (id NUMBER);

    DECLARE
      v_id NUMBER;
    BEGIN
      SELECT id INTO v_id FROM test_tb;
      dbms_output.put_line(v_id);
    EXCEPTION
      WHEN OTHERS THEN
        dbms_output.put_line('SQLERRM   :   ' || SQLERRM);
        dbms_output.put_line('SQLCODE   :   ' || SQLCODE);
    END;

/*sample output*/

    SQLERRM   :   ORA-01403: no data found
    SQLCODE   :   100

    DROP TABLE test_tb;


PRAGMA EXCEPTION_INIT

*********************
 
    Using this you can associate a named exception with a particular oracle error.
    This gives you the ability to trap this error specifically, rather than via an OTHERS handler.

Syntax:

    PRAGMA EXCEPTION_INIT(exception_name, oracle_error_number);

    DECLARE
      v_result NUMBER;
      PRAGMA EXCEPTION_INIT(Invalid, -1476);
    BEGIN
      SELECT 453 / 0 INTO v_result FROM dual;
      dbms_output.put_line('Result : ' || v_result);
    EXCEPTION
      WHEN INVALID THEN
        dbms_output.put_line('Invalid Exception');
    END;



RAISE_APPLICATION_ERROR

************************


    You can use this built-in function to create your own error messages, which can be more descriptive than named exceptions.

Error Number :

    Oracle Error Range :   From -00000 to -19999
      User Error Range  :   From -20000 to -20999


      DECLARE
        v_gender CHAR := '&gender';
    BEGIN
        IF v_gender NOT IN ('M', 'F', 'm', 'f') THEN
          RAISE_APPLICATION_ERROR(-20003, 'Enter valid gender');
        END IF;
        dbms_output.put_line('Gender : ' || v_gender);
    END;


Saturday, October 4, 2014

Package




1. You can groups logical related subprogram (procedures and functions)
2. It consist of two parts
        I) specification
        II) Body
3. It allows the oracle server to read multiple object in to a memory once
4. You can declare global variable,cursor, user define exeption
5. Overloading 
6. we can't create anonyms block inside the package



create table err_log(sno NUMBER, u_name VARCHAR2(30), error_msg CLOB, hap_tm TIMESTAMP);

select * from err_log;


--stand alone procedure

CREATE OR REPLACE PROCEDURE emp_sal_sp(p_employee_id IN employees.employee_id%TYPE) IS
    v_salary     employees.salary%TYPE;
    v_first_name employees.first_name%TYPE;
    v_error      VARCHAR2(1000);
BEGIN
    SELECT salary,
           first_name
      INTO v_salary,
           v_first_name
      FROM employees
     WHERE employee_id = p_employee_id;
    dbms_output.put_line('Salary of ' || v_first_name || ' is ' || v_salary);
EXCEPTION
    WHEN OTHERS THEN
        v_error := 'Error while fetching salary. Error : ' || SQLERRM;
        INSERT INTO err_log
        VALUES
            (1,
             USER,
             v_error,
             systimestamp);
    commit;
END emp_sal_sp;


BEGIN
  -- Call the procedure
  emp_sal_sp(p_employee_id => :p_employee_id);
END;


CREATE OR REPLACE PROCEDURE emp_hdt_sp(p_employee_id IN employees.employee_id%TYPE) IS
    v_hire_date  DATE;
    v_first_name employees.first_name%TYPE;
    v_error      VARCHAR2(1000);
BEGIN
    SELECT hire_date,
           first_name
      INTO v_hire_date,
           v_first_name
      FROM employees
     WHERE employee_id = p_employee_id;
    dbms_output.put_line(v_first_name || ' hired on ' || to_char(v_hire_date,'month ddth, yyyy'));
EXCEPTION
    WHEN OTHERS THEN
        v_error := 'Error while fetching salary. Error : ' || SQLERRM;
        INSERT INTO err_log
        VALUES
            (1,
             USER,
             v_error,
             systimestamp);
    commit;
END emp_hdt_sp;



BEGIN
  -- Call the procedure
  emp_hdt_sp(p_employee_id => :p_employee_id);
END;


create or replace function sum_fn (p_a IN NUMBER, p_b IN NUMBER)
RETURN NUMBER
IS
v_c NUMBER;
BEGIN
v_c := p_a + p_b;
RETURN v_c;
END;
/




--Specification Part

CREATE OR REPLACE PACKAGE emp_pkg 
IS 
PROCEDURE emp_sal_sp(p_employee_id IN employees.employee_id%TYPE);
PROCEDURE emp_hdt_sp(p_employee_id IN employees.employee_id%TYPE);

FUNCTION sum_fn (p_a IN NUMBER, p_b IN NUMBER)
RETURN NUMBER;

END emp_pkg ;

--Body Part

CREATE OR REPLACE PACKAGE BODY emp_pkg 
IS 

PROCEDURE emp_sal_sp(p_employee_id IN employees.employee_id%TYPE) IS
    v_salary     employees.salary%TYPE;
    v_first_name employees.first_name%TYPE;
    v_error      VARCHAR2(1000);
BEGIN
    SELECT salary,
           first_name
      INTO v_salary,
           v_first_name
      FROM employees
     WHERE employee_id = p_employee_id;
    dbms_output.put_line('Salary of ' || v_first_name || ' is ' || v_salary);
EXCEPTION
    WHEN OTHERS THEN
        v_error := 'Error while fetching salary. Error : ' || SQLERRM;
        INSERT INTO err_log
        VALUES
            (1,
             USER,
             v_error,
             systimestamp);
    commit;
END emp_sal_sp;


PROCEDURE emp_hdt_sp(p_employee_id IN employees.employee_id%TYPE) IS
    v_hire_date  DATE;
    v_first_name employees.first_name%TYPE;
    v_error      VARCHAR2(1000);
BEGIN
    SELECT hire_date,
           first_name
      INTO v_hire_date,
           v_first_name
      FROM employees
     WHERE employee_id = p_employee_id;
    dbms_output.put_line(v_first_name || ' hired on ' || to_char(v_hire_date,'month ddth, yyyy'));
EXCEPTION
    WHEN OTHERS THEN
        v_error := 'Error while fetching salary. Error : ' || SQLERRM;
        INSERT INTO err_log
        VALUES
            (1,
             USER,
             v_error,
             systimestamp);
    commit;
END emp_hdt_sp;

FUNCTION sum_fn (p_a IN NUMBER, p_b IN NUMBER)
RETURN NUMBER
IS
v_c NUMBER;
BEGIN
v_c := p_a + p_b;
RETURN v_c;
END;

END emp_pkg;
/


A package specification can exist without a package body, but 
a package body can't exist without a package specification.


--Executing procedure inside the package

BEGIN
 emp_pkg.emp_sal_sp(120);
END;

--Executing function inside the package

SELECT emp_pkg.sum_fn(23,567) FROM dual;

-- You can declare global variable,cursor, user define exeption


create or replace package all_detail
as
PROCEDURE emp2sal (a IN NUMBER);
PROCEDURE emp2exep (a IN NUMBER);
FUNCTION add2num (a IN NUMBER, b IN NUMBER)
RETURN NUMBER;

c NUMBER(8);  --global declaration

        abort_ex EXCEPTION; --global exception declaration
        
CURSOR emp_rec  --global cursor declaration
IS
SELECT first_name, salary, hire_date, department_id
FROM employees;

End all_detail;


create or replace package body all_detail
as

PROCEDURE emp2sal (a IN NUMBER)
AS

BEGIN
  SELECT salary
INTO   c
  FROM   Employees
WHERE  Employee_id = a;
Dbms_output.put_line('Salary of Employee ' || a || ' is ' || c);
EXCEPTION

        WHEN no_data_found THEN
Dbms_output.put_line('Please enter valid id');

END emp2sal;

PROCEDURE emp2exep (a IN NUMBER)
AS

BEGIN
  SELECT Round(Months_between(sysdate,hire_date)/12)
INTO   c
  FROM   Employees
WHERE  Employee_id = a;
Dbms_output.put_line( c || '  Years');
EXCEPTION
        WHEN no_data_found THEN
Dbms_output.put_line('Please enter valid id');
END emp2exep;



FUNCTION add2num (a IN NUMBER, b IN NUMBER)
RETURN NUMBER
AS
BEGIN
c := a+b;
RETURN C;
END;

End all_detail;


/*Declaring a Bodiless Package */


CREATE OR REPLACE PACKAGE global_constant
IS
     mile_2_kilo     CONSTANT  NUMBER :=  1.6093;
     kilo_2_mile     CONSTANT  NUMBER :=  0.6214;
     yard_2_meter    CONSTANT  NUMBER :=  0.9144;
     meter_2_yard    CONSTANT  NUMBER :=  1.0936;
END global_constant;


BEGIN
DBMS_OUTPUT.PUT_LINE('20 miles = ' || 20*global_constant.mile_2_kilo||' km');
END;


/*Forward Declaration in package */

DECLARE
      PROCEDURE P2;   --  forward declaration
      PROCEDURE P3; 
 
 PROCEDURE P1 IS
      BEGIN
         dbms_output.put_line('From procedure p1');
         p2;
      END P1;
      
      PROCEDURE P2 IS
      BEGIN
         dbms_output.put_line('From procedure p2');
         p3;
      END P2;
      
      PROCEDURE P3 IS
      BEGIN
      dbms_output.put_line('From procedure p3');
      END P3;
BEGIN
     p1;
END;


sample output:

From procedure p1
From procedure p2
From procedure p3


Drop package package_name;

Drop package body package_name;

SELECT text FROM user_source u
WHERE u.name = 'EMP_PKG';


Interview Questions:

What is package?
Advantage of package
Is it possible to create package body with out package specification?
what is package overloading?
what is forward declaration in package?
which data dictionary table contain source code of package?
How to declare global variable, exception and cursor?
How to execute procedure and function inside the package?



Thursday, October 2, 2014

%TYPE and %ROWTYPE



--%type is used to fetch the data type of the particular column


create table product_details
(
p_id     NUMBER(3),
p_nm     VARCHAR2(30),
p_qty    NUMBER(8),
order_dt DATE
);


BEGIN
         INSERT INTO product_details VALUES(100,'Name0',400,'23-Mar-13');
         INSERT INTO product_details VALUES(101,'Name1',600,'26-Apr-13');
         INSERT INTO product_details VALUES(102,'Name2',800,'27-Jan-12');
         INSERT INTO product_details VALUES(103,'Name3',300,'23-Jul-11');
         INSERT INTO product_details VALUES(104,'Name4',200,'22-Aug-11');
         INSERT INTO product_details VALUES(105,'Name5',500,'25-Oct-12');
         commit;
END;
/

SELECT * FROM product_details;

------------------------------------
P_ID       P_NM   P_QTY   ORDER_DT
------------------------------------
100  Name0  400  03/23/2013
101  Name1  600  04/26/2013
102  Name2  800  01/27/2012
103  Name3   300  07/23/2011
104  Name4  200  08/22/2011
105  Name5  500   10/25/2012
------------------------------------



DECLARE
    v_name VARCHAR2(4);
BEGIN
    SELECT p_nm
      INTO v_name
      FROM product_details
     WHERE p_id = 100;
    dbms_output.put_line('Product Name  : ' || v_name);
    --error numeric or value error      
END;


DECLARE
    v_name VARCHAR2(5);
BEGIN
    SELECT p_nm
      INTO v_name
      FROM product_details
     WHERE p_id = 100;
    dbms_output.put_line('Product Name  : ' || v_name);
END;
/


ALTER TABLE product_details
MODIFY p_nm VARCHAR2(15); 


INSERT INTO product_details
VALUES
    (106,
     'name6',
     700,
     '26-Dec-12');

commit;


106  name6 700   12/26/2012


DECLARE
      v_name VARCHAR2(5);
BEGIN
      SELECT p_nm INTO v_name
      FROM product_details
      WHERE p_id = 106;
      dbms_output.put_line('Product Name  : ' || v_name);
      --error
END;
/




DECLARE
    v_name product_details.p_nm%TYPE;
BEGIN
    SELECT p_nm
      INTO v_name
      FROM product_details
     WHERE p_id = 106;
    dbms_output.put_line('Product Name  : ' || v_name);
END;
/




DROP TABLE product_details;


DECLARE
    dep_id     departments.department_id%TYPE;
    dep_name   departments.department_name%TYPE;
    dep_man_id departments.manager_id%TYPE;
    dep_loc_id departments.location_id%TYPE;
BEGIN

    SELECT department_id,
           department_name,
           manager_id,
           location_id
      INTO dep_id,
           dep_name,
           dep_man_id,
           dep_loc_id
      FROM departments
     WHERE department_id = 10;

    dbms_output.put_line('Department_id   :    ' || dep_id);
    dbms_output.put_line('Department_name :    ' || dep_name);
    dbms_output.put_line('Manager_id   :    ' || dep_man_id);
    dbms_output.put_line('Location_id  :    ' || dep_loc_id);

END;
/


--%rowtype is used to fetch the data type of all the column
--Insted of using %type if we use %rowtype means we can reduce the no of variables that we declare



DECLARE
    dep_detail departments%ROWTYPE;
BEGIN

    SELECT *
      INTO dep_detail
      FROM departments
     WHERE department_id = 10;

    dbms_output.put_line('Department_id   :  ' || dep_detail.department_id);
    dbms_output.put_line('Department_name :  ' || dep_detail.department_name);
    dbms_output.put_line('Manager_id   :  ' || dep_detail.manager_id);
    dbms_output.put_line('Location_id  :  ' || dep_detail.location_id);

END;
/


DROP TABLE dept_details;

CREATE TABLE dept_details
(
   dept_id           number(3)   ,
   dept_name         varchar2(30),
   dept_manager_name varchar2(30)
);


insert into dept_details values(10,'dept1','manager_name1');
insert into dept_details values(20,'dept2','manager_name2');

SELECT * FROM dept_details;

    -------------------------------------------------------
    |  DEPT_ID   | DEPT_NAME   | DEPT_MANAGER_NAME |
    +------------+-----------------------+-----------------
    |  10  | dept1     | manager_name1     |
    |  20  | dept2     | manager_name2     |    
    ------------+-----------------------+------------------


DECLARE
    all_data dept_details%ROWTYPE;
BEGIN

    all_data.dept_id           := 100;
    all_data.dept_name         := 'Admin';
    all_data.dept_manager_name := 'John';

    UPDATE dept_details
       SET ROW = all_data
     WHERE dept_id = 10;

    dbms_output.put_line(SQL%ROWCOUNT || ' Row(s) get updated');

END;
/


1 Row(s) get updated


select * from dept_details;


      ---------------------------------------------------
    |  DEPT_ID   | DEPT_NAME   | DEPT_MANAGER_NAME|
      ---------------------------------------------------
    |  100 | Admin    | John         |
    |  20 | dept2    | manager_name2    |
      ---------------------------------------------------

Interview Question :

1. What is the use of %TYPE?
2. What is the use of %ROWTYPE?
3. Difference between %TYPE and %ROWTYPE?