Infolinks

Friday 10 August 2012

Oracle/PLSQL: Insert multiple rows with a single INSERT statement


Oracle/PLSQL: Insert multiple rows with a single INSERT statement


Question: How can I insert multiple rows of explicit data in one SQL command in Oracle?
Answer: You can insert multiple rows using the following syntax:
INSERT ALL
   INTO mytable (column1, column2, column3) VALUES ('val1.1', 'val1.2', 'val1.3')
   INTO mytable (column1, column2, column3) VALUES ('val2.1', 'val2.2', 'val2.3')
   INTO mytable (column1, column2, column3) VALUES ('val3.1', 'val3.2', 'val3.3')
SELECT * FROM dual;

Example #1

If you wanted to insert 3 rows into the suppliers table, you could run the following SQL statement:
INSERT ALL
   INTO suppliers (supplier_id, supplier_name) VALUES (1000, 'IBM')
   INTO suppliers (supplier_id, supplier_name) VALUES (2000, 'Microsoft')
   INTO suppliers (supplier_id, supplier_name) VALUES (3000, 'Google')
SELECT * FROM dual;

Example #2

You can also insert multiple rows into multiple tables. For example, if you wanted to insert into both the suppliers and customers table, you could run the following SQL statement:
INSERT ALL
   INTO suppliers (supplier_id, supplier_name) VALUES (1000, 'IBM')
   INTO suppliers (supplier_id, supplier_name) VALUES (2000, 'Microsoft')
   INTO customers (customer_id, customer_name, city) VALUES (999999, 'Anderson Construction', 'New York')
SELECT * FROM dual;
This example will insert 2 rows into the suppliers table and 1 row into the customers table.

Oracle/PLSQL Topics: Oracle Error Messages


Oracle/PLSQL Topics: Oracle Error Messages


The following is a listing of Oracle Error Messages:
00001-00899
ORA-00001ORA-00051ORA-00068ORA-00257
ORA-00018ORA-00054ORA-00071ORA-00301
ORA-00020ORA-00057ORA-00078ORA-00304
ORA-00023ORA-00058ORA-00100ORA-00361
ORA-00028ORA-00060ORA-00107ORA-00401
ORA-00034ORA-00063ORA-00201

00900-00999
ORA-00900ORA-00917ORA-00933ORA-00957
ORA-00902ORA-00918ORA-00934ORA-00960
ORA-00903ORA-00919ORA-00935ORA-00962
ORA-00904ORA-00920ORA-00936ORA-00971
ORA-00905ORA-00923ORA-00937ORA-00972
ORA-00906ORA-00924ORA-00938ORA-00975
ORA-00907ORA-00925ORA-00939ORA-00979
ORA-00908ORA-00926ORA-00942ORA-00980
ORA-00909ORA-00927ORA-00946ORA-00984
ORA-00910ORA-00928ORA-00947ORA-00985
ORA-00911ORA-00931ORA-00948ORA-00995
ORA-00913ORA-00932ORA-00955

01000-01399
ORA-01000ORA-01013ORA-01039ORA-01114
ORA-01001ORA-01014ORA-01040ORA-01133
ORA-01002ORA-01017ORA-01042ORA-01200
ORA-01004ORA-01023ORA-01045ORA-01234
ORA-01005ORA-01031ORA-01052
ORA-01006ORA-01033ORA-01074
ORA-01007ORA-01034ORA-01089
ORA-01008ORA-01035ORA-01109
ORA-01012ORA-01037ORA-01113

01400-01499
ORA-01400ORA-01422ORA-01435ORA-01452
ORA-01401ORA-01423ORA-01436ORA-01453
ORA-01402ORA-01424ORA-01437ORA-01454
ORA-01403ORA-01425ORA-01438ORA-01461
ORA-01404ORA-01426ORA-01439ORA-01465
ORA-01405ORA-01427ORA-01440ORA-01468
ORA-01406ORA-01428ORA-01441ORA-01471
ORA-01407ORA-01429ORA-01442ORA-01476
ORA-01408ORA-01430ORA-01446
ORA-01416ORA-01432ORA-01448
ORA-01417ORA-01433ORA-01449
ORA-01418ORA-01434ORA-01451

01500-01999
ORA-01504ORA-01719ORA-01785ORA-01846
ORA-01506ORA-01722ORA-01789ORA-01847
ORA-01555ORA-01723ORA-01790ORA-01858
ORA-01632ORA-01724ORA-01810ORA-01861
ORA-01652ORA-01727ORA-01818ORA-01916
ORA-01653ORA-01728ORA-01820ORA-01918
ORA-01700ORA-01747ORA-01821ORA-01950
ORA-01704ORA-01756ORA-01830
ORA-01710ORA-01775ORA-01839
ORA-01711ORA-01779ORA-01843

02000-06499
ORA-02003ORA-02268ORA-02437ORA-04091
ORA-02011ORA-02270ORA-02444ORA-04092
ORA-02024ORA-02290ORA-02449ORA-04098
ORA-02069ORA-02291ORA-03113
ORA-02086ORA-02292ORA-04000
ORA-02256ORA-02293ORA-04031
ORA-02260ORA-02298ORA-04088

06500-09999
ORA-06500ORA-06508ORA-06514ORA-06572
ORA-06501ORA-06510ORA-06515ORA-06575
ORA-06502ORA-06511ORA-06550ORA-08002
ORA-06503ORA-06512ORA-06564ORA-08103

10000 - 12999
ORA-12154

Oracle/PLSQL: SQLERRM Function


Oracle/PLSQL: SQLERRM Function


What does the SQLERRM Function do?

The SQLERRM function returns the error message associated with the most recently raised error exception. This function should only be used within the Exception Handling section of your code:
EXCEPTION
    WHEN exception_name1 THEN
        [statements]
    WHEN exception_name2 THEN
        [statements]
    WHEN exception_name_n THEN
        [statements]
    WHEN OTHERS THEN
        [statements]
END [procedure_name];

You could use the SQLERRM function to raise an error as follows:
EXCEPTION
   WHEN OTHERS THEN
      raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;

Or you could log the error to a table as follows:
EXCEPTION
   WHEN OTHERS THEN
      err_code := SQLCODE;
      err_msg := substr(SQLERRM, 1, 200);
      INSERT INTO audit_table (error_number, error_message)
      VALUES (err_code, err_msg);
END;

Oracle/PLSQL: SQLCODE Function


Oracle/PLSQL: SQLCODE Function


What does the SQLCODE Function do?

The SQLCODE function returns the error number associated with the most recently raised error exception. This function should only be used within the Exception Handling section of your code:
EXCEPTION
    WHEN exception_name1 THEN
        [statements]
    WHEN exception_name2 THEN
        [statements]
    WHEN exception_name_n THEN
        [statements]
    WHEN OTHERS THEN
        [statements]
END [procedure_name];

You could use the SQLCODE function to raise an error as follows:
EXCEPTION
   WHEN OTHERS THEN
      raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;

Or you could log the error to a table as follows:
EXCEPTION
   WHEN OTHERS THEN
      err_code := SQLCODE;
      err_msg := substr(SQLERRM, 1, 200);
      INSERT INTO audit_table (error_number, error_message)
      VALUES (err_code, err_msg);
END;

Oracle/PLSQL: WHEN OTHERS Clause


Oracle/PLSQL: WHEN OTHERS Clause


What is a WHEN OTHERS clause?

The WHEN OTHERS clause is used to trap all remaining exceptions that have not been handled by your Named System Exceptions and Named Programmer-Defined Exceptions.
The syntax for the WHEN OTHERS clause in a procedure is:
CREATE [OR REPLACE] PROCEDURE procedure_name
    [ (parameter [,parameter]) ]
IS
    [declaration_section]
BEGIN
    executable_section
EXCEPTION
    WHEN exception_name1 THEN
        [statements]
    WHEN exception_name2 THEN
        [statements]
    WHEN exception_name_n THEN
        [statements]
    WHEN OTHERS THEN
        [statements]
END [procedure_name];

The syntax for the WHEN OTHERS clause in a function is:
CREATE [OR REPLACE] FUNCTION function_name
    [ (parameter [,parameter]) ]
    RETURN return_datatype
IS | AS
    [declaration_section]
BEGIN
    executable_section
EXCEPTION
    WHEN exception_name1 THEN
        [statements]
    WHEN exception_name2 THEN
        [statements]
    WHEN exception_name_n THEN
        [statements]
    WHEN OTHERS THEN
        [statements]
END [function_name];

Here is an example of a procedure that uses a WHEN OTHERS clause:
CREATE OR REPLACE PROCEDURE add_new_order
    (order_id_in IN NUMBER, sales_in IN NUMBER)
IS
    no_sales EXCEPTION;
BEGIN
    IF sales_in = 0 THEN
        RAISE no_sales;
ELSE
    INSERT INTO orders (order_id, total_sales )
    VALUES ( order_id_in, sales_in );
END IF;
EXCEPTION
     WHEN DUP_VAL_ON_INDEX THEN
        raise_application_error (-20001,'You have tried to insert a duplicate order_id.');
    WHEN no_sales THEN
        raise_application_error (-20001,'You must have sales in order to submit the order.');
    WHEN OTHERS THEN
        raise_application_error (-20002,'An error has occurred inserting an order.');
END;
In this example, if an exception is encountered that is not a DUP_VAL_ON_INDEX or a no_sales, it will be trapped by the WHEN OTHERS clause.

Frequently Asked Questions


Question: Is there any way to get the ORA error number (and/or description) for the errors that will fall into OTHERS?
Something like:
WHEN OTHERS THEN
'Error number ' & Err.Number& ' has happen.'
Answer: Yes, you can use SQLCODE function to retrieve the error number and SQLERRM function to retrieve the error message.
For example, you could raise the error as follows:
EXCEPTION
   WHEN OTHERS THEN
      raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;

Or you could log the error to a table as follows:
EXCEPTION
   WHEN OTHERS THEN
      err_code := SQLCODE;
      err_msg := substr(SQLERRM, 1, 200);
      INSERT INTO audit_table (error_number, error_message)
      VALUES (err_code, err_msg);
END;

Oracle/PLSQL: Named Programmer-Defined Exceptions


Oracle/PLSQL: Named Programmer-Defined Exceptions


What is a named programmer-defined exception?

Sometimes, it is necessary for programmers to name and trap their own exceptions - ones that aren't defined already by PL/SQL. These are called Named Programmer-Defined Exceptions.
The syntax for the Named Programmer-Defined Exception in a procedure is:
CREATE [OR REPLACE] PROCEDURE procedure_name
    [ (parameter [,parameter]) ]
IS
    [declaration_section]
    exception_name EXCEPTION;
BEGIN
    executable_section
    RAISE exception_name ;
EXCEPTION
    WHEN exception_name THEN
        [statements]
    WHEN OTHERS THEN
        [statements]
END [procedure_name];

The syntax for the Named Programmer-Defined Exception in a function is:
CREATE [OR REPLACE] FUNCTION function_name
    [ (parameter [,parameter]) ]
    RETURN return_datatype
IS | AS
    [declaration_section]
    exception_name EXCEPTION;
BEGIN
    executable_section
    RAISE exception_name ;
EXCEPTION
    WHEN exception_name THEN
        [statements]
    WHEN OTHERS THEN
        [statements]
END [function_name];

Here is an example of a procedure that uses a Named Programmer-Defined Exception:
CREATE OR REPLACE PROCEDURE add_new_order
    (order_id_in IN NUMBER, sales_in IN NUMBER)
IS
    no_sales EXCEPTION;
BEGIN
    IF sales_in = 0 THEN
        RAISE no_sales;
ELSE
    INSERT INTO orders (order_id, total_sales )
    VALUES ( order_id_in, sales_in );
END IF;
EXCEPTION
     WHEN no_sales THEN
        raise_application_error (-20001,'You must have sales in order to submit the order.');
    WHEN OTHERS THEN
        raise_application_error (-20002,'An error has occurred inserting an order.');
END;
In this example, we have declared a Named Programmer-Defined Exception called no_sales in our declaration statement with the following code:
no_sales EXCEPTION;

We've then raised the exception in the executable section of the code:
 IF sales_in = 0 THEN
        RAISE no_sales;
Now if the sales_in variable contains a zero, our code will jump directly to the Named Programmer-Defined Exception called no_sales.

Finally, we tell our procedure what to do when the no_sales exception is encountered by including code in the WHEN clause:
WHEN no_sales THEN
        raise_application_error (-20001,'You must have sales in order to submit the order.');

We are also using the WHEN OTHERS clause to trap all remaining exceptions:
 WHEN OTHERS THEN
        raise_application_error (-20002,'An error has occurred inserting an order.');

Oracle/PLSQL: Named System Exceptions


Oracle/PLSQL: Named System Exceptions


What is a named system exception?

Named system exceptions are exceptions that have been given names by PL/SQL. They are named in the STANDARD package in PL/SQL and do not need to be defined by the programmer.
Oracle has a standard set of exceptions already named as follows:
Oracle Exception NameOracle ErrorExplanation
DUP_VAL_ON_INDEXORA-00001You tried to execute an INSERT or UPDATE statement that has created a duplicate value in a field restricted by a unique index.
TIMEOUT_ON_RESOURCEORA-00051You were waiting for a resource and you timed out.
TRANSACTION_BACKED_OUTORA-00061The remote portion of a transaction has rolled back.
INVALID_CURSORORA-01001You tried to reference a cursor that does not yet exist. This may have happened because you've executed a FETCH cursor or CLOSE cursor before OPENing the cursor.
NOT_LOGGED_ONORA-01012You tried to execute a call to Oracle before logging in.
LOGIN_DENIEDORA-01017You tried to log into Oracle with an invalid username/password combination.
NO_DATA_FOUNDORA-01403You tried one of the following:
  1. You executed a SELECT INTO statement and no rows were returned.
  2. You referenced an uninitialized row in a table.
  3. You read past the end of file with the UTL_FILE package.
TOO_MANY_ROWSORA-01422You tried to execute a SELECT INTO statement and more than one row was returned.
ZERO_DIVIDEORA-01476You tried to divide a number by zero.
INVALID_NUMBERORA-01722You tried to execute an SQL statement that tried to convert a string to a number, but it was unsuccessful.
STORAGE_ERRORORA-06500You ran out of memory or memory was corrupted.
PROGRAM_ERRORORA-06501This is a generic "Contact Oracle support" message because an internal problem was encountered.
VALUE_ERRORORA-06502You tried to perform an operation and there was a error on a conversion, truncation, or invalid constraining of numeric or character data.
CURSOR_ALREADY_OPENORA-06511You tried to open a cursor that is already open.
The syntax for the Named System Exception in a procedure is:
CREATE [OR REPLACE] PROCEDURE procedure_name
    [ (parameter [,parameter]) ]
IS
    [declaration_section]
BEGIN
    executable_section
EXCEPTION
    WHEN exception_name1 THEN
        [statements]
    WHEN exception_name2 THEN
        [statements]
    WHEN exception_name_n THEN
        [statements]
    WHEN OTHERS THEN
        [statements]
END [procedure_name];

The syntax for the Named System Exception in a function is:
CREATE [OR REPLACE] FUNCTION function_name
    [ (parameter [,parameter]) ]
    RETURN return_datatype
IS | AS
    [declaration_section]
BEGIN
    executable_section
EXCEPTION
    WHEN exception_name1 THEN
        [statements]
    WHEN exception_name2 THEN
        [statements]
    WHEN exception_name_n THEN
        [statements]
    WHEN OTHERS THEN
        [statements]
END [function_name];

Here is an example of a procedure that uses a Named System Exception:
CREATE OR REPLACE PROCEDURE add_new_supplier
    (supplier_id_in IN NUMBER, supplier_name_in IN VARCHAR2)
IS
BEGIN
    INSERT INTO suppliers (supplier_id, supplier_name )
    VALUES ( supplier_id_in, supplier_name_in );
EXCEPTION
    WHEN DUP_VAL_ON_INDEX THEN
        raise_application_error (-20001,'You have tried to insert a duplicate supplier_id.');
    WHEN OTHERS THEN
        raise_application_error (-20002,'An error has occurred inserting a supplier.');
END;
In this example, we are trapping the Named System Exception called DUP_VAL_ON_INDEX. We are also using the WHEN OTHERS clause to trap all remaining exceptions.

Retrieve third lowest value from a table


Retrieve third lowest value from a table


Question: How can I retrieve the third lowest salary amount from a salary table?

Answer: To retrieve the third lowest salary from a salary table, you could run the following query: (please note that the subquery is sorted in ascending order)
SELECT salary_amount
FROM(select salary2.*, rownum rnum from
(select * from salary ORDER BY salary_amount) salary2
where rownum <= 3 )
WHERE rnum >= 3;

If you wanted to retrieve all fields from the salary table for the third lowest salary, you could run the following query: (please note that the subquery is sorted in ascending order)
SELECT *
FROM(select salary2.*, rownum rnum from
(select * from salary ORDER BY salary_amount) salary2
where rownum <= 3 )
WHERE rnum >= 3;

Retrieve second lowest value from a table


Retrieve second lowest value from a table


Question: How can I retrieve the second lowest salary amount from a salary table?

Answer: To retrieve the second lowest salary from a salary table, you could run the following query: (please note that the subquery is sorted in ascending order)
<
SELECT salary_amount
FROM(select salary2.*, rownum rnum from
(select * from salary ORDER BY salary_amount) salary2
where rownum <= 2 )
WHERE rnum >= 2;

If you wanted to retrieve all fields from the salary table for the second lowest salary, you could run the following query: (please note that the subquery is sorted in ascending order)
SELECT *
FROM(select salary2.*, rownum rnum from
(select * from salary ORDER BY salary_amount) salary2
where rownum <= 2 )
WHERE rnum >= 2;

Retrieve third highest value from a table


Retrieve third highest value from a table


Question: How can I retrieve the third highest salary amount from a salary table?

Answer: To retrieve the third highest salary from a salary table, you could run the following query: (please note that the subquery is sorted in descending order)
SELECT salary_amount
FROM(select salary2.*, rownum rnum from
(select * from salary ORDER BY salary_amount DESC) salary2
where rownum <= 3 )
WHERE rnum >= 3;

If you wanted to retrieve all fields from the salary table for the third highest salary, you could run the following query: (please note that the subquery is sorted in descending order)
SELECT *
FROM(select salary2.*, rownum rnum from
(select * from salary ORDER BY salary_amount DESC) salary2
where rownum <= 3 )
WHERE rnum >= 3;

Retrieve second highest value from a table


Retrieve second highest value from a table


Question: How can I retrieve the second highest salary amount from a salary table?

Answer: To retrieve the second highest salary from a salary table, you could run the following query: (please note that the subquery is sorted in descending order)
SELECT salary_amount
FROM(select salary2.*, rownum rnum from
(select * from salary ORDER BY salary_amount DESC) salary2
where rownum <= 2 )
WHERE rnum >= 2;

If you wanted to retrieve all fields from the salary table for the second highest salary, you could run the following query: (please note that the subquery is sorted in descending order)
SELECT *
FROM(select salary2.*, rownum rnum from
(select * from salary ORDER BY salary_amount DESC) salary2
where rownum <= 2 )
WHERE rnum >= 2;

Retrieve Middle N records from a query


Retrieve Middle N records from a query


Question: How can I retrieve the Middle N records from a query?
For example, what if I wanted to retrieve records 3 to 5 from my query results. How can I do this?

Answer: To retrieve the Middle N records from a query, you can use the following syntax:
SELECT *
FROM(select alias_name.*, rownum rnum from
(-- your ordered query --) alias_name
where rownum <= UPPER_BOUND )
WHERE rnum >= LOWER_BOUND;

For example, if you wanted to retrieve records 3 through 5 from the suppliers table, sorted by supplier_name in ascending order, you would run the following query:
SELECT *
FROM(select suppliers2.*, rownum rnum from
(select * from suppliers ORDER BY supplier_name) suppliers2
where rownum <= 5 )
WHERE rnum >= 3;

If you wanted to retrieve records 3 through 5 from the suppliers table, sorted by supplier_name in descending order, you would run the following query:
SELECT *
FROM(select suppliers2.*, rownum rnum from
(select * from suppliers ORDER BY supplier_name DESC) suppliers2
where rownum <= 5 )
WHERE rnum >= 3;

If you wanted to retrieve records 2 through 4 from the suppliers table, sorted by supplier_id in ascending order, you would run the following query:
SELECT *
FROM(select suppliers2.*, rownum rnum from
(select * from suppliers ORDER BY supplier_id) suppliers2
where rownum <= 4 )
WHERE rnum >= 2;

If you wanted to retrieve records 2 through 4 from the suppliers table, sorted by supplier_id in descending order, you would run the following query:
SELECT *
FROM(select suppliers2.*, rownum rnum from
(select * from suppliers ORDER BY supplier_id DESC) suppliers2
where rownum <= 4 )
WHERE rnum >= 2;

Retrieve Bottom N records from a query


Retrieve Bottom N records from a query


Question: How can I retrieve the Bottom N records from a query?
For example, what if I wanted to retrieve the last 3 records from my query results. How can I do this?

Answer: To retrieve the Bottom N records from a query, you can use the following syntax:
SELECT *
FROM (your query ordered in reverse) alias_name
WHERE rownum <= Rows_to_return
ORDER BY rownum DESC;
If you want to retrieve the bottom records from a query, you need to order your results in reverse in the "your query ordered in reverse" section of the solution above.

For example, if you wanted to retrieve the last 3 records from the suppliers table, sorted by supplier_name in ascending order, you would run the following query:
SELECT *
FROM (select * from suppliers ORDER BY supplier_name DESC) suppliers2
WHERE rownum <= 3
ORDER BY rownum DESC;
Notice that although you want the last 3 records sorted by supplier_name in ascending order, you actually sort the supplier_name in descending order in this solution.

If you wanted to retrieve the last 3 records from the suppliers table, sorted by supplier_name in descending order, you would run the following query:
SELECT *
FROM (select * from suppliers ORDER BY supplier_name) suppliers2
WHERE rownum <= 3
ORDER BY rownum DESC;

If you wanted to retrieve the last 5 records from the suppliers table, sorted by supplier_id in ascending order, you would run the following query:
SELECT *
FROM (select * from suppliers ORDER BY supplier_id DESC) suppliers2
WHERE rownum <= 5
ORDER BY rownum DESC;

If you wanted to retrieve the last 5 records from the suppliers table, sorted by supplier_id in descending order, you would run the following query:
SELECT *
FROM (select * from suppliers ORDER BY supplier_id) suppliers2
WHERE rownum <= 5
ORDER BY rownum DESC;