December 30, 2012

Measure Aggregation at SELECT level vs Projection level


Aggregation at SELECT level:  starts when a query is created by an user, a reporting tool creates the SQL and sends a SELECT statement with GROUP BY (selected dimension column in Query) to the database. Then the data is returned to a microcube where the first level of aggregation occurs, the microcube projects the aggregated data onto a report, the SQL is run and the microcube gets the results.


Aggregation at projection level: This aggregation working in the report level(Microcube level). When you remove a one column from the report this aggregation works .


Every measure object should have an aggregation function. Each aggregation operation typically gets combined with an appropriate projection function as well. Most of the aggregation + projection function pairs make sense. Here is the chart that shows the typical matches.

Aggregation at SELECT Level
Aggregation Projection Level
Sum
Sum
Min
Min
Max
Max
Count
Sum
Avg
None or Avg

December 28, 2012

Dynamic SQL

What is dynamic sql? Explain it.
Ans:
Dynamic SQL enables you to write programs those reference SQL statements whose full text is not known until runtime. Dynamic SQL also lets you execute data definition language (DDL) statements and other SQL statements that are not supported in purely static SQL programs.
We use dynamic sql for executing:
  • Data definition language (DDL) statements, such as CREATE, DROP, GRANT, and REVOKE
  • Session control language (SCL) statements, such as ALTER SESSION and SET ROLE
Inside Pl /sql block

   How we execute dynamic sql?
Ans:
Oracle provides two methods for using dynamic SQL within PL/SQL:
Native dynamic SQL (Execute immediate)
The DBMS_SQL package.

       What is the advantage of Native Dynamic SQL over DBMS_SQL package?
Ans:
Native Dynamic SQL is Easy to Use:

DBMS_SQL Package
Native Dynamic SQL
CREATE PROCEDURE insert_into_table (
      table_name  VARCHAR2,
      deptnumber  NUMBER,
      deptname    VARCHAR2,
      location    VARCHAR2) IS
   cur_hdl         INTEGER;
   stmt_str        VARCHAR2(200);
   rows_processed  BINARY_INTEGER;

BEGIN
   stmt_str := 'INSERT INTO ' || table_name || ' VALUES  (:deptno, :dname, :loc)';

   -- open cursor
   cur_hdl := dbms_sql.open_cursor;

   -- parse cursor
   dbms_sql.parse(cur_hdl, stmt_str,dbms_sql.native);

   -- supply binds
   dbms_sql.bind_variable(cur_hdl, ':deptno', deptnumber);
   dbms_sql.bind_variable(cur_hdl, ':dname', deptname);
   dbms_sql.bind_variable(cur_hdl, ':loc', location);

    -- execute cursor
    rows_processed := dbms_sql.execute(cur_hdl);

    -- close cursor
    dbms_sql.close_cursor(cur_hdl);
END;
CREATE PROCEDURE insert_into_table (
      table_name  VARCHAR2,
      deptnumber  NUMBER,
      deptname    VARCHAR2,
      location    VARCHAR2) IS
   stmt_str    VARCHAR2(200);

BEGIN
   stmt_str := 'INSERT INTO ' || table_name || ' values(:deptno, :dname, :loc)';

   EXECUTE IMMEDIATE stmt_str  USING  deptnumber, deptname, location;


Native Dynamic SQL is faster than DBMS_SQL:
          Because the PL/SQL interpreter has built-in support for it. Typically, native dynamic SQL statements perform 1.5 to 3 times better than equivalent DBMS_SQL calls.
Native dynamic SQL bundles the statement preparation, binding, and execution steps into a single operation, which minimizes the data copying and procedure call overhead and improves performance.
          The DBMS_SQL package is based on a procedural API and incurs high procedure call and data copy overhead. Each time you bind a variable, the DBMS_SQL package copies the PL/SQL bind variable into its space for use during execution. Each time you execute a fetch, the data is copied into the space managed by the DBMS_SQL package and then the fetched data is copied, one column at a time, into the appropriate PL/SQL variables, resulting in substantial overhead.

Native Dynamic SQL Supports User-Defined Types:
          Native dynamic SQL supports all of the types supported by static SQL in PL/SQL, including user-defined types such as user-defined objects, collections, and REFs. The DBMS_SQL package does not support these user-defined types.

Native Dynamic SQL Supports Fetching Into Records:

DECLARE
    TYPE EmpCurTyp IS REF CURSOR;
    c EmpCurTyp;
    emp_rec emp%ROWTYPE;
    stmt_str VARCHAR2(200);
    e_job emp.job%TYPE;
BEGIN
   stmt_str := 'SELECT * FROM emp WHERE job = :1';
    -- in a multi-row query
    OPEN c FOR stmt_str USING 'MANAGER';
    LOOP
        FETCH c INTO emp_rec;
        EXIT WHEN c%NOTFOUND;
    END LOOP;
    CLOSE c;
    -- in a single-row query
    EXECUTE IMMEDIATE stmt_str INTO emp_rec USING 'PRESIDENT';
END;
 
Note: A NOT NULL database column constraint does not apply to variables that are declared using %TYPE. Therefore, if you declare a variable using the %TYPE attribute that uses a database column defined as NOT NULL, you can assign the NULL value to the variable.

   What is the advantage of DBMS_SQL package over dynamic SQL?
Ans:
DBMS_SQL is supported in Client-Side Programs: The DBMS_SQL package is supported in client-side programs, but native dynamic SQL is not. Every call to the DBMS_SQL package from the client-side program translates to a PL/SQL remote procedure call (RPC); these calls occur when you need to bind a variable, define a variable, or execute a statement.

DBMS_SQL Supports DESCRIBE: The DESCRIBE_COLUMNS procedure in the DBMS_SQL package can be used to describe the columns for a cursor opened and parsed through DBMS_SQL. This feature is similar to the DESCRIBE command in SQL*Plus. Native dynamic SQL does not have a DESCRIBE facility.

DBMS_SQL Supports SQL Statements Larger than 32KB: The DBMS_SQL package supports SQL statements larger than 32KB; native dynamic SQL does not.


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