29 December, 2015

Oracle | Forward Declaration

Forward Declaration of Elements

There can be cases where the elements have to called in program code before they are coded in the program. But Oracle is very fuzzy about the declaration of program units. It will throw you an error because if the element is not defined, Oracle treats it as wrong semantic.

To resolve cases, where mutual recursion is present, meaning a program element calls another program unit which in turn calls the first program unit, this issue can be resolved using forward declarations.
In forward declaration, the actual element is not coded, but rather a declaration of it is made before calling it in another program unit. This ensures that Oracle knows the code for the declared program unit is somewhere later present in the code.

There are few guidelines for forward declaration as well:
1. A variable or a cursor cannot be forward declared.
2. Only modules like a procedure or a function can be forward declared.
3. The definition of the forward declared element should be present in the declaration part of the same PL/SQL block where the element is declared.

12 October, 2015

Oracle B Tree and Bitmap Index | Internal working

Oracle B-tree indexes
B-tree indexes are ordered lists of values divided into ranges with a key associated with a row or range of rows, thereby providing excellent retrieval performance for queries such as exact match and range searches.
This type of index contains 3 types of blocks - the root block, one or more branch blocks and one or more leaf blocks. The root block holds keys and pointers to the branch blocks which in turn hold pointers to the leaf blocks which contain the key (data) values that have been indexed and the rowids of the rows in the Oracle database table associated with each key value.
Branch blocks hold the minimum key prefix needed to be able to choose the required branch and a pointer to the child block containing the key. The number of keys and pointers is limited by the block size. Index leaf blocks are double linked - each block contains pointers to the next and previous leaf blocks.
B-tree indexes are always balanced because the height of the index (the number of levels in the index) is the same throughout the index. In other words, the number of blocks that have to be read to find the rowid associated with any particular index value is not dependent on that value. For example if you had an index on the last_name column of the employee table in the sample Oracle database the number or blocks that would need to be read to find the rowid associated with "Ernst" would be the same as for "King".
The height of a b-tree index is the number of blocks required to go from the root block to a leaf block. For an index with one level of branch blocks the height is 3 (1 root block + 1 branch block + 1 leaf block).

Oracle bitmap indexes
Bitmap indexes are completely different to b-tree indexes. Whereas b-tree indexes are ideal for storing highly selective/unique values (low cardinality), bitmap indexes are designed to store values of low cardinality where the same value can be found in a large proportion of the table. An example of this might be the part number column in the sales table, or gender in the employee table.
With this type of index, each distinct value of the column is associated with a set of bits representing the rows in the table (one bit for each row in the table). Each bit has a value of 0 or 1. If the bit is set then then the row associated with that bit has that value in the column.
Bitmap indexes are expensive to maintain as the whole bitmap has to be rebuilt after any DML operation (insert/update/delete) on the table.

Oracle Triggers

Triggers are an important part of Oracle. And I know only them to be the objects which are event-driven. 

That means they cannot be executed by the plsql code and rather they depend upon some event to occur. That event can be any DML operation a table or a DDL level operation on the database.

Definition - Triggers are procedures which are event-driven.

Timing points(Events which trigger triggers) - BEFORE | AFTER
ROW LEVEL | STATEMENT LEVEL

So if there are multiple triggers defined on a table, from the above, we can define the order of the trigger execution. 
Before statement >>> Before each row >>> DML >>> After each row >>> After statement.

FOLLOWS - If there are multiple triggers defined at the same timing point for a table, then the order in which they will be executed, is not defined; and is decided by Oracle server.
But, in Oracle 11g, there a new keyword FOOLOWS created. through this keyword, we can define which trigger is to follow which trigger.

COMPOUND TRIGGER - We define a trigger for a particular event, like before the row of after the statement, but Oracle 11g, brought this new way to define a single trigger which can define code blocks to run at different events. This is compound trigger.
Compound trigger have many benefits over normal triggers. And they have many rules as well.

|||||||||||||||||||||||||||||||||||||||||||||||

BEFORE and AFTER triggers are available for tables; INSTEAD OF triggers is available for views only.

Up to 3 triggering events can be connected and specified using the keyword OR. INSERT OR UPDATE OR DELETE

UPDATE can be optionally followed by OF; specifying the columns whose update will run the trigger.

the special columns NEW and OLD are only available if the trigger is row-level.
CREATE TRIGGER trig_tt
AFTER INSERT
REFERENCING NEW AS newrec
OR UPDATE
ON tab_tt
FOR EACH ROW
WHEN(newrec.a1 <= 100)
BEGIN
   INSERT INTO tem VALUES (:newrec.b1, :newrec.c1);
END trig_tt;

As you can see from the above code, the special variable NEW is used without colon(:) in the WHEN clause.

|||||||||||||||||||||||||||||||||||||||||||||||
To check the errors in a trigger, use:
SHOW ERRORS TRIGGER trigger_name
|||||||||||||||||||||||||||||||||||||||||||||||
list all user created triggers -
SELECT trigger_name FROM USER_TRIGGERS;
|||||||||||||||||||||||||||||||||||||||||||||||
 MUTATING TABLE ERRORS
when the trigger queries or tries to modify a table which is mutating already; Oracle will report a mutating trigger error.

To Aviod mutating table errors:
> A row-level trigger must not query or modify a mutating table. NEW and OLD values are still accessible.
> A statement-level trigger must not query or modify a mutating table of the trigger is fired as the result of a CASCADE DELETE.

|||||||||||||||||||||||||||||||||||||||||||||||
FUN FACTS
Oracle puts a size limit of 32 kb to triggers. This size is big enough to write over 4000 characters. But if you still need more code, then the best idea is to create named procedures and call them in the code of triggers.

Oracle fires all triggers of a type together and then triggers of another type.
We can't control which type will be fired when.

25 September, 2015

FOR UPDATE , NO WAIT | Oracle

When a SELECT statement picks the data from any table, the rows are not locked. And while the user performs some operation on the data, there is a chance that some other user may delete or modify the data. 

To resolve this, we can use the FOR UPDATE clause, which locks the rows picked up in the select statement and releases the locks only after the code block is exited. Ex- 

CURSOR cursor_name
IS
   select_statement

   FOR UPDATE [OF column_list] [NOWAIT]

This cursors select statement has put a lock on the selected rows and will be released only after the cursor is closed.

The NOWAIT clause is optional and it means that the control will not wait for the resources to be available. the

Mutating Trigger | Oracle

Found this small reference to the mutating trigger error.

The most likely cause of a mutating table error is the misuse of triggers. Here is a typical example:
  1. you insert a row in table A.
  2. A trigger on table A (for each row) executes a query on table A, for example to compute a summary column.
  3. Oracle throws an ORA-04091: table A is mutating, trigger/function may not see it
This is an expected and normal behaviour, Oracle wants to protect you from yourself since Oracle guarantees:
  • (i) that each statement is atomic (i.e will either fail or succeed completely)
  • (ii) that each statement sees a consistent view of the data
Most likely when you write this kind of trigger you would expect the query (2) to see the row inserted on (1). This would be in contradiction with both points above since the update is not finished yet (there could be more rows to be inserted).
Oracle could return the result consistent with a point in time just before the beginning of the statement but from most of the examples I have seen that try to implement this logic, people see a multi-row statement as a series of successive steps and expect the statement [2] to see the changes made by the previous steps. Oracle can not return the expected result and therefore throws the error.
If as I suspect the cause of the mutating table error is a trigger, one way to avoid the error is to move the logic out of the trigger into procedures.

Oracle MERGE Statement

It was introduced in Oracle 9i, to insert or update the data in a table conditionally. Its also called upsert.

It is faster as it reduces table scans.

Found this example where data from the hr table is merged with the employees table. Here we have MERGE INTO statement, instead of the usual INSERT INTO. And the table from which the new data is to be picked, is specified using USING keyword.

The next step is to specify the merge condition, based on which the data will be checked. 

When the condition will match, an update will be fired to update the employees table, otherwise if not matched, the data will be inserted into employees table.

MERGE INTO employees e
    USING hr h
    ON (e.id = h.emp_id)
  WHEN MATCHED THEN
    UPDATE SET e.address = h.address
  WHEN NOT MATCHED THEN
    INSERT (id, address)

    VALUES (h.emp_id, h.address);


MERGE statement enhancements in 10g
There are few additions done to make merge statement more flexible.
- Now, we can skip one of the MATCHED or NOT MATCHED blocks.
- a WHERE condition can also be added to the insert/update part.
- a DELETE statement can also be added to the insert/update part but only on the MATCHED block.

REF Cursor | Oracle

Using REF CURSORs (or cursor variable)is one of the most powerful, flexible, and scalable ways to return query results.

Its a datatype whose value is the memory address of a SQL query result. So, basically its a pointer to a result-set. It allows a user to pass the reference of this resultset among all the programs that need access to it.

Like a normal cursor, its data is accessible in the forward only direction. And also a REF CURSOR is read-only and its data cannot be updated.

TYPES
- Strong REF cursor
- Weak REF cursor

While declaring, if the return type of ref cursor is defined, it becomes a strong cursor.

TYPE emp_curs IS REF CURSOR
RETURNING emp%ROWTYPE;

And if the returning block, returns a ref cursor of a different type, then the one defined, it will raise a "ROWTYPE_MISMATCH" exception.

Diff between a cursor and REF cursor
At the basic level, they are both same. But a normal cursor is quite static in its definition, and its query cannot be changed. Whereas a REF cursor can be opened and used as per the requirement.

And a REF cursor can be passed across program blocks, but a normal cursor can't.

----------

A REF cursor is a variable , so it can be passed as parameter across program blocks.

TYPE emp_curs IS REF CURSOR
RETURNING emp%ROWTYPE;

se emp_curs;

Here the se is a variable of ref cursor type and it can be used for emp table records.


oracle-plsql-ref-cursors

For And For all

https://venzi.wordpress.com/2007/09/27/bulk-collect-forall-vs-cursor-for-loop/

FOR is an actual loop which will go through records one by one and do some processing. 

FORALL is NOT an actual loop, it's just a notation for a bulk DML operation. It will NOT go through rows one by one. For example, you can do some row processing in a FOR loop, but you won't be able to do it in FORALL.

24 September, 2015

Context Switching | Oracle

Context Switching – There is pl/sql engine for pl/sql code and sql engine for sql queries. Every time the control is passed between any of these two engines, its called context switching.

Context switching takes time and creates a delay in execution of the code. It’s a necessary requirement for the code, but too much switches will make the code work slow.

Ex- SELECT  emp_id,
       Dept_name(emp_id)
FROM emp
WHERE emp_id = v_id;


The above code is part of a procedure(plsql eng). When the code executes the query, the control is passed to (sql eng). While, executing query, the func dept_name is encountered and control is passed to (plsql eng). This function itself has a sql query to generate the department name and hence control goes to (sql eng) again. This is not a good practise and is not recommended. 

Oracle | DATA DICTIONARY

DATA DICTIONARY

-- set of read only tables, provide info about the database
-- contains - definition of all schema objects (tables, views, indexes, sequences, synonyms, functions, procs, packages, clusters etc.)
>> how much space is allocated to and is used by a schema object
>> integrity constraints
>> default values of the columns
>> names of the users, their privileges and roles
>> who accessed and updated which db object
>> other general db related info

data dictionary is structured in tables and views. It is stored in the SYSTEM tablespace of a database.

It consists of : BASE TABLES - which store all the db related info. user access to these tables is not advised, and only Oracle database should access these tables. Most info stored in these tables is in cryptic form.

USER-ACCESSIBLE VIEWS - summarize the info stored in BASE TABLES into userful informative views. Most of the views are intended for every user, but there are few which are for administrators only.
These views are grouped into 3 classes - 
DBA_ - These views have some additional info for database administrators
ALL_ - accessible to all users, contains objects to which the user has privileges
USER_ - accessible to all users, contains objects owned by the user

The system supplied view DICTIONARY has names and desc of all the data dictionary views.

******
select OBJECT_NAME from USER_OBJECTS
WHERE object_type = 'TABLE' 

This query will give the list of all the user tables in the schema.
******
select *  from ALL_OBJECTS
WHERE object_type = 'TABLE' 

This query will give all the tables , user created as well as Oracle supplied like DUAL.

Oracle PARTITIONS | Oracle

@@@@ PARTITIONS @@@@

It makes manging large tables & indexes management easy. Its done through a new type of storage structure called PARTIOTION.

A partition is an independent object; it may also have its independent storage characteristics.

However, from an application's perspective, there is just only one schema. No change is required for the DML statements.

IOTs can also be partitioned like a normal table.

BENEFITS - Increased availability, increased query performance for data warehouses, decreased contention for a single resource in OLTP systems, easy administration of schema objects(DDL)

Each partition should have the same logical attributes like column names, constraints; but they can have different logical attributes like tablespace to which it belongs.

PARTITION KEY - one or more columns which determine the partition to which a row of data will go. Ex- In a range partition, the date is the parameter on the basis of which we can partiition a table data.

PARTITIONING STRETEGIES - it defines the conditions based on which the data is partitioned. There are 3 available - RANGE, LIST and HASH.
RANGE - most common type, PARTITION BY RANGE(colname)
**database creates interval partitions for data beyond that transition point. Interval partitions extend range partitioning by instructing the database to create partitions of the specified range or interval automatically when data inserted into the table exceeds all of the range partitions. the SALES_2001 partition contains rows with partitioning key time_id values greater than or equal to 01-JAN-2001.
LIST - partitioning key is based on a set of values and based on those values , the data is partitioned. PARTITION colname VALUES (set of values)
HASH - hash algo is applied on the key to select the partition to which the data will be added. Useful for OLTP systems where high update contention is there. Increases availability. 
PARTITION BY HASH(colname)
you cannot specify to which partition what data should go, and oracle distributes the data evenly across all partitions.

PARTITIONED TABLES - 
partitioned table is different from a non-partitioned table. The normal table has its data allocated to table segment where as in case of partitioned tables, the data is allocated to partition segment. Each partition segment has a portion of data allocated to it.

PARTITIONED INDEXES - 
Like a partitioned table, the partitioned index is decomposed into smaller pieces. 
Global(B-Tree index) indexes are partitioned independent of their table where as local partitioned indexes are automatically linked to its table partition.

How to Load Data into Oracle | Fast Load

There are many ways to load data into Oracle -- Each of these processes varies in speed, simplicity, scalability, recoverability and data availability. There is no single best way to load data into Oracle and it varies with all the criterias mentioned above.

>>SQL*Loader
>>>>Data pump import and export
>>>>>>External tables


>>SQL*Loader >> Used when we have to load huge volumes of data into database from external sources, like a csv file.

It is used to load data from a single or multiple files in the same load session. We can also perform various data manipulations/ validations before loading. Selective load of data is also possible.

>>>>External tables >> They allow you to access tables outside the database, as they are actually present in the database. They are quite similar to how we use sql*loader. Its a convenient way to use sql*loader functionality. When an external table is queried, Oracle parses the flat file and provides data to the  user in such a manner as if the data is stored in the database itself.
The user can define the structure of the flat file and then SQL query is used to generate iska kaam.

>>Data pump import and export >> This utility is used to transport oracle objects between different Oracle databases, regardless of the hardware and software.

LISTAGG Aggregate Function | Oracle

LISTAGG Aggregate function @@@@

The function concatenates the results in a single row. Like if you want to check which covers exist for a transaction in the agreement table. Check out the following query :

select policy_no, trans_id, listagg(product_line_id,'-') within group (order by agr_line_seq_no desc) agg_data
from agreement_line
where 1=1 
and policy_no = 12345678  
group by policy_no, trans_id;

The data is grouped on the basis of policy and transaction number. The aggregate function will show the result as a concatenated string:

POLICY_NO TRANS_ID AGG_DATA
12345678 28310344 CAGUU-CAGIS-CAGIP-CAGIJ-CAGII-CAGIA-CAGFA-CAGPP
12345678 29437966 CAGUU-CAGIS-CAGIP-CAGIJ-CAGII-CAGIA-CAGFA-CAGPP
12345678 29456666 CAGUU-CAGIS-CAGIP-CAGIJ-CAGII-CAGIA-CAGFA-CAGPP


Order of execution of Triggers

Order of execution of Triggers

If 2 or more triggers are defined on the same statement of a table, then the order of execution of them is –

1. All before statement triggers
2. All before row triggers
3. All after row triggers
4. All after statement triggers

But, along with this, if we have 2 or more triggers defined at the same level, then we can also order their execution. Oracle has provided the FOLLOWS keyword for this.

22 September, 2015

Oracle Versions | Oracle

This page is check and visualize all the new changes that were introduced in the various updates of Oracle. 

I will start with the addition of an image with I found in some presentation a while ago.




Oracle 9i :


  • Flashback Queries (allows user to view the data of a query, that existed at a particular instant in time)

Oracle 10g :
  • Flashback Version Query

Oracle Pseudocolumns | Oracle

Named pseudocolumns as they are not actually part of the table, so not actually stored in the table.

Data of these columns can only be selected, but cannot be inserted, updated or deleted.

Some of the pseudocolumns available in Oracle are:


  • Hierarchical Query Pseudocolumns
  • Sequence Pseudocolumns
  • Version Query Pseudocolumns
  • COLUMN_VALUE Pseudocolumn
  • OBJECT_ID Pseudocolumn
  • OBJECT_VALUE Pseudocolumn
  • ROWID Pseudocolumn
  • ROWNUM Pseudocolumn

1. Hierarchical Query Pseudocolumn :
                Used only in hierarchical queries. Examples - 
CONNECT_BY_ISCYCLE - returns 1 if the parent row is also the child row of the current row, otherwise it returns 0. This is used specifically for checking the following error

ERROR:
ORA-01436: CONNECT BY loop in user data



But it can only be used in the case when the CONNECT BY clause has used the NOCYCLE parameter.

Example reference for the cycle


CONNECT_BY_ISLEAF - returns 1 if the current row is the leaf of the tree defined in the CONNECT BY condition. Otherwise it returns 0.

LEVEL - returns data based on the level of the current row in the inverted tree. 1 for the root row, 2 for its child, 3 for the next child in the tree and so on.

2. Sequence Pseudocolumns :
            Sequence is a schema object which can generate unique sequential values. These values can be used for primary key of the table.
The CURRVAL and NEXTVAL are the pseudocolumns that are used for the sequence.

3. Version Query Pseudocolumns :
            Applicable only in the flashback queries, specifically flashback version queries. The pseudocolumns are:
  • VERSIONS_STARTTIME: Returns the timestamp of the first version of the rows returned by the query.
  • VERSIONS_STARTSCN: Returns the SCN of the first version of the rows returned by the query.
  • VERSIONS_ENDTIME: Returns the timestamp of the last version of the rows returned by the query.
  • VERSIONS_ENDSCN: Returns the SCN of the last version of the rows returned by the query.
  • VERSIONS_XID: For each version of each row, returns the transaction ID (a RAW number) of the transaction that created that row version.
  • VERSIONS_OPERATION: For each version of each row, returns a single character representing the operation that caused that row version. The values returned are I (for an insert operation), U (for an update operation) or D (for a delete operation).
4. COLUMN_VALUE pseudocolumn :
            Used when a virtual table is created using the TABLE function.

5. OBJECT_ID pseudocolumn :
            returns the object identifier of the column in object table or view. Used mostly when INSTEAD OF trigger is used for any view.

6. OBJECT_VALUE pseudocolumn :
           returns the system generated names of the columns used in object table.

7. ROWID pseudocolumn :
          contains the address of each row of the table. It is the fastest way to access a row in the database.

Usually each row in the database has a unique rowid value. However, the rows of different tables stored together in the same cluster can have same rowids.

It contains the following information required to locate a row:
a> data object number of the object
b> the datafile of the tablsespace in which the row resides
c> datablock in the datafile where the row is stored
d> inside that datablock, the position of the row. The first row is termed as position 0.

8. ROWNUM pseudocolumn : 
         ROW_NUMBER build-in SQL function provides a unique way to order the resultset. The ROWNUM column is used to order the resultset of a query. Each row is assigned a unique number in the order(1,2,3,4,5...)

If order by clause is used in the same query where rownum is used, the order by will force the results to be reordered. But if the order by is used in a sub-query and rownum is used in the top level query, the rownum will be used on the ordered data.


References:

Main Article

List of Topics | Oracle

List of topics :

The post contains the list of  all the common topics that should be covered while preparing for Oracle interiews.

The page will be updated constantly as new topics and subtopics will be added.

# Pseudocolumns

23 August, 2015

Oracle | Keywords | GROUP BY, ROLLUP and CUBE

This article is for knowing how some of the keywords in Oracle work:

1. GROUP BY - Group by clause allows us to group the data based on a column or a combination of columns. The main benefit of using this keyword is when we have to get the aggregated data.
Ex - We have to find the total number of employees working in different departments. The following query can be used for this.
SELECT dept_id, COUNT(emp_id) 
FROM department d, employee e 
WHERE e.dept_id = d.dept_id 
GROUP BY dept_id 
The same way we can use group by to get the sum or average of the salaries of different departments.
 

25 July, 2015

How Many Ways a Cursor Can Be Defined In Oracle

Wandering down the roads of Oracle resources, I found an open article related to Oracle Cursors. It is a blog by Steven Feuerstein who has written many books on pl sql and Oracle in general.
The article is about the ways a cursor can be defined in Oracle.

Oracle PL SQL | Pending Questions

1. The validity of a package depends upon the validity of the other database objects it references to; So if we try to create 2 packages which have dependency on each other, then how will that contention be resolved?

Resources | Multiple Edits | Updated Periodically

1. SQL, PL/SQL The programming language of Oracle - Ivan Bayross

24 July, 2015

More on Oracle Autotrace and TKprof

 

Autotrace is quite easy to use and provides useful info about the query statistics. It should be the first tool to be used for perf. Testing an application.

Autotrace provides many of the TRACE and TKPROF statistics such as disk reads and total reads.

The main difference between the AUTOTRACE and EXPLAIN PLAN commands in Oracle is that AUTOTRACE actually executes the query (in the way TRACE does) and automatically queries the plan table, whereas EXPLAIN PLAN does neither.

 

It can be used from SQL*Plus and provides query stats on the screen.

 

Options for the Autotrace –

• autotrace on – Enables all options.
• autotrace on explain – Displays returned rows and the explain plan.
• autotrace on statistics – Displays returned rows and statistics. 
• autotrace trace explain – Displays the execution plan for a select statement without actually executing it. "set autotrace trace explain"
• autotrace traceonly – Displays execution plan and statistics without displaying the returned rows. This option should be used when a large result set is expected.

Performance Tuning | Components of a trace file

 

Components of a trace –

 

Sample of a TKPROF’ed file

 

PARSE – the phase where Oracle finds the query in the shared pool(called soft parse) or creates a new plan(hard parse)

EXECUTE – this is the work done by Oracle in the OPEN or EXECUTE part of the statement. It will be empty for SELECT stmt.

FETCH – will have the most part of processing in case of a SELECT stmt, but would be mostly empty in case of an UPDATE stmt.

 

COUNT – Gives count on how many times this phase of the query was performed. Ideally, the parse count of a query should be 1 and execute count can be 1 or more. In a properly written application, the parse count will be 1.

CPU – amount of cpu time spent in thousands of seconds.

ELAPSED – The actual clock time spent on the query. If the elapsed time is quite large than the value of cpu time, then it means oracle spent time waiting for something.

DISK – how many physical I/Os were performed on the query. Like we have 34 physical I/O reads in the above query.

 

QUERY – Number of logical I/Os performed to retrieve consistent mode blocks. Generally all physical I/Os result into a logical I/O.

CURRENT – number of logical I/Os performed to retrieve blocks as of now. This is used in cases when DML is performed in the query, like an UPDATE stmt. In this case, the query data must be retrieved in the current mode.

ROWS – The number of rows processed/ affected by this phase. For update, this value would be populated in the Execute phase, and in case of a SELECT stmt, this value would be in Parse phase.

Implicit vs. Explicit cursors

Implicit vs. Explicit

 

Both the above are purely conceptual things and for Oracle engine, both are same. But implicit cursors are more efficient and easy to deal with.

 

Implicit

Explicit

begin

  for x in ( select * from t )

  loop

     process x;

   end loop;

end;

declare

   cursor c is select * from t;

   l_rec c%rowtype;

begin

   open c;

   loop

      fetch c into l_rec;

      exit when (c%notfound);

      process l_rec;

   end loop;

   close c;

end;

/

 

Both these have no performance benefit over the other. But for explicitly defined cursors, there is more code that needs to be written and hence chances of programmatic errors are more.

Oracle pointers - Part 001

Composite Index

In a composite index, the selected columns should be chosen wisely as this impacts the index performance. The more the columns of a composite index are used in the WHERE clause , the faster would be the execution. The rule is most commonly used column should do first in the composite index.

---------

Cardinality

This is the measure of distinct values of a set. And in terms of database, cardinality is defined as the number of distinct rows returned by a query.

-----------

HINTS -

ALL_ROWS- It instructs the optimizer to fetch the last row of the result-set as fast as possible. non-interactive, batch mode type of application would benefit from this.

FIRST_ROWS - It instructs the optimizer to fetch the first row to the client as fast as possible. An interactive, typical end-user application would benefit from it.

Some tables used by optimizer to gather statistics

It’s a list of some tables which optimizer uses to gather various statistics related to the database tables.

select * from user_tables
where table_name ='EMP'

 
select * from user_tab_statistics
where table_name ='EMP'
 

select * from user_tab_col_statistics
where table_name ='EMP'

 
select * from user_tab_histograms
where table_name ='EMP'
and column_name = 'EMPID'

08 July, 2015

Oracle Collections : Introduction

A collection is an ordered group of elements which have the same data type and we use subscripts to actually access those elements.

There are three types of collections provided by Oracle:

  1. Index-by Tables / Associative Arrays
  2. Nested Table
  3. Variable size array / Varray

Index by Table / Associative Array
Each stored data unit is in the form of KEY-VALUE pair. The keys are unique and it can be either a string or an integer.

TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY sucscript_type;

table_name type_name;

Below is an example showing how to use associatibe array:

TYPE salary IS TABLE OF NUMBER INDEX BY varchar2(20);
salary_list salary;

--Adding elements to this ass. array

salary_list('ram') = 15000;
salary_list('lakshman') = 7050;
salary_list('bharat') = 35000;
salary_list('shatrugan') = 5000;

--Now using the collection elements

name := salary_list.FIRST;
WHILE name IS NOT NULL LOOP
DBMS_OUTPUT.PUT_LINE ('Salary of '||name||' is '||TO_CHAR(salary_list(name));

name := salary_list.NEXT(name);


END LOOP;

END;
/

Elements of a index-by table can be %ROWTYPE data of a database table; or it could be %TYPE of a single column of the table.


NESTED TABLES

Its like a one-dimensional array where the elements are stored with their subscript. 
But its not conventional type of array as the no. of elements in the nested table is unbound compared to normal array. And its also not as dense as arrays are because the elements keep on changing making it sparse.

The syntax of nested tables is similar to that of the index-by collection except the fact that nested tables do not use INDEX BY clause.

Nested tables can be stored in the database tables where as index-by doesn't.

06 July, 2015

Analytical Functions - Introduction

1. What we can do with analytical functions can be done through simple joins and subqueries, but aggregate functions are always faster or atleast equal to native SQL queries.

2. The “group by” works similar to the aggregate function, but the “non-group by” columns are not allowed in the query. In aggregate func, this restriction is omitted and we can see the non-group by data also and the grouped value is repeated for all the results.

select student_class, count(*) cnt from students
where class in ('6A','6B')
group by class

select student_class, house, count(*) over (partition by student_class) cnt from students
where class in ('CF','CHILD')

3. The Analytical functions are computed after all the where, join, group by and having clauses are complete and before the order by clause. So, the analytical functions can appear only in the select clause and main order by clause of the query.

4. If the condition inside the OVER() clause is left empty, the analytical functions works on the entire resultset. We can use any non-analytical function in the OVER() clause.
select status, ext_batch_id, count(*) over () cnt from gefi_batch_header
where status in ('CF','CHILD')

5. The functions SUM, COUNT, AVG, MIN, MAX are the common analytic functions the result of which does not depend on the order of the records.
Functions like LEAD, LAG, RANK, DENSE_RANK, ROW_NUMBER, FIRST, FIRST VALUE, LAST, LAST VALUE depends on order of records. In the next example we will see how to specify that. We can order the records using the ORDER BY clause inside the OVER() clause.

Now , we will explore each of the above mentioned analytical functions in detail:

ROW_NUMBER, RANK and DENSE_RANK

The order by clause of the row_number() function, does not need to be in the select part of the query. This is not possible in the normal order by clause used in the query.
select status, ext_batch_id, row_number() over (partition by status order by batch_id) cnt from gefi_batch_header
where status in ('CF','CHILD')

You can even omit the partitioning clause and still use the order by in the OVER() clause.
select status, ext_batch_id, row_number() over (order by batch_id) cnt from gefi_batch_header
where status in ('CF','CHILD')

RANK and DENSE_RANK, both provide a rank to the resultset rows, but there is a slight difference in the 2 approaches:
SELECT empno, deptno, sal,
RANK() OVER (PARTITION BY deptno
ORDER BY sal DESC NULLS LAST) RANK,
DENSE_RANK() OVER (PARTITION BY
deptno ORDER BY sal DESC NULLS
LAST) DENSE_RANK
FROM emp
WHERE deptno IN (10, 20)
ORDER BY 2, RANK;
 
EMPNO  DEPTNO   SAL  RANK DENSE_RANK
------ ------- ----- ----- ----------
  7839      10  5000     1          1
  7782      10  2450     2          2
  7934      10  1300     3          3
  7788      20  3000     1          1
  7902      20  3000     1          1
  7566      20  2975     3          2
  7876      20  1100     4          3
  7369      20   800     5          4
 
8 rows selected.


As you can see from the query and its result, the RANK skips the rank number, if it finds 2 results with the same rank level. The next in order is assigned the next possible rank. But in case if DENSE_RANK, the values are not skipped and hence it is dense[may be].