This new page will contain every cool tips I found regarding using Oracle, mainly 11g.

Index :

  • timing a sqlplus query
  • insert 1.000.000 rows in a table with random values
  • select by date
  • list table stats for full schema
  • create/drop stats for table/index
  • limit the number of rows returned
  • connect to a RAC instance and find which one
  • find informations on the Listener
  • searching for index
  • drop every tables from a schema

Timing a sqlplus query

Juste use :
SET TIMING ON
select * from mytable
…. Results here….
Elapsed: 00:00:00.15
Thanks to Brent V

Insert 1.000.000 rows in a table with random values

Create table test_normal (empno number(10), ename varchar2(30), sal number(10));

Begin
For i in 1..1000000
Loop
   Insert into test_normal
   values(i, dbms_random.string('U',30), dbms_random.value(1000,7000));
   If mod(i, 10000) = 0 then
   Commit;
  End if;
End loop;
End;

Create table test_random
as
select /*+ append */ * from test_normal order by dbms_random.random;

select by Date

In Oracle databases you have to convert the « string » to a date (TO_DATE), or a date to a string (TO_CHAR). The best is to use an example :

 select count(*) from portaluser where CREATED_AT > TO_DATE('2008-09-24 12:00:00', 'YYYY-MM-DD HH24:MI:SS');

The Date format is like :

MM Numeric month (e.g., 07)
MON Abbreviated month name (e.g., JUL)
MONTH Full month name (e.g., JULY)
DD Day of month (e.g., 24)
DY Abbreviated name of day (e.g., FRI)
YYYY 4-digit year (e.g., 1998)
YY Last 2 digits of the year (e.g., 98)
RR Like YY, but the two digits are « rounded » to a year in
the range 1950 to 2049.
Thus, 06 is considered 2006 instead
of 1906
AM (or PM) Meridian indicator
HH Hour of day (1-12)
HH24 Hour of day (0-23)
MI Minute (0-59)
SS Second (0-59)

List table stats for full schema

This will give you the cardinality of stats of each tables. It can be helpfull to see if your optimizer is up to date.

set linesize 256
set pagesize 0
SELECT *   FROM USER_TAB_COL_STATISTICS;

Resulting in a large list of every table/colums, with the stats:

TABLE_NAME                     COLUMN_NAME                    NUM_DISTINCT LOW_VALUE                                                        HIGH_VALUE                                                          DENSITY  NUM_NULLS NUM_BUCKETS LAST_ANAL SAMPLE_SIZE GLO USE AVG_COL_LEN HISTOGRAM
------------------------------ ------------------------------ ------------ ---------------------------------------------------------------- ---------------------------------------------------------------- ---------- ---------- ----------- --------- ----------- --- --- ----------- ---------------
PORTALUSER                     GENDER                                    3 80                                                               C103                                                             2.5444E-07          4           3 10-OCT-08     1965083 YES NO            3 FREQUENCY
PORTALUSER                     BIRTHDATE                             26633 776E0101010101                                                   78770C05010101                                                   .000037547       5338           1 10-OCT-08     1959749 YES NO           11 NONE
PORTALUSER                     LASTNAME                            1818434 096769726F7420090909                                             C3B9C3B9C3B9                                                     5.4992E-07         41           1 10-OCT-08     1965046 YES NO           11 NONE
PORTALUSER                     FIRSTNAME                           1708987 09456D616E75656C6C6509090909                                     E282AC6C2140                                                     5.8514E-07       1950           1 10-OCT-08     1963137 YES NO           11 NONE

Create/drop stats for table/index

Whatever you need to do with stats, use the dbms_stats package.

Stats creation/update:

exec dbms_stats.gather_table_stats('DB_USER','TABLE_NAME',cascade  => true, force  => true, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');

Options are not necessary. Cascade will rebuild for every column and index in the table. Force will rebuild stats that are already up to date.
Let’s go with an example :

exec dbms_stats.gather_table_stats('REVOLUTION_DEV','PORTALUSER_DOMAIN',cascade  => true, force  => true, method_opt=>'FOR ALL INDEXED COLUMNS SIZE 1');

If you want to remove every stats, use :

exec dbms_stats.delete_table_stats ( ownname=> 'REVOLUTION_DEV', tabname=> 'PORTALUSER_DOMAIN', cascade_parts=> true, cascade_columns=> true, cascade_indexes=> true);

Limit the number of row returned

While you can use « limit 10″ on Mysql, you can’t do that with Oracle.
With Oracle you have to add a WHERE statement with a limit on ROWNUM:

select id,  nickname from portaluser WHERE ROWNUM <= 10;

While I made some testing without any problem, I read to NOT use ORDER BY and ROWNUM at the same time. So, this is not recommended :

select id,  nickname from portaluser WHERE ROWNUM <= 10 order by id;

Instead, you have to use a double select :

select * from (select id,nickname  from  portaluser order by id) WHERE ROWNUM <= 10;

I really don’t know the efficience or not of such a query for now. Please, if you know, comment. Also, comment if you have information of this sort by thing and the differences between oracle 9, 10 or 11 release.
I had help from http://dotnet.org.za/thea/archive/2005/02/22/14715.aspx and http://www.ispirer.com/doc/sqlways38/Output/SQLWays-1-044.html

Connect to a RAC instance and find which one

connect system/***@ORACLE_RAC
SQL> select instance_name, host_name from v$instance ;

INSTANCE_NAME          HOST_NAME
---------------------  ---------------------
ORACLE_RAC2            host2

Find informations on the Listener

lsnrctl can give you a lot of details on the listener itself, on it’s configuration, and many more. Just check it out. Run it on both nodes, as Oracle user :

$ lsnrctl status

LSNRCTL for Solaris: Version 11.1.0.6.0 - Production on 05-NOV-2008 10:27:01

Copyright (c) 1991, 2007, Oracle.  All rights reserved.

Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
STATUS of the LISTENER
------------------------
Alias                     LISTENER_RACBAY0
Version                   TNSLSNR for Solaris: Version 11.1.0.6.0 - Production
Start Date                28-FEB-2008 12:09:33
Uptime                    250 days 22 hr. 17 min. 28 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /opt/oracle/product/11/oracle_base/asm_1/network/admin/listener.ora
Listener Log File         /opt/oracle/product/11/oracle_base/diag/tnslsnr/racbay0/listener_racbay0/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.16.249.14)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.16.0.40)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.16.4.40)(PORT=1521)))
Services Summary...
Service "+ASM" has 1 instance(s).
  Instance "+ASM1", status READY, has 1 handler(s) for this service...
Service "+ASM_XPT" has 1 instance(s).
  Instance "+ASM1", status READY, has 1 handler(s) for this service...
Service "BAYDB" has 1 instance(s).
  Instance "BAYDB1", status READY, has 1 handler(s) for this service...
Service "BAYDBXDB" has 1 instance(s).
  Instance "BAYDB1", status READY, has 1 handler(s) for this service...
Service "BAYDB_XPT" has 1 instance(s).
  Instance "BAYDB1", status READY, has 1 handler(s) for this service...
The command completed successfully

searching for index

A solution when you are trying to get some information about indexes in your database is to use the « dba_indexes » table. If you are only a user, query « user_indexes » and replace « OWNER » by « TABLE_OWNER » :

select TABLE_NAME, OWNER, INDEX_NAME, INDEX_TYPE, UNIQUENESS, DISTINCT_KEYS from dba_indexes where TABLE_NAME='PORTALUSER' order by OWNER;

TABLE_NAME                     OWNER                          INDEX_NAME                     INDEX_TYPE                  UNIQUENES DISTINCT_KEYS
------------------------------ ------------------------------ ------------------------------ --------------------------- --------- -------------
PORTALUSER                     REVOLUTION_BENCH               PORTALUSERDOMAINNICKNAME       NORMAL                      UNIQUE               16
PORTALUSER                     REVOLUTION_BENCH               PORTALUSER_NICKNAME_IDX        NORMAL                      NONUNIQUE            16
PORTALUSER                     REVOLUTION_BENCH               SYS_C0080558                   NORMAL                      UNIQUE               16
PORTALUSER                     REVOLUTION_BENCH               PORTALUSERDOMAINEMAIL          NORMAL                      UNIQUE               16
PORTALUSER                     REVOLUTION_DEMO                PORTALUSERDOMAINEMAIL          NORMAL                      UNIQUE               25
PORTALUSER                     REVOLUTION_DEMO                PORTALUSER_NICKNAME_IDX        NORMAL                      NONUNIQUE            25
PORTALUSER                     REVOLUTION_DEMO                SYS_C0064055                   NORMAL                      UNIQUE               25
PORTALUSER                     REVOLUTION_DEMO                PORTAL_LOWER_NICKNAME_IDX      FUNCTION-BASED NORMAL       NONUNIQUE            23
PORTALUSER                     REVOLUTION_DEMO                PORTAL_CREATED_AT_DESC_IDX     FUNCTION-BASED NORMAL       NONUNIQUE            25
PORTALUSER                     REVOLUTION_DEMO                PORTALUSER_EMAIL_INDEX         NORMAL                      NONUNIQUE            25
PORTALUSER                     REVOLUTION_DEMO                PORTUSRREGISTRSTATE_BITMAP_IDX BITMAP                      NONUNIQUE             2

TABLE_NAME                     OWNER                          INDEX_NAME                     INDEX_TYPE                  UNIQUENES DISTINCT_KEYS
------------------------------ ------------------------------ ------------------------------ --------------------------- --------- -------------
PORTALUSER                     REVOLUTION_DEMO                PORTALUSERDOMAINNICKNAME       NORMAL                      UNIQUE               25
PORTALUSER                     REVOLUTION_DEV                 PORTAL_LOWER_NICKNAME_IDX      FUNCTION-BASED NORMAL       NONUNIQUE       1965083
PORTALUSER                     REVOLUTION_DEV                 PORTAL_CREATED_AT_DESC_IDX     FUNCTION-BASED NORMAL       NONUNIQUE        296631
PORTALUSER                     REVOLUTION_DEV                 SYS_C0062869                   NORMAL                      UNIQUE          1965086
PORTALUSER                     REVOLUTION_DEV                 PORTALUSER_NICKNAME_INDEX      NORMAL                      NONUNIQUE       1965086
PORTALUSER                     REVOLUTION_DEV                 PORTALUSER_EMAIL_INDEX         NORMAL                      NONUNIQUE       1965086
PORTALUSER                     REVOLUTION_DEV                 PORTALUSERDOMAINNICKNAME       NORMAL                      UNIQUE          1965086
PORTALUSER                     REVOLUTION_DEV                 PORTALUSERDOMAINEMAIL          NORMAL                      UNIQUE          1965086
PORTALUSER                     REVOLUTION_DEV                 PORTALUSER_DOMAINID_INDEX      NORMAL                      NONUNIQUE             1
PORTALUSER                     WEBPORTALS_UAT                 PORTAL_LOWER_NICKNAME_IDX      FUNCTION-BASED NORMAL       NONUNIQUE        339672
PORTALUSER                     WEBPORTALS_UAT                 PORTAL_CREATED_AT_DESC_IDX     FUNCTION-BASED NORMAL       NONUNIQUE        331207

Then you can learn more of the index with the query :

select index_name, table_name, column_name  from  user_ind_columns order by table_name, index_name,column_position;

Drop every tables from a schema

Even when using impdp to import data, the old schema is not removed. You only get new schema change and data. Then you need to remove everything before importing, including constraints.

One solution is to use a cursor loop as the schema user :

DECLARE cursor usertables IS
  select table_name from user_tables;
BEGIN
for cur in usertables loop
    EXECUTE IMMEDIATE 'DROP TABLE "WEBPORTALS_UAT".'||cur.table_name||' CASCADE CONSTRAINTS';
end loop;
END;
/

You can drop every sequences by replacing the table select by :

select sequence_name from user_sequences;

-

Links

http://justgeeks.blogspot.com/
http://www.oracle.com/technology/pub/articles/sharma_indexes.html
http://www.psoug.org/library.html
http://fadace.developpez.com/oracle/rac/spfile/