Thursday, July 23, 2009

Popular Misconception

There is a popular misconception that NOT IN and NOT EXISTS are two ways to filter out rows present in one table and not in another table, with both methods being usable interchangeably. Popular wisdom is that the difference between the two is only in terms of performance (being on the basis of whether the larger table is the "outer" or the "inner" in the query) but that the results are the same.


However, we must remember that such an operation being an Anti-Join fails when NULLs are involved. In Oracle a NULL cannot be compared to any other value, not even another NULL. Therefore, a NOT IN operation would fail if the result set being probed returns a NULL. In such a case, the results of a NOT IN query is 0 rows while a NOT EXISTS query would still show the rows present in the one table but not in the other table.

Here is a simple demonstration :-

-- create the two test tables
SQL> create table results_table as select owner,object_name,object_type from dba_objects where owner in ('HEMANT','DBSNMP','OUTLN');

Table created.

SQL> create table query_table as select owner,object_name,object_type from dba_objects where owner in ('DBSNMP','OUTLN');

Table created.

-- A NOT IN query
SQL> SELECT r.owner, r.object_name 
                   FROM results_table r
                WHERE r.owner NOT IN (SELECT q.owner FROM query_table q)
                ORDER by 1,2;

OWNER OBJECT_NAME  
------------------------------ ------------------------------  
HEMANT DUPDB  
HEMANT MY_T_A  
HEMANT RESULTS_TABLE  
HEMANT SOURCE_TABLE  
HEMANT TEST_APPEND  
HEMANT TRACE_USER_SESSIONS  
HEMANT TRACE_USER_SESSIONS_BEGIN  
HEMANT TRACE_USER_SESSIONS_END  

8 rows selected.

-- A NOT EXISTS query

SQL> SELECT r.owner, r.object_name 
                FROM results_table r
               WHERE NOT EXISTS (SELECT '1' 
                                                           FROM query_table q
                                                         WHERE r.owner=q.owner)
               ORDER by 1,2;

OWNER OBJECT_NAME  
------------------------------ ------------------------------  
HEMANT DUPDB  
HEMANT MY_T_A  
HEMANT RESULTS_TABLE  
HEMANT SOURCE_TABLE  
HEMANT TEST_APPEND  
HEMANT TRACE_USER_SESSIONS  
HEMANT TRACE_USER_SESSIONS_BEGIN  
HEMANT TRACE_USER_SESSIONS_END  

8 rows selected.

SQL> REM So far, NOT IN and NOT EXISTS have presented the same results
SQL> REM What happens if there is a row with a NULL value ?
SQL> INSERT INTO query_table VALUES (NULL,'ABCDEFGH','TABLE');

1 row created.

SQL> -- Retry the NOT IN query
SQL> SELECT r.owner, r.object_name 
                   FROM results_table r
                 WHERE r.owner NOT IN (SELECT q.owner FROM query_table q)
                  ORDER by 1,2;

no rows selected

SQL> -- retry the NOT EXISTS query
SQL> SELECT r.owner, r.object_name 
                 FROM results_table r
               WHERE NOT EXISTS (SELECT '1' 
                                                           FROM query_table q
                                                        WHERE r.owner=q.owner)
             ORDER by 1,2;
OWNER OBJECT_NAME  
------------------------------ ------------------------------  
HEMANT DUPDB  
HEMANT MY_T_A  
HEMANT RESULTS_TABLE  
HEMANT SOURCE_TABLE  
HEMANT TEST_APPEND  
HEMANT TRACE_USER_SESSIONS  
HEMANT TRACE_USER_SESSIONS_BEGIN  
HEMANT TRACE_USER_SESSIONS_END  

8 rows selected.

SQL> REM Why ? Because of the presence of a NULL in the query_table !
SQL> REM So a "NOT IN" anti-join fails because a NULL returned cannot be compared !
SQL> REM One "workaround" is to filter out rows which contain NULLs
SQL> REM but think carefully before you do so. Are you sure you want to exclude them ?
SQL>
SQL> REM In the ideal world, such columns should be defined as NOT NULL columns !
SQL> REM That would be the right schema design !
SQL> -- test the suggested workaround
SQL> SELECT r.owner, r.object_name 
                  FROM results_table r
                WHERE r.owner NOT IN (SELECT q.owner 
                                                                 FROM query_table q
                                                              WHERE OWNER IS NOT NULL)
                ORDER by 1,2;

OWNER OBJECT_NAME  

------------------------------ ------------------------------  
HEMANT DUPDB  
HEMANT MY_T_A  
HEMANT RESULTS_TABLE  
HEMANT SOURCE_TABLE  
HEMANT TEST_APPEND  
HEMANT TRACE_USER_SESSIONS  
HEMANT TRACE_USER_SESSIONS_BEGIN  
HEMANT TRACE_USER_SESSIONS_END  

8 rows selected.


You can see that if there is a single row with a NULL value on the query predicate (the OWNER column in QUERY_TABLE), the NOT IN query actually fails.

Tom Kyte has explained this in the section on Anti-Joins in his "Effective Oracle By Design" book. And its posted by Hemant K Chitale in his http://hemantoracledba.blogspot.com./


I conclude that NOT IN will behave like <>ALL and NOT EXISTS will behave like <>ANY.

Wednesday, July 22, 2009

Memory Map of Oracle Forms

In oracle forms after we deployed our forms into a service when a user opens a form until the user close the form we cant be able to compile it (Convert to fmx). To achieve this we can use this in the configuration.
FORMS_MMAP=FALSE

Export and Import Data Pump Utility

This Export (EXPDP) and Import (IMPDP) utilities are introduced in Oracle 10g for full or partial data export and import. 

It has many new features compared with the old version of Export (EXP) and Import (IMP) utilities.

Additional features :- 

1. We can compress the datas when export. so that the dump file size will be reduced.

2. We can Split the export as jobs. And start/stop/restart it when ever needed.

3. We can export specific database object of specific database users and specific tablespaces alone.

4. When Import we can remap the user to another user. i.e when we export a user objects and want to import it as another user object it will be useful.

5. Same way we want to remap the objects from one tablespace to another tablespace when importing. 

6. We can import the database when exporting the database. Which looks like direct export and import of database/users/objects from one system to another system in the network.

Here Code given will be used to achieve 4 and 5.

EXPDP 'SYS/ORACLE@NEW AS SYSDBA' SCHEMAS=SCOTT DUMPFILE=STS.DMP


IMPDP 'SYS/ORACLE22@ORCL22 AS SYSDBA' DUMPFILE=STS.DMP REMAP_SCHEMA=SCOTT:RMVER REMAP_TABLESPACE=USERS:RMVER

This code will be used to achieve 6

create database link dbl2  connect to  rmver721 identified by rmver721 using '(DESCRIPTION =
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(HOST = DB_SERVER)(PORT = 1521))
   )
   (CONNECT_DATA =
     (SERVICE_NAME = orcl)
   )
)';

IMPDP 'SYS/ORACLE22@ORCL22 AS SYSDBA' SCHEMAS=SCOTT REMAP_SCHEMA=SCOTT:RMVER REMAP_TABLESPACE=USERS:RMVER NETWORK_LINK=dbl2

Have Updated and Use Features

Thanks 

Have a nice day.