September 11, 2010

Use of Constants

Posted in Oracle, PL/SQL tagged , , , , , at 1:35 am by itsourteamwork

A constant is something whose value never changes. For ex, literal 5 is a constant, because the value 5 can’t be changed. Similarly, the character literal “BOOK” is also a constant.

A constant variable is a normal variable but this variable’s value can’t be changed.

Why to use a constant when the literal can be directly used in a program?

Well, lets take an example:
Suppose, there is a program, which calculates commission for the sales reps depending on the no of orders that they booked. If the total no of orders are greater than 10 then the sales rep will get 5 percent commission on the total order that he/she booked.

CREATE OR REPLACE PROCEDURE pr_calc_comm
(p_sales_rep_id  ORDER_MST.sales_rep_id%TYPE) IS

v_order_count          PLS_INTEGER;
v_order_value          NUMBER;
v_comm_amt             NUMBER;
v_stmt                 VARCHAR2(32000);
BEGIN
v_stmt := ‘Select order_mst WHERE sales_rep_id =’ || p_sales_rep_id|| ‘ at 100′;

–Get the total no of orders and the order value
SELECT COUNT(orders_id) , SUM(order_value)
INTO v_order_count , v_order_value
FROM order_mst
WHERE sales_rep_id = p_sales_rep_id;

/* Check whether the order count is greater than 10.
If yes, then calculate the commission as 5% of the order value */
v_stmt :=’Calculating comm at 200′;

IF v_order_count > 10 THEN

v_comm_amt := v_order_value * 5 / 100;
v_stmt :=’Insert into comm_tab at 300’;

INSERT INTO comm_tab(sales_rep_id,comm_amt)
VALUES (p_sales_rep_id, v_comm_amt);

COMMIT;

END IF;

EXCEPTION
WHEN OTHERS THEN
Raise_application_error(‘Error’ ||SQLERRM || ‘ at ‘|| v_stmt);

END;

Above program will work fine.

What if, if the commission percentage is changed to 7 percent? Well, you can open the code and change the percentage to 7. Similarly, if the order count is changed to 15 from 10, then also, the program can be modified. You can replace 10 by 15.
What if, if the percentage 5 is used in more than one place in a big program, say a program of 1000 line? How can you find the value in that big program?
Now lets re-write the same program by using constants

CREATE OR REPLACE PROCEDURE pr_calc_comm
(p_sales_rep_id  ORDER_MST.sales_rep_id%TYPE) IS

v_order_count                                  PLS_INTEGER;
v_order_value                                  NUMBER;
v_comm_amt                                   NUMBER;
v_stmt                                                VARCHAR2(32000);

–Declare constant variables
c_min_order_count CONSTANT  PLS_INTEGER := 10;
c_comm_pct             CONSTANT  NUMBER(5,2) := 5;


BEGIN

v_stmt :=’Selet on order_mst WHERE sales_rep_id =’ || p_sales_rep_id|| ‘ at 100′;
–Get the total no of orders and the order value

SELECT COUNT(orders_id) , SUM(order_value)
INTO v_order_count , v_order_value
FROM order_mst
WHERE sales_rep_id = p_sales_rep_id;

v_stmt :=’Calculating comm at 200’;

/* Check whether the order count is greater than 10.
If yes, then calculate the commission as 5% of the order value */

IF v_order_count > c_min_order_count THEN

v_comm_amt := v_order_value * c_comm_pct / 100;
v_stmt :=’Insert into comm_tab at 300′;

INSERT INTO comm_tab(sales_rep_id,comm_amt)
VALUES (p_sales_rep_id, v_comm_amt);

COMMIT;

END IF;

EXCEPTION

WHEN OTHERS THEN
Raise_application_error(‘Error’ ||SQLERRM || ‘ at ‘|| v_stmt);

END;

We have added two constant variables and used them in the program. Now, if the values need to be changed, then simply we need to change the value in the declaration section.
Now, what if, if the same variable needs to be used in more than one procedure/function/package body? Individual constant variables can be declared in the respective procedure/function/package bodies. If the value of the constant variable needs to be changed then we have to change in all the places where ever the constant variables were declared.
So, if the same constant variables need to be used in more than one procedure, then create a package, which contains the constant variables, and use them in the individual programs.
Another use of Constants
Suppose, in a Banking application, there can be diff types of accounts. Savings account, Current Account, and Salary account etc. Lets take a piece of code from a program
IF v_account_type = ‘S’ THEN –Check for savings acc type
–DO something
ELSIF v_account_type =’C’ THEN –Check for current acc type
–DO something
ELSIF v_account_type =’L’ THEN — Check for Salary acc type
— DO something
ELSE
–display some error informing the user that Invalid acc type
— or do nothing
END IF;
Instead of using the special lateral values like S, C, L, constants can be declared as

c_acc_type_savings CONSTANT CHAR(1) := ‘S’;
c_acc_type_current CONSTANT CHAR(1) := ‘C’;
c_acc_type_salary  CONSTANT CHAR(1) := ‘L’;

and the above IF statement can be re-written as
IF v_account_type = c_acc_type_savings THEN  –Check for savings acc type
–DO something
ELSIF v_account_type =  c_acc_type_current THEN  –Check for current acc  type
–DO something
ELSIF v_account_type = c_acc_type_salary THEN  — Check for Salary acc type
— DO something
ELSE
–display some error informing the user that Invalid account type
— or do nothing
END IF;

Also, if a variable needs to be compared with a value called ‘Savings’ like

IF v_acc_type =’Savings’ THEN
END IF;
and, the value ‘Savings’ needs to be checked in many places, then there is a chance for making typo errors. Instead if a constant is used then the chance making typo errors can be eliminated
.
The best practice is to use constant variable instead of constant values.

Always declare constants at the appropriate scope rather than use special literal values in code.  Do not use ‘magic’ literals in code.
The benefits of this methodology include the following:

  • Standardization: If a value has a significant meaning for multiple objects within a package or throughout a schema, or even at a broader scope, it can be defined and maintained easily and consistently across the entire spectrum.
  • Compile-time checking of all sentinal values. Since the actual value of the constant is maintained in one place only, there is no danger of multiple uses of the same value being misspelled, miss-cased (upper/lower) or otherwise inconsistent with one a nother, resulting in data or logic errors.

Ease of maintenance.  If a value needs to change, the change is made in one place and all uses of it are automatically synchronized.
Last, but not the least, keep all the constants in a common packages and use them wherever required.

September 6, 2010

Performance Improvement with Associative Arrays in PL/SQL, Oracle

Posted in Oracle, PL/SQL, SQL tagged , , , , , , at 10:41 am by itsourteamwork

Lets see, how the performance can be improved with the use of Associative Arrays.

We are going using Associative Arrays for caching the data to reduce the function calls or select statements.

Suppose, there is a Function (get_dept_info) which returns the dept name for a given dept no from the dept table.

In a main pl/sql block, from the emp table, all the employees will be retrieved one by one in a loop, for each emp retrieved, the above function (get_dept_info) will be called to get the dept name (we can get the dept name by joining the emp table directly with dept table also). For explaining the concept only we are using this example.

The algorithm that we are going to follow is

  1. Create a replica table (emp_new) for the emp table
  2. Insert more data into the table (emp_new) so for the testing.
  3. Create a pl/sql block
  4. In the pl/sql block, loop thru the employees in the emp_new table
  5. for each emp, try to get the dept name :
  6. This part we will do in two ways
  7. 1: directly calling (get_dept_info) function
  8. 2: using associative arrays
  9. then do any processing as per the requirement.  In our case we will not do anything.

Now lets how to do this:

–Connect to the user Scott

SQL> SHOW USER;
USER is “SCOTT”

–Set the TIMI ON to see the time taken to execute the commands

SQL> SET TIMI ON;

–Create a table, exact replica of emp table

SQL> CREATE TABLE emp_new AS SELECT * FROM emp;

Table created.

Elapsed: 00:00:00.10

–Change the column width of empno to store any bigger no.

SQL> ALTER TABLE emp_new MODIFY empno NUMBER;

Table altered.

Elapsed: 00:00:00.03

–A pl/sql block to insert more rows into the emp_new table

SQL> BEGIN
2    FOR I IN 1..15 LOOP
3      INSERT INTO emp_new SELECT * FROM emp_new;
4    END LOOP;
5    UPDATE emp_new SET empno = empno+ROWNUM;
6    COMMIT;
7  END;
8
9  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:22.28
SQL>
SQL> SELECT COUNT(*) FROM emp_new;

COUNT(*)
———-
491520

Elapsed: 00:00:01.23

–Create the function to return the dept name for a given dept no

SQL> CREATE OR REPLACE    FUNCTION get_dept_info ( p_dept_no dept.deptno%TYPE) RETURN VARCHAR2 IS
2        v_dname  dept.dname%TYPE;
3      BEGIN
4        SELECT dname INTO v_dname FROM dept WHERE deptno = p_dept_no;
5        RETURN v_dname;
6      EXCEPTION
7        WHEN OTHERS THEN
8          Raise_application_error (-20100,’Error ‘|| sqlerrm ||’ for deptno = ‘ || p_dept_no);
9      END get_dept_info ;
10
11  /

Function created.

Elapsed: 00:00:00.06

–Now, execute the following code to get the dept name for the dept no

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2      v_str                            VARCHAR2(32000):=’In Declaration Secion’;
3      v_dname                          dept.dname%TYPE ;
4
5  BEGIN
6    v_str :=’Before For loop at 100′;
7    FOR emp_data IN (SELECT * FROM emp_new WHERE deptno IS NOT NULL)  LOOP –loop thru the employees
8      v_str :=’Calling get_dept_info (‘ ||emp_data.deptno ||’) at 200′;
9      v_dname := get_dept_info (emp_data.deptno);  –function call to get the dname
10      –DBMS_OUTPUT.PUT_LINE(‘For dno ‘|| emp_data.deptno ||’ dname is ‘|| v_dname);
11      NULL;
12    END LOOP;
13
14
15  EXCEPTION
16    WHEN OTHERS THEN
17       Raise_application_error(-20010,’Error ‘||SQLERRM ||’ at ‘||v_str);
18  END;
19
20  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:14.57

–Change the code to get the dept name using associative arrays

–Create an associative array index by VARCHAR2;

–FOR each dept no retrieved from the emp table, first check in the associative arrary, if there exists a dept name

–If exists then return

–If not then, NO_DATA_FOUND exception will be raised

–In the exception handler, call the function (get_dept_info) to get the dept nam

–store the dept name in the associative array for the next use

–In this way, the no of calls to the function will be reduced(the max no of  calls will be the no of distinct values in the emp table)

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2      v_str                            VARCHAR2(32000):=’In Declaration Secion’;
3      v_dname                          dept.dname%TYPE ;
4      TYPE  dname_type  IS TABLE OF dept.dname%TYPE INDEX BY VARCHAR2(10);  –Array type declaration
5      v_dname_tab  dname_type;  –Variable for the array
6  BEGIN
7    v_str :=’Before For loop at 100′;
8    FOR emp_data IN (SELECT * FROM emp_new WHERE deptno IS NOT NULL)  LOOP
9      BEGIN
10        v_dname := v_dname_tab(emp_data.deptno); — Check associative array
11      EXCEPTION
12        WHEN NO_DATA_FOUND THEN  –Means the dept no is not there in the array
13          v_str :=’Calling get_dept_info (‘ ||emp_data.deptno ||’) at 200′;
14          v_dname := get_dept_info (emp_data.deptno);   –call the function to get the dept name
15          v_dname_tab(emp_data.deptno ) := v_dname ;  –Store in the associative array for the future use
16      END;

17
18      –DBMS_OUTPUT.PUT_LINE(‘For dno ‘|| emp_data.deptno ||’ dname is ‘|| v_dname);
19      NULL;
20    END LOOP;
21
22
23  EXCEPTION
24    WHEN OTHERS THEN
25       Raise_application_error(-20010,’Error ‘||SQLERRM ||’ at ‘||v_str);
26  END;
27
28  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:01.76

The time taken for first block to execute is 14 secs. The time taken for the second block to execute is 2 secs. See the diff.

August 31, 2010

OBIEE 11g : New Features

Posted in OBI EE, Oracle tagged , , , , , at 11:57 am by itsourteamwork

Much awaited requirement :
Now create analysis (requests) from multiple subject areas which are related to each other.

Click here for full list of new features.

August 29, 2010

Are We Going Back?

Posted in Oracle tagged , , , , , , at 4:13 am by itsourteamwork

Flat File Vs XML

Those who worked in COBOL language, DBase or any other language to store the data in a DAT file, will know about that, the file can be opened from its location and the data can be views(unlike the data stored in a database). This DAT file will have an heading as the first row and the other rows are the data corresponding to each column.

If the same file is compared with and XML file, the data will be stored in the same column style but with in tags.

So, it can be compared with a flat DAT file with the data being enclosed in TAGs.

Dumb Terminals Vs Thin Client

Similarly, in old days, the server was a powerful system and dumb terminals (clients) were connected to the server from diff locations. The clients will send every request/operation to the server and the Sever will send the results back which was effecting the network traffic.

Later, in place of the dumb terminals, a smart client was introduced which can do the processing at the client place itself if the process/request does not require any server interaction or any information from the server. So the client, intelligently, decides whether it can server the request or not there by reducing the network traffic.

Now, the concept of Thin Client came in, where the clever client is replaced by a thin client whose price is very less compared to the smart client. Again its a trade-off between the network traffic and the price of the client. But the point here is, they have gone back to the old style of dumb client/terminal.

August 26, 2010

OBIEE 11g : New Feature : Archive – Unarchive : A Powerful Way To Export And Import The Objects

Posted in OBI EE, Oracle tagged , , , , at 10:12 am by itsourteamwork

I am sure, in Answers/Dashboards, most othe OBIEE 10g requests developers would have faced a common issue of copying all their objects from one folder to another folder, one environment to another environment (in the developing stage) etc.

If you got the access to the system in which the Catalog is stored then, these action are very easy. But how to do it in Dashboard catalog.

OBIEE 11g came up with a solution for this problem. Archive and Unarchive. In Archive you can archive (export)a folder with diff objects to the local file system. The the archived file can be unarchived (imported) into another folder. So simple… isn’t it?

Archiving

First, select the folder which needs to be archived. For ex, we want to archive Sample Lite folder.

Now, click on the Archive link, which will open a dialog box with some options for the archiving. These options will be discussed in the coming posts.

After clicking OK button, a dialog box will appear asking where the catalog to be saved. Select the desired location and save the file.

Unarchiving

Select the folder into which the archived (exported) filed needs to be unarchived (imported). In our example, we are going to unarchive the Sample Lite folder into a Test folder. Then click on the Unarchive link.

The Unarchive dialog box will appear which allows us to select the file which needs to be unarchived into the currently selected folder ( in our example, its Test).

Select the appropriate archive file name and click on OK (The other available options will be discussed in the coming posts).

OBIEE will unarchive the file into the selected folder.

See, how easily the folders can be copied from one folder to another folder with going into the file system.

OBIEE 11g : Home Page Option

Posted in OBI EE, Oracle tagged , , , at 9:38 am by itsourteamwork

OBIEE 11g came up with a new option called “Home” which is like one page to create new object (like dashboard, analysis, reports), see the recently visited or most populate objects etc.

OBIEE 11g : First Look

Posted in OBI EE, Oracle tagged , , , at 9:34 am by itsourteamwork

Have the first look at OBIEE 11g in Dashboard and Catalog (previously Answers)

Login Screen

Once, you are logged in, you will be taken to your “My Dashboard” which will be empty in the beginning.

Click on the “Edit” link to create the dashboard in the dashboard editor.

August 23, 2010

OBIEE 11g : First Look at (Catalog) Answers

Posted in OBI EE, Oracle tagged , , , at 2:19 pm by itsourteamwork

At last, I got a chance to log into OBIEE 11g dashboards and here is the first look at the Catalog (previously Answers)

August 10, 2010

What is Client-Server Architecture?

Posted in Oracle tagged , , , at 9:28 am by itsourteamwork

A Client-Server Architecture is a system in which many systems(clients) will be connected to a central system (server). The server accepts the request from clients, process them (if required, stores the data) and sends the results back to the client.

The server system will be a high-end system with strong processing and storage capacity. The server stores the data related to the organization centrally. Whenever a client request for any data, it will send the requried data to the client.
The clients can be thin client or strong client.

The Thin client (also called as dumb client) can’t do any thing on their own. For every small calculation they are dependent on the server. They simply sends the request and gets the ouput to present to the user.

Advantages : They are Cost effective as, they are very cheap in price.

Disadavantage : For each and every request, they are depenent on the server. Assume a situation where the user provided Qty and Price Per Unit. Now the total price needs to be displayed. To do this, there is no requirement of the data from the server. Its a smimple mathematical calculation. But, even to do this, the client depends on the server to do the processing.

The Strong client (also called as Clever client) is a system with some processing capacity in it.

Advantage: Unlike the dumb client, its not dependent on the server for every thing. Its clever enough to do all the things which does not required any server intervention. So these will reduce the network traffic.

Disadvantage: They are costly as compared with the dumb clients.

August 3, 2010

Not In Vs Minus in SELECT statement of Oracle

Posted in Oracle, SQL tagged , , at 12:56 pm by itsourteamwork

What is the diff between NOT IN and MINUS. As per the SET theory, both should yield the same results.

Lets take an example : From the scott schema by using the Emp and Dept table, if the following queries were fired to get the list of DEPARTMENTS that do not have any EMPLOYEE, then,

SELECT deptno FROM dept WHERE deptno NOT IN (SELECT deptno FROM emp);

and

SELECT deptno FROM dept
MINUS
SELECT deptno FROM emp;

both queries will return no rows.
————————————————————–
Now, lets look at the following data:

DEPARTMENT table got few more rows

DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
50 QUALITY CHICAGO
60 IT CHICAGO
70 MARKETING NEY YORK

EMPLOYEE table
For the first row, employee no 9999, there is no department assigned. Deptno is NULL.

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO STATUS
9999 James James 7782 23-Jan-82 1300 (null) (null) Y
7369 SMITH CLERK 7902 17-Dec-80 800 (null) 20 Y
7499 ALLEN SALESMAN 7698 20-Feb-81 1600 300 30 Y
7521 WARD SALESMAN 7698 22-Feb-81 1250 500 40 Y
7566 JONES MANAGER 7839 2-Apr-81 2975 (null) 20 Y
7654 MARTIN SALESMAN 7698 28-Sep-81 1250 1400 50 N
7698 BLAKE MANAGER 7839 1-May-81 2850 (null) 30 Y
7782 CLARK MANAGER 7839 9-Jun-81 2450 (null) 10 N
7788 SCOTT ANALYST 7566 19-Apr-87 3000 (null) 20 Y
7839 KING PRESIDENT (null) 17-Nov-81 5000 (null) 10 N
7844 TURNER SALESMAN 7698 8-Sep-81 1500 0 30 Y
7876 ADAMS CLERK 7788 23-May-87 1100 (null) 20 N
7900 JAMES CLERK 7698 3-Dec-81 950 (null) 30 Y
7902 FORD ANALYST 7566 3-Dec-81 3000 (null) 20 N
7934 MILLER CLERK 7782 23-Jan-82 1300 (null) 60 Y

If the below queries were fired, to get the list of departments that does not have any employee, one row (department no 70) should be returned.

SELECT deptno FROM dept WHERE deptno NOT IN (SELECT deptno FROM emp);

and

SELECT deptno FROM dept
MINUS
SELECT deptno FROM emp;

But surprisingly, first query will return no rows and the second will return the department no 70 because this dept does not have any employee.

Why? Its because, in the first query, each deptno from dept table will be compared with all the deptnos along with the NULL in the emp table. Remember, comparison of a value with NULL will be FALSE. So the deptno 70 comparison with NULL will be false and deptno 70 will not be returned.

Next page