Job Search

Sunday, October 25, 2015

Collection Comparison


Composite Data Type

1) Collection : 
In a collection, the internal components always have the same data type, and are called elements. We can access each element of a collection variable by its unique index, with this syntax: variable_name(index). To create a collection variable, we either define a collection type and then create a variable of that type or use %TYPE.

2) Record : 
In a record, the internal components can have different data types, and are called fields. We can access each field of a record variable by its name, with this syntax: variable_name.field_name. To create a record variable, we either define a RECORD type and then create a variable of that type or use %ROWTYPE or %TYPE.

We can create a collection of records, and a record that contains collections.

Varray
NestedTable
Associative Arrays(Index by tables)
1.Fixed Number of elements
2.Subscript will be sequence no

3.Uninitialized Status : Null - Initialization required  normally
4.Extend required
5. Dense or Sparse : Always dense
6. Can be stored in DB as a column
7. Number of Elements:  Specified
8. Where Defined : In PL/SQL block or package or at schema level.
9. Can Be ADT Attribute Data TypeOnly if defined at schema level
1.Any number of elements
2.Subscript will be sequence no

3.Null,  Initialization required


4.Extend required
5. Starts dense, can become sparse
6.Can be stored in DB as a column
7. Unspecified

8. In PL/SQL block or package or at schema level.

9. Only if defined at schema level.
1.Any number of elements
2.Substring can be arbitrary number or string
3.Empty, Initialization Not required

4.Extend not required
5. Either

6.Cannot be stored in DB as a column
7. Unspecified

8. In PL/SQL block or package.


9. No


Translating Non-PL/SQL Composite Types to PL/SQL Composite Types
If we have code or business logic that uses another language, we can usually translate the array and set types of that language directly to PL/SQL collection types. For example:

Non-PL/SQL Composite Type
Equivalent PL/SQL Composite Type
Hash table
Associative array
Unordered table
Associative array
Set
Nested table
Bag
Nested table
Array
Varray


I hope you all have enjoyed reading this article. Comments are welcome....


Related Posts:


ORACLE/PLSQL: NAMED SYSTEM EXCEPTIONS

WHAT IS A NAMED SYSTEM EXCEPTION IN ORACLE?
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 Name
Oracle Error
Explanation
DUP_VAL_ON_INDEX
ORA-00001
You tried to execute an INSERT or UPDATE statement that has created a duplicate value in a field restricted by a unique index.
TIMEOUT_ON_RESOURCE
ORA-00051
You were waiting for a resource and you timed out.
TRANSACTION_BACKED_OUT
ORA-00061
The remote portion of a transaction has rolled back.
INVALID_CURSOR
ORA-01001
You 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_ON
ORA-01012
You tried to execute a call to Oracle before logging in.
LOGIN_DENIED
ORA-01017
You tried to log into Oracle with an invalid username/password combination.
NO_DATA_FOUND
ORA-01403
You 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_ROWS
ORA-01422
You tried to execute a SELECT INTO statement and more than one row was returned.
ZERO_DIVIDE
ORA-01476
You tried to divide a number by zero.
INVALID_NUMBER
ORA-01722
You tried to execute a SQL statement that tried to convert a string to a number, but it was unsuccessful.
STORAGE_ERROR
ORA-06500
You ran out of memory or memory was corrupted.
PROGRAM_ERROR
ORA-06501
This is a generic "Contact Oracle support" message because an internal problem was encountered.
VALUE_ERROR
ORA-06502
You tried to perform an operation and there was a error on a conversion, truncation, or invalid constraining of numeric or character data.
CURSOR_ALREADY_OPEN
ORA-06511
You tried to open a cursor that is already open.

SYNTAX
We will take a look at the syntax for Named System Exceptions in both procedures and functions.

Syntax for Procedures
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];

Syntax for Functions
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];

EXAMPLE
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.



I hope you all have enjoyed reading this article. Comments are welcome....

Alter database VS Alter system

Alter system
alter database commands cannot be audited; where as alter system can
alter database needs bouncing(reboot) database but alter system doesn't 

An "alter system" command is (mostly) only possible in status OPEN. The only exception from this I recall presently is 

"alter system set param=value" to modify initialization parameters. That is already possible in NOMOUNT status.

ALTER SYSTEM is an Instance Level command. Generally this applies for running processes, parameters etc. (however "ALTER SYSTEM DUMP" seems to be an exception).

Use the ALTER SYSTEM statement to dynamically alter your Oracle instance. The settings stay in effect as long as the database is mounted. HOWEVER, if you wish to make the changes permanent then the SPFile must be amended.

Alter database
but ALTER DATABASE BACKUP CONTROL FILE TO TRACE; doesn't require bouncing.

"alter database" on the other hand is already possible in status MOUNT, where tablespaces including the system tablespace that contains audit information is not accessible. That is why "alter database" cannot be audited probably.

As a rule of thumb: You can do "alter database" in MOUNT already, but "alter system" only in status OPEN.

ALTER DATABASE is a Database Level command. Generally, this applies to the physical structure of the database.

Think of an RAC environment. Most ALTER SYSTEM commands (ALTER SYSTEM DUMP is one exception) are local to the instance (although SET can set for multiple instances). The ALTER DATABASE commands are for the whole database.


Use the ALTER DATABASE statement to modify, maintain, or recover an existing database.



I hope you all have enjoyed reading this article. Comments are welcome....

Logical vs Physical Standby database

Standby databases, in a nutshell, acts as a failover for our mission critical production databases. When production database crashes, applications can quickly switchover to the stand by databases.
Oracle provides two types of standby databases:

1. Physical Standby Database
Standby database is called “physical” if the physical structure of stand by exactly matches with stand by structure. Archived redo log transferred from primary database will be directly applied to the stand by database.

2. Logical Standby Database

Stand by database is called “logical”, the physical structure of both 
databases do not match and from the archived redo log we create SQL statements then these statements will be applied to stand by database.



Question:  What is the difference between logical standby and physical standby in Oracle Data Guard?
Answer:  In  Oracle Data Guard you, Oracle transfers data from the main database to a standby database, and in case of failures, Oracle will switch over to the standby database.  We have two ways to create a standby database, logical standby and physical standby.

Physical standby differs from logical standby:
  • Physical standby schema matches exactly the source database.
  • Archived redo logs and FTP'ed directly to the standby database which is always running in "recover" mode.  Upon arrival, the archived redo logs are applied directly to the standby database.

Logical standby is different from physical standby:
  • Logical standby database does not have to match the schema structure of the source database.
  • Logical standby uses LogMiner techniques to transform the archived redo logs into native DML statements (insert, update, delete).  This DML is transported and applied to the standby database. 
  • Logical standby tables can be open for SQL queries (read only), and all other standby tables can be open for updates. 
  • Logical standby database can have additional materialized views and indexes added for faster performance.

Installing Physical standbys offers these benefits:
  • An identical physical copy of the primary database
  • Disaster recovery and high availability
  • High Data protection
  • Reduction in primary database workload
  • Performance Faster

Installing Logical standbys offer:
  • Simultaneous use for reporting, summations and queries
  • Efficient use of standby hardware resources
  • Reduction in primary database workload
  • Some limitations on the use of certain datatypes


I hope you all have enjoyed reading this article. Comments are welcome....

Trigger with mutating problem

Trigger with mutating problem

If you have created a couple of triggers in Oracle then you must have come across a problem called "Table is mutating; trigger may not read or modify it".

Mutating problem occurs if you try to access a table from a trigger which is fired by a command that modified the table. For example, if you are updating EMPLOYEES table and try to access EMPLOYEES table using SELECT statement in before or after row-level trigger then Oracle complains that the table is being modified so it cannot be read from the trigger.

Let us understand the problem with an example. Assume we have to ensure the salary of manager is always more or equal to the salaries of the employees whom he/she manages. In HR account of Oracle, we have EMPLOYEES table containing employee_id, salary and manager_id columns (apart from other not related to this example). We have to ensure whenever we are inserting or updating a row in EMPLOYEES table the salary of the employee is less than or equal to the salary of the manager, if manager_id is not null.

Let us try to create a trigger to accomplish the task as follows:
create or replace trigger trg_check_salary
before update
on employees
for each row
declare
   v_salary employees.salary%type;
begin
   if  :new.manager_id is not null then
       /* get the salary of the manager */
       select  salary into v_salary
       from employees
       where employee_id = :new.manager_id;
  
       if  v_salary < :new.salary then
         raise_application_error(20100,'Employee salary is more than manager');
       end if;
   end if;
end;
/

Now issue the following command to update EMPLOYEES table as follows and see the message issued by Oracle.

SQL> update employees set salary = 10000 where employee_id = 110;
update employees set salary = 10000 where employee_id = 110
       *
ERROR at line 1:
ORA-04091: table HR.EMPLOYEES is mutating, trigger/function may not see it
ORA-06512: at "HR.TRG_CHECK_SALARY", line 6
ORA-04088: error during execution of trigger 'HR.TRG_CHECK_SALARY'

As we understood, the problem is, we are trying to access the table (EMPLOYEES) that is being modified by the UPDATE command.
Before we apply the remedy, let us drop the above trigger to ensure it is not fired when we update or insert rows into EMPLOYEES table.
 drop trigger trg_check_salary;

Remedy for mutating problem

The remedy for mutating problem requires some process. We need to create a package to store the data being modified and write three triggers. The following process summaries the procedure.
  1. We need to create a package that stores the data in PL/SQL tables for rows that are being modified by the command
  2. Create a BEFORE STATEMENT trigger to initialize variables in the package
  3. Create an AFTER ROW trigger to insert data from the row being modified to PL/SQL tables
  4. Create an AFTER STATEMENT trigger to validate the data that is inserted into PL/SQL tables and raise error if any invalid data is found
Oracle allows STATEMENT level trigger to access the data from the table as by that time the data is already modified in the table. So it is possible to compare the data that is being modified with the data in the table during this trigger.

Creating a package

The following is the package that stores data from the rows that are being modified.
 
CREATE OR REPLACE PACKAGE trg_check_pkg IS
   PROCEDURE init_data;
   PROCEDURE insert_data(mgrid IN employees.manager_id%type, sal IN employees.salary%type);
   PROCEDURE check_data;
END;
 
CREATE OR REPLACE PACKAGE BODY trg_check_pkg IS
 
 TYPE mgrid_table IS TABLE OF number(5) index by binary_integer;  /*  table type */
 mgrids mgrid_table;   /* table to store manager ids */
 
 TYPE salary_table IS TABLE OF number(5) INDEX BY BINARY_INTEGER; /* table type */
 salaries salary_table;         /* table to store salaries  */
    
 pos binary_integer;  /* table index */
 
 PROCEDURE init_data IS
 BEGIN
   pos := 0;
 END;
 
 PROCEDURE insert_data(mgrid IN employees.manager_id%type, sal  IN employees.salary%type) IS
 BEGIN
   pos := pos + 1;
   salaries(pos) := sal;
   mgrids (pos) := mgrid;
 END;
 
 PROCEDURE check_data IS
   dummy number;
 BEGIN
  WHILE pos > 0 
  LOOP
     BEGIN
       /* check whether salary of the manager is more than employee's salary */
       SELECT 1 INTO dummy FROM employees
       WHERE  salary >= salaries(pos) and  mgrids(pos) = employee_id;
 
      EXCEPTION
       WHEN NO_DATA_FOUND THEN
          RAISE_APPLICATION_ERROR(-20000,'Manager salary must be more than or equal to employee salary');
      END;
      pos := pos - 1;
 END LOOP;
END;
 
END;
 

Create required trigger

Now, in order to store data that is being update into variables of package and check the data in the tables subsequently, create the following triggers.
 
First of three triggers is BEFORE STATEMENT trigger to initialize package data.
CREATE OR REPLACE TRIGGER trg_check_salary_bs
BEFORE insert or update OF salary,manager_id   /* statement-level trigger */
ON employees  
BEGIN
     trg_check_pkg.init_data;
END;
/

Second trigger is AFTER ROW trigger to store data that is being modified by the command.
CREATE OR REPLACE TRIGGER trg_check_salary_ar
After INSERT OR UPDATE OF salary, manager_id
ON employees
FOR EACH ROW  /* row-level trigger */
BEGIN
   IF :new.manager_id IS NOT NULL THEN
       trg_check_pkg.insert_data( :new.manager_id, :new.salary);
   END IF;
END;
/

Third trigger is AFTER STATEMENT trigger that is used to check whether the data that was modified is valid.
CREATE OR REPLACE TRIGGER  trg_check_salary_as
After INSERT OR UPDATE OF salary,manager_id  /* statement-level trigger */
ON employees
BEGIN
     trg_check_pkg.check_data;
END;
/

Now try updating the salary of an employee(110) to  13000, which is more than the salary of the manager (12000). You get the following output.
SQL> update employees set salary = 13000 where employee_id = 110;
update employees set salary = 13000 where employee_id = 110
         *
ERROR at line 1:
ORA-20000: Manager salary must be more than or equal to employee salary
ORA-06512: at "HR.TRG_CHECK_PKG", line 32
ORA-06512: at "HR.TRG_CHECK_SALARY_AS", line 2
ORA-04088: error during execution of trigger 'HR.TRG_CHECK_SALARY_AS'


I hope you all have enjoyed reading this article. Comments are welcome....