August 25, 2012

NULL



All scalar functions (except REPLACE, NVL, and CONCAT) return null when given a null argument. For example, consider a query that averages the five values 1000, null, null, null, and 2000. Such a query ignores the nulls and calculates the average to be (1000+2000)/2 = 1500. The expression NVL(COMM,0) returns 0 if COMM is null or the value of COMM if it is not null.

Any arithmetic expression containing null values evaluates to NULL.
To test for nulls, use only the comparison conditions IS NULL and IS NOT NULL.

When working with nulls, you can avoid some common mistakes by keeping in mind the following rule:
§  Simple comparisons involving nulls always yield NULL.
§  Applying the logical operator NOT to a null yields NULL.
§  In conditional control statements, if the condition yields NULL, its associated sequence of statements is not executed



a)       x:=5;
y:= NULL;
...
IF x! = y THEN   -- Yields NULL, not TRUE
                    Sequence of statements;  -- not executed
END IF;

b)       a:= NULL;
b:= NULL;
...
IF a=b THEN  --Yields NULL, not TRUE
                    Sequence of statements; -- not executed
END IF; 


August 19, 2012

LOB in Oracle


Q: What is LOB (Large Objects)?
Ans:
We can use a LONG data type to store character data up to 2GB in length per row; the LONG RAW data type provides storage for long binary data. In place of LONG and LONG RAW we can use LOB data types (BLOB, CLOB, NCLOB, and BFILE) for storage of long data upto 4GB in length

BLOB  : Binary LOB; binary data, up to 4GB in length stored in the database
CLOB  : Character LOB; Character data up to 4GB in length, stored in Database
BFILE  : Binary File; read only binary data stored outside database, the length of which is limited by operating system.
NCLOB          : (National character LOB) A CLOB column that supports a multibyte character set.

Q: Will data integrity and concurrency are maintained for BFILE data types?
Ans:
Since the column uses BFILE datatype, its data is stored outside the database, the database stores only a locator value that allows it to find the external file. Oracle does not guarantee the data integrity of BFILE files stored outside the database. Oracle does not validate that the file exists when we insert a record using a BFILE datatype.Data concurrency and integrity are maintained only for internally stored LOBs.

Q: Where the LOB data is physically stored?
Ans:
The data for the LOB columns, whether stored inside or outside the database, may not be physically stored within the table. Within the table, Oracle stores locator values that point to data location. For BFILE datatypes, the locator points to an external file; for BLOB and CLOB datatypes, the locator points to a separate data location that the database creates to hold the LOB data. Except BFILE if the data less than 4kb then it will be stored at table.

Q: Advantage of LOB over LONG and RAW datatypes.
Ans:
Long and Raw stores data upto 2GB where as LOB can stores upto 4GB.
We can have only one LONG column in a table but we can have more than one LOB column in a table

Ref Cursor


Q: What are Ref Cursor and its type?

A REF CURSOR is a cursor variable that actually contains a pointer to a query result set. The result set is determined by the execution of the OPEN FOR statement using the cursor variable. Currently pl/sql supports both strongly and weakly typed REF Cursor’s.

Pl/sql supports the declaration of a cursor variable using both the SYS_REFCURSOR built-in data type as well as creating a type of REF CURSOR and then declaring a variable of that type. SYS_REFCURSOR is a REF CURSOR type that allows any result set to be associated with it. This is known as a weakly-typed REF CURSOR.

For the strong ref cursor the returning columns with datatype and length need to be known at compile time. For the weak ref cursor the structure does not need to be known at compile time.

Declaring a SYS_REFCURSOR Cursor Variable:

          Name SYS_REFCURSOR;

Declaring a User Defined REF CURSOR Type Variable:

          Create a referenced cursor TYPE
                    TYPE emp_cur_type IS REF CURSOR RETURN EMP%ROWTYPE;
          Declare the actual cursor variable based on that TYPE
                    my_rec emp_cur_type;

Q: Example of each.
                    Strong ref cursor
                    Weak ref cursor
                    Passing Ref Cursors
Strong ref cursor:
          CREATE OR REPLACE PACKAGE strongly_typed IS
TYPE return_cur IS REF CURSOR RETURN emp%ROWTYPE;
PROCEDURE child (p_return_rec OUT return_cur);
PROCEDURE parent (p_NumRecs PLS_INTEGER); 
END strongly_typed;
/
CREATE OR REPLACE PACKAGE BODY strongly_typed IS
PROCEDURE child (p_return_rec OUT return_cur) IS
BEGIN
                    OPEN p_return_rec FOR   SELECT * FROM EMP;
END child; 
PROCEDURE parent (p_NumRecs PLS_INTEGER) IS
p_retcur return_cur;
                    at_rec   emp%ROWTYPE;
BEGIN
                    Child (p_retcur);
                    FOR i IN 1.. p_NumRecs
                    LOOP
                    FETCH p_retcur INTO at_rec;
                    dbms_output.put_line (at_rec.ename);
                    END LOOP;
END parent;

Weak ref cursor:

          CREATE OR REPLACE PROCEDURE test_proc(p_return_cur OUT SYS_REFCURSOR)
IS
BEGIN
                    OPEN p_return_cur FOR 'SELECT * FROM EMP;
END child;
/
DECLARE
cur sys_refcursor;   
all_rec    emp%ROWTYPE;
BEGIN
                    test_proc (cur);
                    FOR i  IN 1..10 LOOP
                              FETCH cur  INTO all_rec;
                              Dbms_Output.put_line (all_rec.ename);
                    END LOOP;
END; 
/

Passing Ref Cursors:
CREATE OR REPLACE PROCEDURE pass_ref_cur (p_cursor SYS_REFCURSOR) IS
TYPE array_t IS TABLE OF VARCHAR2(4000) INDEX BY BINARY_INTEGER;
rec_array array_t;
BEGIN
          FETCH p_cursor BULK COLLECT INTO rec_array;
          FOR i IN rec_array.FIRST .. rec_array.LAST
          LOOP
                    dbms_output.put_line (rec_array (i));
          END LOOP;
END pass_ref_cur;
DECLARE
          rec_array SYS_REFCURSOR;
BEGIN
          OPEN rec_array FOR 'SELECT ename FROM emp';
          pass_ref_cur (rec_array);
          CLOSE rec_array;
END;
/         

Autonomous Transactions and Its Application


Q: What is Autonomous Transactions?
Autonomous transactions allow you to create a new transaction within a transaction that may commit or roll back changes, independently of its parent transaction. They allow you to suspend the currently executing transaction, start a new one, do some work and commit or roll back, all without affecting the currently executing transaction state. And may be used in:
·        Top-level anonymous blocks
·        Local, standalone, or packaged functions and procedures
·        Methods or object types
·        Database triggers
EX:
             Create or replace procedure AutonomousInsert
             As
                          Pragma autonomous transaction;
             Begin
                          Insert into t values (‘Autonomous Insert’);
                          Commit;
             End; 
             /
Begin
   Insert into t values (‘Anonymous Block’);
   AutonomousInsert;
   Rollback;
End;
/
 
Select * from t;
Output:
MSG
-------------------------
Autonomous Insert
 
Q: In which case we need Autonomous Transactions?
 
Logging Mechanisms:
             You need to log an error to your database log table. On the other hand, you need to roll back your core transaction because of the error. And you don't want to roll back over other log entries. What's a person to do? Go autonomous!
 
Commits and rollbacks in your database triggers:
             If you define a trigger as an autonomous transaction, then you can commit and/or roll back in that code. 
 
Q: Describe the rules and restriction for Autonomous Transactions?
 
·        We can only make a top-level anonymous block an autonomous transactions 
        This will work
             DECLARE
                          PRAGMA AUTONOMOUS_TRANSACTION;
                          myempno NUMBER;
             BEGIN
                          INSERT INTO EMP VALUES (myempno, ...);
                          COMMIT;
             END;
             /
Whereas this construction:
             DECLARE
                          myempno NUMBER;
             BEGIN
                          DECLARE
                                      PRAGMA AUTONOMOUS_TRANSACTION;
                          BEGIN  
                                      INSERT INTO EMP VALUES (myempno, ...);
                                      COMMIT;
                           END;
             END;
             /
         Results an error      
             PLS-00710: PRAGMA AUTONOMOUS_TRANSACTION cannot be declared here
 
·        If an autonomous transaction attempts to access a resource held by the main transaction (which has been suspended until the autonomous routine exits), you can cause a deadlock to occur in your program.
 
             CREATE OR REPLACE PROCEDURE update_salary (dept_in IN NUMBER)
             IS
             PRAGMA AUTONOMOUS_TRANSACTION;
             CURSOR myemps IS SELECT empno FROM EMP WHERE deptno=dept_in FOR UPDATE NOWAIT;
             BEGIN
             FOR rec IN myemps
             LOOP
                          UPDATE EMP SET Sal = Sal * 2      WHERE empno = rec.empno;
             END LOOP;
             COMMIT;
             END;
             /
             BEGIN
                UPDATE EMP SET Sal = Sal * 2;
                date_salary (10);
             END;
             /   
           The results are not pretty:
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified

  • You cannot mark all subprograms in a package (or all methods in an object type) as autonomous with a single PRAGMA declaration. You must indicate autonomous transactions explicitly in each program. For example, the following package specification is invalid:

CREATE PACKAGE warcrimes_pkg 
AS
   PRAGMA AUTONOMOUS_TRANSACTION;
   
   PROCEDURE register (Culprit IN VARCHAR2, event IN VARCHAR2);
END warcrimes_pkg;
/

  • To exit without errors from an autonomous transaction program, you must perform an explicit commit or rollback. If the program (or any program called by it) has transactions pending, the runtime engine will raise an exception -- and then it will roll back those uncommitted transactions.

CREATE OR REPLACE PROCEDURE fire_em_all
IS
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
   DELETE FROM EMP;
END;
/

             SQL :\> exec fire_em_all
             *
             ERROR at line 1
ORA-06519: active autonomous transaction detected and rolled back

Q: Explain the concepts of Autonomous Transactions within SQL statement?

We have been able to call your own functions from within SQL -- provided that you follow a variety of rules. The main one is this: you are not allowed to update the database. But this can be done by using Autonomous Transactions

Suppose that we want to keep a trace of all the rows that have been touched by a query. We create this simple function to perform the audit:

CREATE OR REPLACE FUNCTION traceit (
   Tab IN VARCHAR2,
   Rowid_in IN ROWID)
   RETURN INTEGER
IS
BEGIN
   INSERT INTO query_trace VALUES (tab, rowid_in, USER, SYSDATE);
   RETURN 0;
END;
/
When I try to use this function inside a query, I get the expected error:

SQL> select ename, traceit ('emp', rowid) from EMP;
                   *
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query

If we now transform traceit into an autonomous transaction by adding the pragma (and committing my results before the RETURN statement!), the results are very different. My query works, and the query_trace table is filled:

SQL> SELECT ename, traceit ('emp', ROWID)
  2    FROM EMP;
ENAME      TRACEIT ('EMP', ROWID)
----------       --------------------
KING                          0
...
MILLER                       0


SQL> SELECT table_name, rowid_info, queried_by, TO_CHAR (queried_at, 'HH: MI: SS’) queried_at FROM query_trace;

TABLE_NAME           ROWID_INFO                     QUERIED_BY QUERIED_AT
----------       ------------------                ----------       ----------
EMP              AAADEPAACAAAAg0AAA     SCOTT          05:32:54
...
EMP              AAADEPAACAAAAg0AAN     SCOTT          05:36:50

Some New Features of oracle 11g over 10g


1.   Virtual columns

“virtual column" is an empty column that contains a function upon other table columns (the function itself is stored in the data dictionary). You cannot attempt to insert anything into the virtual column and only read that column

Ex: create table t1 (c1 number, c2 number, c3 as (c1+c2) virtual)

Note:
o   Virtual columns may not reference other virtual column values
Create table t(x number, x1 as (x+1), x2 as (x1+1)); gives error
o   11g virtual columns only work within the specified table, and you cannot reference columns within other tables

2.   Read only Tables

Prior to oracle 11g, one can’t make a single table as READ-ONLY; either makes the whole tablespace to READ-ONLY OR NOT. But this is possible in 11g.

SQL :\> alter table test read only;

The DBA_TABLES and USER_TABLES and ALL_TABLES view have a new column READONLY which can be used to see which tables are READONLY or not.

3.   Invisible indexes

You can remove an index from consideration by the optimizer by making it invisible. One possible use of this feature is to test the removal of an index before dropping it.
Prior to 11g, this was typically achieved by making an index unusable during a set period of time. During this observation period, the DBA would monitor the database performance to make the determination of whether to drop the index. If performance was negatively affected, the index would need to be rebuilt before it could be used again.
Beginning with Oracle 11g, the DBA has the option of making the index invisible, as opposed to unusable, during this observation period. If performance degradation is observed, the index can be made visible again without rebuilding the index. This can minimize the period of performance degradation while also preventing an expensive operation to rebuild or recreate an index
          SQL :\> create index t_ind on t (column_name) invisible
SQL :\> alter index t_ind invisible;
SQL :\> alter index t_ind visible

4.   Sequences in PL/SQL

Oracle 11g allows the use of sequence in PL/SQL expressions.
Prior to 11g:
DECLARE
      n NUMBER;
BEGIN
      SELECT   x_seq.NEXTVAL INTO n FROM dual;
      DBMS_OUTPUT.PUT_LINE ('Nextval=' || TO_CHAR (n));
END;
          In 11g:
DECLARE
       n NUMBER: = x_seq.NEXTVAL;
BEGIN
      DBMS_OUTPUT.PUT_LINE ('Nextval=' || TO_CHAR (n));
END;
5.   Compound Triggers

In oracle11g allows to developer to combine triggers with different timing option into a single compound trigger.

CREATE OR REPLACE TRIGGER compound_trig
FOR INSERT ON test
COMPOUND TRIGGER
-------------------------------
BEFORE STATEMENT IS
BEGIN
  dbms_output.put_line('BEFORE STATEMENT LEVEL');
END BEFORE STATEMENT;
-------------------------------
BEFORE EACH ROW IS
BEGIN
  dbms_output.put_line('BEFORE ROW LEVEL');
END BEFORE EACH ROW;
-------------------------------
AFTER STATEMENT IS
BEGIN
  dbms_output.put_line('AFTER STATEMENT LEVEL');
END AFTER STATEMENT;
-------------------------------
AFTER EACH ROW IS
BEGIN
  dbms_output.put_line('AFTER ROW LEVEL');
END AFTER EACH ROW;
END compound_trig;
/
6.   Database Replay

Database Replay provides DBAs and system administrators with the ability to faithfully, accurately and realistically rerun actual production workloads, including online user and batch workloads, in test environments. By capturing the full database workload from production systems, including all concurrency, dependencies and timing, Database Replay enables you to realistically test system changes by essentially recreating production workloads on the test system –something that a set of scripts can never duplicate.

7.   Query Result Cache

Improve the performance of SQL across the whole database instance by caching query results.
SQL :\> SELECT * FROM EMP;

5 rows selected.
Elapsed: 00:00:05.15

SQL :\> SELECT /*+ result_cache */ * FROM EMP;

5 rows selected.
Elapsed: 00:00:05.20

Adding the RESULT_CACHE hint to the query tells the server to attempt to retrieve the information from the result cache. If the information is not present, it will cache the results of the query provided there is enough room in the result cache. Since we have no cached results, we would expect the first run to take approximately five seconds, but subsequent runs to be much quicker.

SQL :\> SELECT /*+ result_cache */ * FROM EMP;

5 rows selected.
Elapsed: 00:00:00.25

The default action of the result cache is controlled by the RESULT_CACHE_MODE parameter. When it is set to MANUAL, the RESULT_CACHE hint must be used for a query to access the result cache.

SQL :\> SHOW PARAMETER RESULT_CACHE_MODE

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
Result_cache_mode                    string      MANUAL

If we set the RESULT_CACHE_MODE parameter to FORCE, the result cache is used by default, but we can bypass it using the NO_RESULT_CACHE hint.

SQL :\> ALTER SESSION SET RESULT_CACHE_MODE=FORCE;
SQL :\> select /*+ no_result_cache */  * from EMP;

August 14, 2012

SQL Traps -- Data Modeling Issue

 Chasm Trap :
                       This also known as Joining path issue or Data modeling issue.A chasm trap is a type of join path between three tables when two many-to-one joins converge on a single table, and there is no context in place that separates the converging join paths.

You only get incorrect results when the following circumstances all exist simultaneously:
1. There is a “many-to-one-to-many” relationship between three tables in the universe structure.
2. The query includes objects based on the two “many” tables.
3. There are multiple rows returned for an object (usually a dimension) based on the "one"
table.

Ex:

Client_Name
Sale_Date
Sale_Revenue
XYZ
4/12/2012
30000
XYZ
3/11/2012
34000



Client_Name
Rental_Date
Rental_Revenue
XYZ
8/10/2011
300
XYZ
10/10/2011
400


Query 1: What is the sale amount?

Client_Name
Sale_Revenue
XYZ
64000

Correct results

Query 2: What is the sale Rental Amount?

Client_Name
Rental_Revenue
XYZ
700

Correct Results

Query 3: What is the sale amount and Rental Amount

Client_Name
Rental_Revenue
Sale_Revenue
XYZ
1400
128000


This is a wrong result, which is called as issue due to chasm trap.

What is the reason behind wrong results?

                The first two queries return the correct data, but combining Sales Revenue and Rental Revenue in the third query returns inaccurate results. The query returns every possible combination of sale rows with every possible combinationof rental rows. Hence, the sale transactions each appear twice as do the rental transactions, and as a result of this the aggregates have been multiplied by the number of related rows on the alternative "many" table.


Client_Name
Sale_Date
Sale_Revenue
Rental_Date
Rental_Revenue
XYZ
4/12/2012
30000
8/10/2011
300
XYZ
4/12/2012
30000
10/10/2011
400
XYZ
3/11/2012
34000
8/10/2011
300
XYZ
3/11/2012
34000
10/10/2011
400
Sum:
128000
1400

 Solutions:
   
1.       Modify the SQL parameters for the universe so you can generate separate SQL queries for
Each measure. (File > Parameters > SQL tab )
This method is not recommended as it only works with measures and results in certain
Inefficiencies in processing. It does not generate separate queries for dimension or detail
Objects.
2.       Create a context for each fact table.
This solution works in all cases and does not result in inefficiencies.
 

FAN Trap :

This also known as Joining path issue or Data modeling issue. A Fan trap occurs when below conditions are satisfied
 
  Case 1:

1.       Table1 --< table 2 --< table 3 i.e. one to many and again one to many 
2.       A dimension coming from the first table and measures coming from the two subsequent tables.

Or

  Case 2:
  
1.       Table1 --< table 2 i.e. Two tables in a one-to-many relationship.
2.       A dimension and a measure coming from the first table and a measure coming from the subsequent table(s).

Ex:

CLINET
Client ID
Client Name
1
XYZ

PURCHASE_ORDER
PO_Number
Client_ID
Total_Amount
Discount
Net_Amount
1
1
4000
300
3700

ORDER_DEATILS
OrderNumber
Item_id
Amount
1
100
3000
1
200
1000

In this case report designer wants pull the report for below columns for client XYZ
    Client_Name – Clinet.Clinet_name
    Net_Amount – Order.Net_Amount
    Amount – Order_Details.Amount

If I pull the report for this, report will look like this.

Client_Name
Net_Amount
Amount
XYZ
7400
4000

If you see Net_Amount is not coming correctly, the value should come as 3700 not 7400.

To understand what is happening, you need to look at the rows that are returned. Since two
Different item ID numbers are involved for one order, there are two rows returned. The amount 3700 is aggregated twice in this case.

Client_Name
Item_id
Net_Amount
Amount
XYZ
100
3700
3000
XYZ
200
3700
1000

   Where you have a one-many-many relationship for tables in the FROM clause the resulting logical table produces a Cartesian product. Only then is aggregation applied. This is the reason for the fan effect.

Solutions:
1.       Modify the SQL parameters for the universe so you can generate separate SQL queries for
Each measure. (File > Parameters > SQL tab)
This method is not recommended as it only works with measures and results in certain
Inefficiencies in processing. It does not generate separate queries for dimension or detail
Objects.
2.        Use a combination of aliases and contexts.

3.        Avoid the fan trap scenario.