Friday, January 31, 2014

SQL loader


DROP DIRECTORY emp_dir;

--
-- emp_dir (Directory)
--
CREATE OR REPLACE DIRECTORY
emp_dir AS
'G:\FLAT_FILES';

GRANT READ, WRITE ON DIRECTORY emp_dir TO SCOTT WITH GRANT OPTION;



CREATE TABLE oldemp (
empno NUMBER,empname CHAR(20),birthdate DATE)
ORGANIZATION EXTERNAL
(TYPE ORACLE_LOADER
DEFAULT DIRECTORY emp_dir
ACCESS PARAMETERS
(RECORDS DELIMITED BY NEWLINE
BADFILE 'bad_emp'
LOGFILE 'log_emp'
FIELDS terminated by ','
(empno CHAR,
empname CHAR,
birthdate CHAR date_format date mask "dd-mon-yyyy"))
LOCATION ('emp1.txt'))
PARALLEL 5
REJECT LIMIT 200;


Sunday, January 26, 2014

Oracle Analytic Functions

Oracle Analytic Functions :

Oracle Analytic Functions compute an aggregate value based on a group of rows.Analytic functions differ from aggregate functions in the sense that they return multiple rows for each group. The group of rows is called a window and is defined by the analytic clause. For each row, a sliding window of rows is defined. The window determines the range of rows used to perform the calculations for the current row.

Oracle provides many Analytic Functions such as

AVG, CORR, COVAR_POP, COVAR_SAMP, COUNT, CUME_DIST, DENSE_RANK, FIRST, FIRST_VALUE, LAG, LAST, LAST_VALUE, LEAD, MAX, MIN, NTILE, PERCENT_RANK, PERCENTILE_CONT, PERCENTILE_DISC, RANK, RATIO_TO_REPORT, STDDEV, STDDEV_POP, STDDEV_SAMP, SUM, VAR_POP, VAR_SAMP, VARIANCE.

The Syntax of analytic functions:
Analytic-Function(Column1,Column2,...)
OVER (
[Query-Partition-Clause]
[Order-By-Clause]
[Windowing-Clause]
)
or
The general syntax of analytic function is:
Function(arg1,..., argn) OVER ( [PARTITION BY <...>] [ORDER BY <....>] [<window_clause>] )
--window_clause> is like "ROW <?>" or "RANK <?>" 

Analytic functions take 0 to 3 arguments.

It is true that whatever an analytic function does can be done by native SQL, with join and sub-queries. But the same routine done by analytic function is always faster, or at least as fast, when compared to native SQL




SELECT deptno,
COUNT(*) DEPT_COUNT
FROM emp
WHERE deptno IN (20, 30)
GROUP BY deptno;



    DEPTNO DEPT_COUNT
---------- ----------
        30          6
        20          5

2 rows selected.

Consider the Query-1 and its result. Query-1 returns departments and their employee count. Most importantly it groups the records into departments in accordance with the GROUP BY clause. As such any non-"group by" column is not allowed in the select clause.

Query 2:


SELECT empno, deptno, 
COUNT(*) OVER (PARTITION BY 
deptno) DEPT_COUNT
FROM emp
WHERE deptno IN (20, 30);

    EMPNO     DEPTNO DEPT_COUNT
---------- ---------- ----------
      7369         20          5
      7876         20          5
      7566         20          5
      7788         20          5
      7902         20          5
      7900         30          6
      7844         30          6
      7654         30          6
      7521         30          6
      7499         30          6
      7698         30          6

11 rows selected.

Now consider the analytic function query (Query-2) and its result. Note the repeating values of DEPT_COUNT column.
This brings out the main difference between aggregate and analytic functions. Though analytic functions give aggregate result they do not group the result set. They return the group value multiple times with each record. As such any other non-"group by" column or expression can be present in the select clause, for example, the column EMPNO in Query-2.
Analytic functions are computed after all joins, WHERE clause, GROUP BY and HAVING are computed on the query. The main ORDER BY clause of the query operates after the analytic functions. So analytic functions can only appear in the select list and in the main ORDER BY clause of the query.
In absence of any PARTITION or <window_clause> inside the OVER( ) portion, the function acts on entire record set returned by the where clause. Note the results of Query-3 and compare it with the result of aggregate function query Query-4.
Query : 3
SELECT empno, deptno,
COUNT(*) OVER ( ) CNT
FROM emp
WHERE deptno IN (10, 20)
ORDER BY 2, 1;


     EMPNO     DEPTNO        CNT
---------- ---------- ----------
      7782         10          8
      7839         10          8
      7934         10          8
      7369         20          8
      7566         20          8
      7788         20          8
      7876         20          8
      7902         20          8

8 rows selected.

Query : 4

SELECT COUNT(*) FROM emp
WHERE deptno IN (10, 20);

correlated subquery

The Correlated subqueries are used for row-by-row processing .Each subquery is executed once for each row of the outer query.


  • GET candidate row from outer query
  • EXECUTE inner query using the candidate row value
  • USE values from inner query to qualify or disqualify candidate row.

The non-correlated subquery or Nested Subquery is  that ,  the subquery can be run independently of the outer query. Basically, the subquery has no relationship with the outer query.

Now, a correlated subquery has the opposite property – the subquery can not be run independently of the outer query. You can take a look at this example of a correlated subquery below and easily see the difference yourself:


SELECT *
FROM Employee Emp1
WHERE (1) = (
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)

It’s important to understand the order of operations in a correlated subquery. First, a row is processed in the outer query. Then, for that particular row the subquery is executed – so for each row processed by the outer query, the subquery will also be processed. In our example of a correlated subquery above, every time a row is processed for Emp1, the subquery will also choose that row’s value for Emp1.Salary and run. And then the outer query will move on to the next row, and the subquery will execute for that row’s value of Emp1.Salary. This will continue until the “WHERE (1) = (… )” condition is satisfied.

The Oracle server performs  a correlated subquery when the subquery reference a column from a table refererred to in the parent statement. A correlated subquery is evaluated once for each row processed by the parent statement . The parent statement can be SELECT ,UPDATE or DELETE statement.

Nested subqueries versus Correlated Subquery:

With a normal subquery, the inner SELECT query runs first and execute once, returning values to be used by the main query.  A Correlated subquery however executes once for each candidate row considered by the outer query. In other words, the inner query is driven by the outer query.

Nested subqueries :

  • The inner query executes first and find a value.
  • The outer query executes once, using the value from the inner query.

Correlated Subqueries:


  • Get a candidate row (fethched by the outer query).
  • Executes the inner query using the value of the candidate row.
  • Use the values resulting from the inner query to qualify or disqualify the candidate.
  • Repeat until no candidate row remains.


Ex: Using Correlated Subquery find all employees who earn more than the average salary in their department.

SELECT last_name, salary,department_id     -- Parent Query
FROM employees outer
WHERE salary > ( SELECT AVG(salary)
                             FROM  employees
                          WHERE department_id=outer.department_id);


-- The subquery references a column from a table in the parent query. each time a row in the outer  query is processed , the inner query is evaluated.

The example in the slide determines which employee earns more than the avearge salary of their department. In this case, the correlated subquery specifically computes the avearage salary for each department.

Because both the outer query and inner query use the EMPLOYEES table in the FROM clause , an alias is given to the EMPLOYEES in the outer SELECT statement, for calrity. Not only does the alias make the entire SELECT statement more readable, but without the alias the query would not work properly , because the inner statement would not be able to distinguish the inner table column from the outer table column.

/* Using Correlated subquery display details of those employees who has switched jobs at least twice*/

SELECT e.employee_id, last_name,e.job_id
FROM employees e
WHERE 2 <= ( SELECT COUNT(*)
                 FROM  job_history
                 WHERE employee_id=e.employee_id);


The Oracle server evaluates the  a correlated subquery as follows.

1. Select a row from the table specified in the outer query . This will be current candidate row .
2.Store the value of the column referenced in the subquery from the candidate row  (here the column referenced in the subquery is e. employee_id)
3.Perform the subquery with its condition referencing the value from the outer query's candidate row. ( here group funtion count(*) is evaluated based on the value of                                              
                                                                                                                                                   e.employee_id column based on the step 2)
4. Evaluate the WHERE clause of the outer query on the basis of the results of the subquery performed on step3. this determines if the candidate row is selected for output. ( Here, the number of times the employee has switched jobs, evaluated by the subquery , is compared with 2 in the WHERE clause of the outer query.If the condition is satisfied that employee record is displayed.)

5.Repeat the procedure for the next candidate row of the table , and so until all row in the table have been processed.

The Correlation is established by using an element from the outer query in the subquery.In this example , the correlation is established by the statement employee_id =e.employee_id in which you compare employee_id from the table in the subquery with the employee_id from table in the outer query.

Friday, January 24, 2014

Using a Subquery in the FROM clause : inline view

Inline view:

You can use  a subquery in the FROM clause of a SELECT statement , which is very similar to how views are used. A subquery in the FROM clause of a SELECT statement is also called an inline view.  A subquery in the FROM clause  of a SELECT statement defines a data source for the particular SELECT statement, and only that SELECT statement.  The example below displays employee last names, salaries,department number  and average salaries  for all the employees who earn more than the average salary in their department. The subquery in the FROM clause is named b , the outer query references the SALAVG column using this alias.

SELECT  a.last_name ,a.salary,a.department_id,b.salavg
FROM employees a , ( SELECT department_id,
                                 AVG(salary) salavg
                                 FROM employees 
                                 GROUP BY department_id) b
                                 
WHERE a.department_id =b.department_id
AND a.salary >b.salavg;


LAST_NAME                     SALARY DEPARTMENT_ID     SALAVG
------------------------- ---------- ------------- ----------
Hartstein                      13000            20       9500
Higgins                        12000           110      10150
King                           24000            90 19333.3333
.........
.........
38 rows selected.

Thursday, January 23, 2014

Advanced Subqueries: (Pairwise and Non-pairwise Subquery)

Sub Query:
A sub query is a SELECT statement that is embeded in a clause of another SQL statement,called the parent statement.

The subquery (inner query )returns a value that is used by the parent statement. Using a nested sub query is equivalent to performing two sequential queries and using the result of inner query as search value in the outer query (main query).

Purpose of use of sub query:

To  Provide values for conditions in WHERE ,HAVING  and START WITH  clause of SELECT statements.

  • To define the set of rows to be inserted into the target table of an INSERT or CREATE TABLE statement.
  • To define the set of rows to be included in a view or snapshot in a CREATE VIEW or CREATE SNAPSHOT statement.
  • To definf one or more values to be assigned to existing rows in an update statement.
  • To define a table to be operated on by a containing query .( You do this by placing the sub query in the FROM  clause. This can be done in INSERT ,UPDATE and DELETE statements as well.)


A  sub query is evaluated once for the entire parent statement.

Syntax:

SELECT select_list

FROM table

WHERE expr operator (SELECT select_list

                                        FROM table);


The subquery (inner query) executes once before the main query.

The result of the sub query is used by the main query (outer query).                                                                                            

Ex-1: Display the last name of employees who earn more than the the employee with id 200;


SELECT last_name
FROM employees
WHERE salary >
           
               (SELECT salary
       FROM employees
       WHERE employee_id=200);



Ex-1: Display the names of all who earn less than the average salary in the company.

SELECT last_name,job_id,salary
FROM employees
WHERE salary <
              (SELECT AVG(salary)
               FROM employees );



Single-row and multiple-row subqueries: 

Subqueries that can return only one or zero rows to the outer statement are called single-row subqueries. Single-row subqueries are subqueries used with a comparison operator in a WHERE, or HAVING clause.

Subqueries that can return more than one row (but only one column) to the outer statement are called multiple-row subqueries. Multiple-row subqueries are subqueries used with an IN, ANY, or ALL clause.


Example 1: Single-row subquery
You store information particular to products in one table, Products, and information that pertains to sales orders in another table, SalesOrdersItems. The Products table contains the information about the various products. The SalesOrdersItems table contains information about customers' orders. If a company reorders products when there are fewer than 50 of them in stock, then it is possible to answer the question "Which products are nearly out of stock?" with this query:

SELECT ID, Name, Description, Quantity
FROM Products
WHERE Quantity < 50;


However, a more helpful result would take into consideration how frequently a product is ordered, since having few of a product that is frequently purchased is more of a concern than having few product that is rarely ordered.

You can use a subquery to determine the average number of items that a customer orders, and then use that average in the main query to find products that are nearly out of stock. The following query finds the names and descriptions of the products which number less than twice the average number of items of each type that a customer orders.

SELECT Name, Description
FROM Products WHERE Quantity <  2 * (
   SELECT AVG( Quantity )
   FROM SalesOrderItems
   );

In the WHERE clause, subqueries help select the rows from the tables listed in the FROM clause that appear in the query results. In the HAVING clause, they help select the row groups, as specified by the main query's GROUP BY clause, that appear in the query results.

Example 2: Single-row subquery

The following example of a single-row subquery calculates the average price of the products in the Products table. The average is then passed to the WHERE clause of the outer query. The outer query returns the ID, Name, and UnitPrice of all products that are less expensive than the average:

SELECT ID, Name, UnitPrice
FROM Products
WHERE UnitPrice <
  ( SELECT AVG( UnitPrice ) FROM Products )
ORDER BY UnitPrice DESC;


ID Name             UnitPrice
401 Baseball Cap 10.00
300 Tee Shirt 9.00
400 Baseball Cap 9.00
500 Visor            7.00
501 Visor            7.00

Example 3: Simple multiple-row subquery using IN

Suppose you want to identify items that are low in stock, while also identifying orders for those items. You could execute a SELECT statement containing a subquery in the WHERE clause, similar to the following:

SELECT *
FROM SalesOrderItems
WHERE ProductID IN
   (  SELECT ID
       FROM Products
       WHERE Quantity < 20 )
ORDER BY ShipDate DESC;


In this example, the subquery makes a list of all values in the ID column in the Products table, satisfying the WHERE clause search condition. The subquery then returns a set of rows, but only a single column. The IN keyword treats each value as a member of a set and tests whether each row in the main query is a member of the set.

Example 4: Multiple-row subqueries comparing use of IN, ANY, and ALL

Two tables in the SQL Anywhere sample database contain financial results data. The FinancialCodes table is a table holding the different codes for financial data and their meaning. To list the revenue items from the FinancialData table, execute the following query:

SELECT *
FROM FinancialData
WHERE Code IN
    ( SELECT Code
        FROM FinancialCodes
        WHERE type = 'revenue' );

Year Quarter Code Amount
1999 Q1 r1 1023
1999 Q2 r1 2033
1999 Q3 r1 2998
1999 Q4 r1 3014
2000 Q1 r1 3114
... ... ... ...

The ANY and ALL keywords can be used in a similar manner. For example, the following query returns the same results as the previous query, but uses the ANY keyword:

SELECT *
FROM FinancialData
WHERE FinancialData.Code = ANY
   (  SELECT FinancialCodes.Code
       FROM FinancialCodes
       WHERE type = 'revenue' );


While the =ANY condition is identical to the IN condition, ANY can also be used with inequalities such as < or > to give more flexible use of subqueries.

The ALL keyword is similar to the word ANY. For example, the following query lists financial data that is not revenue:

SELECT *
FROM FinancialData
WHERE FinancialData.Code <> ALL
   (  SELECT FinancialCodes.Code
       FROM FinancialCodes
      WHERE type = 'revenue' );

This is equivalent to the following command using NOT IN:

SELECT *
FROM FinancialData
WHERE FinancialData.Code NOT IN
   (  SELECT FinancialCodes.Code
      FROM FinancialCodes
      WHERE type = 'revenue' );


Multiple Column Subqueries:

In the single row sub queries and multiple row sub queries only one column is returned by the inner SELECT statement and this is used to evaluate the expression in the parent SELECT statement.

If you want to compare two or more columns , you must write a compund WHERE clause using logical operators.

Using Multiple-Column subqueries, you can combine duplicate WHERE conditions into a single WHERE clause.

Syntax:

SELECT  column, column, ...

FROM table

WHERE (column,column,....)  IN   --------------------------------- Main Query
                                     
                                     (SELECT column, column ,......
                                      FROM table
                                      WHERE condition );


************************************************************************
Main Query

....WHERE (manager_id, department_id) IN
     
                              Subquery

                      100                   90

                      102                   60

                      124                   40


Each row of the main query is compared to values from a multiple-row and multiple-column subquery.

In the above, the value of manager_id and department_id  from the main query are being compared with the manager_id and department_id  values retrieved by the subquery. Since the number of columns that are being compared are more than one , the example qualifies as a multiple coulmn subquery.


Column Comparisons:

Column comparisons in a multiple column subquery can be :

Pairwise Comparisons
Non-Pairwise Comparisions


Pairwise Comparisons: 

Ex:

/* Display the details of employees who are managed by the same manager and work in the same department as the employees with EMPLOYEE_ID 178 and 174*/

SELECT employee_id, manager_id, department_id
FROM employees
WHERE (manager_id,department_id) IN
                                                     
                                  (SELECT manager_id,department_id
                                   FROM employees
                                   WHERE employee_id in (178,174))

AND employee_id NOT IN (178,174);

The example above is a multiple column subquery because the subquery returns more than one column. It compares the values in the manager_id column and department_id column of each row in the EMPLOYEES  table with the values in the manager_id column and the department_id column for the employees with the employee_id 178 or 174.

First, the subquery to retrieve the manager_id and department_id values for the employees with the employee_id 178 or 174 is executed. These values are compared with the with the manager_id column and department_id column of each row in the EMPLOYEES table. If the value match, the row is displayed.  In the output, the records of the employees with the EMPLOYEE_ID 178 or 174 will not be displayed .

EMPLOYEE_ID MANAGER_ID DEPARTMENT_ID
----------- ---------- -------------
        175        149                              80
        176        149                             80
        177        149                             80
        179        149                            80



Non-Pairwise Comparisons:


/* Display the details of employees who are managed by the same manager and work in the same department as the employees with EMPLOYEE_ID 178 and 174*/

SELECT employee_id, manager_id, department_id
FROM employees
WHERE manager_id IN
                (SELECT manager_id
                 FROM employees
                 WHERE employee_id in (178,174))

AND department_id IN
                 (SELECT department_id
                 FROM employees
                 WHERE employee_id in (178,174))

AND employee_id NOT IN (178,174);


The above example shows a non pairwise comparison of the columns. It displays the employee_id, manager_id and department_id of any employee whose manager_id matches any othe manager IDs of employees whose employee IDs are either 178 or 174 and department_id match any of the department IDs of employees whose employee IDs are either 178 or 174.

First, the subquery to retrieve the manager_id values of the employees with the employee_id 178 or 174 is executed. Similarly, the second subquery to retrieve the department_id  values for the employees with the employee_id 178 or 174 is executed. The retrieved values values of manager_id and department_id columns are compared with the manager_id and department_id column for each row in the EMPLOYEES table . If the manager_id column of the row in the EMPLOYEES  table matches with any of the values of  the manager_id retrieved by the inner subquery  and if the department_id column of the row in the EMPLOYEES table matches with any of the values of the department_id retrieved by the second subquery , the record is displayed.

EMPLOYEE_ID MANAGER_ID DEPARTMENT_ID
----------- ---------- -------------
        179        149                            80
        177        149                             80
        176        149                            80
        175        149                            80


Both the output are same but in different order.

Pairwise :
/*Display the order_id, product_id and quantity of any item in which the product_id and quantity match both the product_id and quantity of an item in order_id 2366*/

Table available on OE Schema in oracle starter database like scott or hr:


SELECT order_id , product_id ,quantity
FROM           order_items
WHERE        (product_id , quantity)    IN
                                        (SELECT product_id,   quantity
                                         FROM       order_items
                                         WHERE     order_id =   2366)
AND  order_id =   2366;





  ORDER_ID PRODUCT_ID   QUANTITY
---------- ---------- ----------
      2366       2359          8
      2366       2373          7
      2366       2382         10
      2366       2394         11
      2366       2395         12
      2366       2400         16
      2366       2406         20
      2366       2409         22
      2366       2415         24
      2366       2419         24

10 rows selected.






Non-Pairwise:

SELECT order_id , product_id ,quantity
FROM      order_items
WHERE   product_id    IN   (SELECT product_id
                                         FROM       order_items
                                         WHERE     order_id =   2366)
                                       
AND  quantity IN    (SELECT quantity
                             FROM       order_items
                            WHERE     order_id =   2366)
                                     
AND  order_id =   2366;



 ORDER_ID PRODUCT_ID   QUANTITY
---------- ---------- ----------
      2366       2359          8
      2366       2373          7
      2366       2382         10
      2366       2394         11
      2366       2395         12
      2366       2400         16
      2366       2406         20
      2366       2409         22
      2366       2419         24
      2366       2415         24

10 rows selected.



/*Write a query to display the name, department number, and salary of any employee whose department number and salary match the department number and salary of any employee who earns a commission*/

SELECT first_name , department_id, salary
FROM employees
WHERE (department_id, salary)  IN  (SELECT department_id, salary
                           FROM employees
                           WHERE commission_pct  IS NOT NULL ) ;


/*Display the name, department name, and salary of any employee whose salary and commission match the salary and commission of any employee located in location id 1700.*/

SELECT e.first_name, d.department_name, e.salary
    FROM employees e, departments d
    WHERE e.department_id = d.department_id
    AND
    d.location_id  = 1700 ;



FIRST_NAME           DEPARTMENT_NAME                    SALARY
-------------------- ------------------------------ ----------
Jennifer             Administration                       4400
Shelley              Accounting                          12000
William              Accounting                           8300
Steven               Executive                           24000
Neena                Executive                           17000
Lex                  Executive                           17000
Nancy                Finance                             12000
Daniel               Finance                              9000
John                 Finance                              8200
Ismael               Finance                              7700
Jose Manuel          Finance                              7800
Luis                 Finance                              6900
Den                  Purchasing                          11000
Alexander            Purchasing                           3100
Shelli               Purchasing                           2900
Sigal                Purchasing                           2800
Guy                  Purchasing                           2600
Karen                Purchasing                           2500

18 rows selected.





/*Create a query to display the name, hiredate, and salary of any employee who have both the same salary and commission as Scott.*/

SELECT ename, hiredate, sal
    FROM emp
    WHERE
    ename <> 'SCOTT'
AND
(sal, NVL(comm,0) )  IN
                    ( SELECT sal, NVL(comm,0)
                      FROM emp
                      WHERE ename = 'SCOTT');


/*Create a query to display the employees that earn a salary that is higher than the salary of all of the clerks. Sort the results on salary from highest to lowest */

SELECT ename, job, sal
    FROM emp
    WHERE sal  >  ALL
                                       ( SELECT sal
                                          FROM emp
                                          WHERE job = 'CLERK')
ORDER BY SAL DESC;


In pair wise comparison we write like this:

"where (MGR_ID, DEPT_ID) IN (SUBQUERY)"

IN non pair wise comparison we write like this:

"where (MGR_ID) IN (SUBQUERY)
and (DEPT_ID) IN (SUBQUERY)"


In first one we are checking two columns simultaneously within a single query, whereas in the second one we are checking each column individually with two queries.

So the output will also differes, check it out by practical implementation.

Wednesday, January 22, 2014

Advantages of Procedure / Sub program

Block Structure :A subprogram is based on standard pl/sql structure that contains a declarative section, an executable section   and an optional exception handling section.
Modularity:   Mopdularisation is the process of breaking up large blocks of code into smaller groups of code called modules.          
               It is easier to maintain and debug code of smaller modules than a single large program.

Extensibility : The modulues can be easily extended for customization by incorporating more functionality,

                if required without affecting the remaining modules of the program.

Reusability :     After the code is modularized, the modules can be reused by the same program or shared by other programs.

Maintainibility : Subprograms provide easy maintainance because the code is located in one place and hence any modifications  required to the subprogram can be performed in this single location.

Improved data security and integrity and code clarity: subprograms provide improved data integrity and security . The data objects are accessed through the subprogram and a user can invoke the subprogram only if appropriate access priviledge is given to user.

Thursday, January 16, 2014

Stored Procedure in 10g

A procedure is a group of PL/SQL statements that you can call by name. Stored procedure is a named PL/SQL block which performs one or more specific task.

Stored procedures offer advantages in the areas of development, integrity, security, performance, and memory allocation.

A procedure has a header and a body. The header consists of the name of the procedure and the parameters or variables passed to the procedure. The body consists or declaration section, execution section and exception section similar to a general PL/SQL Block.

A procedure is similar to an anonymous PL/SQL Block but it is named for repeated usage.

We can pass parameters to procedures in three ways.
1) IN-parameters
2) OUT-parameters
3) IN OUT-parameters

A procedure may or may not return any value.


General Syntax to create a procedure is:

CREATE [OR REPLACE] PROCEDURE proc_name [list of parameters]
IS  
   Declaration section
BEGIN  
   Execution section
EXCEPTION  
  Exception section
END;


IS - marks the beginning of the body of the procedure and is similar to DECLARE in anonymous PL/SQL Blocks. The code between IS and BEGIN forms the Declaration section.

The syntax within the brackets [ ] indicate they are optional. By using CREATE OR REPLACE together the procedure is created if no other procedure with the same name exists or the existing procedure is replaced with the current code.

argument
Specify the name of an argument to the procedure. If the procedure does not accept arguments, you can omit the parentheses following the procedure name.

IN
Specify IN to indicate that you must supply a value for the argument when calling the procedure.


OUT
Specify OUT to indicate that the procedure passes a value for this argument back to its calling environment after execution.


IN OUT
Specify IN OUT to indicate that you must supply a value for the argument when calling the procedure and that the procedure passes a value back to its calling environment after execution.

If you omit IN, OUT, and IN OUT, then the argument defaults to IN.

NOCOPY
Specify NOCOPY to instruct the database to pass this argument as fast as possible. This clause can significantly enhance performance when passing a large value like a record, an index-by table, or a varray to an OUT or IN OUT parameter. IN parameter values are always passed NOCOPY.

When you specify NOCOPY, assignments made to a package variable may show immediately in this parameter, or assignments made to this parameter may show immediately in a package variable, if the package variable is passed as the actual assignment corresponding to this parameter.

Similarly, changes made either to this parameter or to another parameter may be visible immediately through both names if the same variable is passed to both.

If the procedure is exited with an unhandled exception, then any assignment made to this parameter may be visible in the caller's variable.

These effects may or may not occur on any particular call. You should use NOCOPY only when these effects would not matter.

datatype
Specify the datatype of the argument. An argument can have any datatype supported by PL/SQL.

Datatypes cannot specify length, precision, or scale. For example, VARCHAR2(10) is not valid, but VARCHAR2 is valid. Oracle Database derives the length, precision, and scale of an argument from the environment from which the procedure is called.




How to execute a Stored Procedure?
There are two ways to execute a procedure.

1) From the SQL prompt.

 EXECUTE [or EXEC] procedure_name;
2) Within another procedure – simply use the procedure name.

  procedure_name;
NOTE: In the examples given above, we are using backward slash ‘/’ at the end of the program. This indicates the oracle engine that the PL/SQL program has ended and it can begin processing the statements.


Stored Procedure without any Parameter

CREATE TABLE LOG_TABLE

( USER_ID VARCHAR2(10 ) , LOG_DATE DATE  )

Table Created.

CREATE OR REPLACE PROCEDURE SCOTT.log_execution
IS
BEGIN
   INSERT INTO log_table (user_id, log_date)
        VALUES (USER, SYSDATE);
 
  END log_execution;
 /

IN  PARAMETER EXAMPLE
1st example:

CREATE OR REPLACE PROCEDURE HR.remove_emp (employee_id NUMBER)
AS
   tot_emps   NUMBER;
BEGIN
   DELETE FROM employees1
         WHERE employees1.employee_id = remove_emp.employee_id;

   tot_emps := tot_emps - 1;
END;
/

SHOW ERRORS;


To execute :

SET SERVEROUTPUT ON

DECLARE
  EMPLOYEE_ID NUMBER;

BEGIN
  EMPLOYEE_ID := 205;
REMOVE_EMP ( EMPLOYEE_ID );
  --COMMIT;
Dbms_output.put_line (EMPLOYEE_ID || ' has been deleted');
END;



2nd Example:

The below example creates a procedure ‘employee_details’ which gives the details of the employee.

CREATE OR REPLACE PROCEDURE employee_details
 IS
 CURSOR emp_cur IS
SELECT first_name, last_name, salary FROM employees1;
--emp_rec emp_cur%rowtype;
BEGIN
FOR emp_rec in emp_cur
LOOP
dbms_output.put_line(emp_rec.first_name || ' ' ||emp_rec.last_name || ' ' ||emp_rec.salary);
END LOOP;
END;

OUT PARAMETER EXAMPLE:

Definition:

In Oracle PL/SQL, the term OUT refers to one of the parameter passing modes. Unlike the IN parameter mode, it must be specified in the parameter declaration. An OUT parameter is a 'pass by value' method. The parameter must be assigned with a value within the subprogram body. This value is then passed to the host environment, from where the subprogram has been called.

Notes
A default value cannot be assigned to the OUT parameter.
The NOCOPY hint can be used in the parameter declaration to convert the parameter calling method from 'Call by Value' method to the 'Call by reference' method.

Example Syntax:

PARAMETER [IN | OUT | IN OUT] [DATA TYPE] [DEFAULT],

Example Usage:

The procedure P_GET_SAL fetches the salary of an employee from EMPLOYEE table for the given employee id and returns it to the calling environment.

CREATE OR REPLACE PROCEDURE P_GET_SAL (P_EMPID NUMBER, P_SAL OUT NUMBER)
IS
BEGIN
SELECT SALARY INTO P_SAL
FROM EMPLOYEES1
WHERE EMPLOYEE_ID=P_EMPID;
END;
/

SQL> VAR G_SAL NUMBER;
SQL> EXEC P_GET_SAL(100,:G_SAL);

PL/SQL procedure successfully completed.

SQL> PRINT G_SAL;

     G_SAL
----------
     26400

OR:

DECLARE
  P_EMPID NUMBER;
  P_SAL NUMBER;

BEGIN
  P_EMPID := 100;
  P_GET_SAL (P_EMPID,P_SAL );
 DBMS_OUTPUT.PUT_LINE(P_EMPID ||' draws salary' ||  P_SAL);
 END;

100 draws salary 26400
PL/SQL procedure successfully completed.


IN OUT PARAMETER EXAMPLE

CREATE OR REPLACE procedure format_phone
(p_phone_no IN OUT varchar2)
is
begin
p_phone_no :='(' || SUBSTR(p_phone_no,1,3) ||
                       '(' || SUBSTR(p_phone_no,4,3) ||      
                       '-' || SUBSTR(p_phone_no,7 );
END format_phone;
/
Procedure created.

SQL> var g_phone_no varchar2(15)
SQL> begin
  2  :g_phone_no :='9880002441';
  3  end;
  4  /

PL/SQL procedure successfully completed.

SQL> print g_phone_no

G_PHONE_NO
--------------------------------
9880002441

SQL> exec format_phone(:g_phone_no);

PL/SQL procedure successfully completed.

SQL> print g_phone_no

G_PHONE_NO
--------------------------------
(988)000-2441


OR 

SET SERVEROUTPUT ON

DECLARE
P_PHONE_NO VARCHAR2(32767);

BEGIN
P_PHONE_NO := '9880002441';

FORMAT_PHONE ( P_PHONE_NO );

DBMS_OUTPUT.PUT_LINE(P_PHONE_NO);

END;

Output:
(988)000-2441
PL/SQL procedure successfully completed.
************************************************************


A subprogram is a program unit/module that performs a particular task.
These subprograms are combined to form larger programs. This is basically called the 'Modular design'.

A subprogram can be invoked by another subprogram or program which is called the calling program.

A subprogram can be created:

At schema level

Inside a package

Inside a PL/SQL block

A schema level subprogram is a standalone subprogram. It is created with the CREATE PROCEDURE or CREATE FUNCTION statement.

It is stored in the database and can be deleted with the DROP PROCEDURE or DROP FUNCTION statement.

A subprogram created inside a package is a packaged subprogram.

It is stored in the database and can be deleted only when the package is deleted with the DROP PACKAGE statement.


PL/SQL subprograms are named PL/SQL blocks that can be invoked with a set of parameters. PL/SQL provides two kinds of subprograms:

Functions: these subprograms return a single value, mainly used to compute and return a value.

Procedures: these subprograms do not return a value directly, mainly used to perform an action.

Cheers:
Rajani