New WordPress

I am using godaddy as hosting provider. It is fairly cheap and reliable, and when I moved from blogspot to my own domain, I realised the “economic” plan I was using did not allow to keep on using blogspot on my own domain (something with active/passive ftp).

The wordpress tool they offered worked well, but is no longer supported and they provided no upgrade path to 2.6.x, so when I installed 2.6, it just deleted all my posts, anyway I had a backup and managed to import (as sql statements) my posts in the new blog… lucky!

Please mention me any annoyance you may have with this new one !

my book is in Louisville

I just could not wait any longer for my free copies so I ordered my own book on amazon :mrgreen:

amazon 0977671585

I am now tracking my package …

Information about shipment

Ship Carrier: UPS
Tracking Number: 1Z5R89396630405037
Status: In transit
Order #: 104-6746451-0852226
Shipment Date: November 24, 2008
Destination: BIRMENSDORF, CH
Estimated Arrival: November 28, 2008

Track your package

Date Time Location Event Details
November 25, 2008 02:00:00 AM LOUISVILLE KY US Arrival Scan
November 24, 2008 08:59:00 PM PHOENIX AZ US Departure Scan
November 24, 2008 06:59:00 PM PHOENIX AZ US Arrival Scan
November 24, 2008 06:37:00 PM PHOENIX AZ US Departure Scan
November 24, 2008 04:43:00 PM PHOENIX AZ US Shipment received by carrier
November 24, 2008 01:19:48 PM US Shipment has left seller facility and is in transit

one more OCE certification

I have passed my Oracle 9i Certified Master exam in 2004. Since then the 10g exam has been in preparation.

Well, according to dba10gocm_upgrade the OCM Upgrade exam content has not been finalized.

There is also an OCM Member restricted website. In case you have the password, you can read :
More Great Benefits Coming Soon . . .

Soon=Forever+a few centuries?

According to Paul answer to my comment on his blog : we are developing a one-day upgrade exam for 10g OCM to 11g OCM and will include a streamlined path for 9i OCM to 11g OCM

Ok, I am a bit pessimistic about the future of OCM. As OCM Gregory Guillou posted on my previous blog post :
It doesn’t really make any sense to have an upgrade exam for the what ? 50 9i OCM ?

Since about last year there is a way more succesful exam suite. The Oracle Certified Expert. I did myself pass the rac and sql ones.

Ok, the news :
There is a new Oracle Certified Expert exam which is called : Oracle Database 11g Performance Tuning Certified Expert

The exam is in Beta now, good luck to you!

<CTRL> + .

Sometimes the simplest tricks just ease your life the nice way.

While typing code in TOAD, I just found out those two handy keyboard shortcuts

<CTRL> + . = Autocompletes tablenames
<CTRL> + T = Popups the list of column names

I want to select everything from emp and dept joined on deptno.


SELECT*FROM E e,D d
where e.=d.

Especially useful when table and column is not EMP.DEPTNO but WWRTM_CUOTDSOTM_IWUWH_ML.H2OUUP2_NIAGASTSGM_IMUMTUCI πŸ™‚

select in HTML format, XQUERY variant

Same as Select in html format, but with XMLTABLE instead of XMLTRANSFORM


select
xmlroot(
xmlelement(
"table",
xmlconcat(
xmltype(
'<tr><th>DEPTNO</th><th>DNAME</th><th>LOC</th></tr>'),
xmlagg(column_value)
)
),version '1.0'
)
from
xmltable('
for $f in ora:view("LSC_DEPT")
return
<tr>
<td>{$f/ROW/DEPTNO/text()}</td>
<td>{$f/ROW/DNAME/text()}</td>
<td>{$f/ROW/LOC/text()}</td>
</tr>');

DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

select in HTML format

Last Wednesday I selected data from an HTML table : select from xml

Today, let’s try the opposite, generate an HTML table from a SQL query


select
XMLSERIALIZE(
DOCUMENT
XMLROOT(
XMLTRANSFORM(
XMLTYPE(
CURSOR(
SELECT * FROM DEPT
)
),
XMLTYPE.CREATEXML(
'




Table DEPT

Table DEPT in HTML format


DEPTNO DNAME LOC




'
)
)
, VERSION '1.0')
)
from DUAL;

Table DEPT in HTML format

DEPTNO DNAME LOC
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

Largely inspired from xmlfiles.com

select from xml

My wife is so happy that an African president is ruling the world for the next four years !

Ok, here is a simple exercice :

How do you select from an HTML file ?

Take an example

The table of departments

10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON


create table T of XMLTYPE;

insert into T values(
XMLTYPE(
'


Employee table

The table of departments

10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON


'));

select deptno, dname, loc
from T t,
xmltable(‘/html/body/table/tr’
passing value(t) columns
deptno number path ‘/tr/td[1]’,
dname varchar2(10) path ‘/tr/td[2]’,
loc varchar2(10) path ‘/tr/td[3]’
);


DEPTNO DNAME LOC
---------- ---------- ----------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

xmltable is a 10gR2 features. For those with 9i, use TABLE(XMLSEQUENCE(EXTRACT(VALUE(t),’/html/body/table/tr’))) instead.

Note the html file must be in XHTML format, some rewritting may imply. SQLPLUS for example does not generate html files that are valid XHTML documents, for instance because of the <p> tags that to not have a </p> tag. Note that xml tags are case sensitive.

echo does not accept end of arguments operator

Let’s start with an example :

$ cat AI
#!/usr/bin/bash
while :
do
echo "What's your name ?"
read a
if [ ! $a ]
then
break
fi
echo "Your name is :"
echo $a
echo
done
echo "Bye"

$ ./AI
What's your name ?
Jo
Your name is :
Jo

What's your name ?
Jack
Your name is :
Jack

What's your name ?
-e
Your name is :

What's your name ?

Bye

This artificial intelligence is not very intelligent, it cannot recognize me if I am called “-e” (it is Friday, have a look at Little Bobby Tables ).

Most unix tools consider
-- signals the end of options and disables further option processing

But not echo πŸ™
$ touch -e
touch: invalid option -- e
Try `touch --help' for more information.
$ touch -- -e
$ ls -l -e
ls: invalid option -- e
Try `ls --help' for more information.
$ ls -l -- -e
-rw-r--r-- 1 lsc dba 0 Oct 31 15:44 -e
$ rm -e
rm: invalid option -- e
Try `rm ./-e' to remove the file `-e'.
Try `rm --help' for more information.
$ rm -- -e
$ echo -e

$ echo -- -e
-- -e

So, what’s the solution? well, probably not using “echo”, for example printf

$ (echo “What’s your name ?”
read a
echo “Your name is :”
printf “%s\n” “$a”)
What’s your name ?
-e
Your name is :
-e

Flying toasters and dense_rank

Have fun with this caps-lock user question :

asktom:Logic behind the DENSE_RANK

This is one more statement on how to not use order by

like in

select ename, deptno, row_number() over (order by 1)
from emp order by 2;
ENAME DEPTNO ROW_NUMBER()OVER(ORDERBY1)
---------- ---------- --------------------------
CLARK 10 1
KING 10 2
MILLER 10 3
JONES 20 4
FORD 20 5
ADAMS 20 6
SMITH 20 7
SCOTT 20 8
WARD 30 9
TURNER 30 10
ALLEN 30 11
JAMES 30 12
BLAKE 30 13
MARTIN 30 14

According to the doc, order by position is invalid. Actually, order by 1 is treated as order by ‘bananas’.
When used in an analytic function, the order_by_clause must take an expression (expr). The SIBLINGS keyword is not valid (it is relevant only in hierarchical queries). Position (position) and column aliases (c_alias) are also invalid. Otherwise this order_by_clause is the same as that used to order the overall query or subquery.

Thanks Tom for being so funny πŸ™‚

ⓕⓀⓝ β“¦β“˜β“£β“— β“€β“β“˜β“’β“žβ““β“”

Whether you need to write in Chinese אני אוהב אוΧͺך

Reverse your characters ʎuunɟ

Play some chess ♔ or do some maths β‰²βˆ€βˆƒβˆ„βˆ‘

Unicode can helps you. It can be stored in the database, in email, in plain-text files.

Read more :
– Unicode Home Page

Stored outlines

Note:
Performance Tuning Guide
Stored outlines will be desupported in a future release in favor of SQL plan management. In Oracle Database 11g Release 1 (11.1), stored outlines continue to function as in past releases. However, Oracle strongly recommends that you use SQL plan management for new applications. SQL plan management creates SQL plan baselines, which offer superior SQL performance and stability compared with stored outlines.


This said, let’s take a small example. If you have a query which is running fast most of the time and sometimes is running very slow due an unexpected plan change, you may want to considering enforcing plan stability with a Stored Outline.

To fake this example, let’s try to enforce a full table scan for select empno from emp where ename=’SCOTT’.

SQL> set autot on exp
SQL> select empno from emp where ename='SCOTT';
EMPNO
----------
7788

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1
1 0 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=1 By

For the purpose of this exercice, I consider this to be the right plan and I want to enforce Oracle to use this plan for this query.


SQL> create or replace outline o for category emp_scott on
select empno from emp where ename='SCOTT';

Outline created.

SQL> create unique index i on emp(ename)
tablespace my_slow_tape_drive;

Index created.

SQL> set timi on
SQL> set autot on exp
SQL> select empno from emp where ename='SCOTT';
EMPNO
----------
7788

Elapsed: 01:45:59.95

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' (Cost=2
2 1 INDEX (UNIQUE SCAN) OF 'I' (UNIQUE) (Cost=1

Oracle uses an index scan, but the index is located on a tape (which is not possible on 11gR1 and older πŸ˜‰ ) and it takes ages to complete the query. Let’s try to use the good plan that was used at the time we created the stored outline


SQL> alter session set use_stored_outlines=emp_scott;

Session altered.

Elapsed: 00:00:00.00
SQL> select empno from emp where ename='SCOTT';
EMPNO
----------
7788

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1
1 0 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=1 By

SQL> SELECT LAST_LOAD_TIME,OUTLINE_CATEGORY,sql_text
from v$sql
where sql_text like 'select%SCOTT%';
LAST_LOAD_TIME OUTLINE_C SQL_TEXT
------------------- --------- ----------------------------
2008-10-16/09:42:30 select empno from emp where
2008-10-16/09:46:50 EMP_SCOTT select empno from emp where

The plan using the outline is now used

where is my database link listed?


$ sqlplus scott/tiger@DEVL
SQL> select * from all_db_links;
no rows selected
SQL> select * from dual@PROD;
D
-
X

Hey, why does this work???

Ok, after some research I found out that this seems to be an implicit loopback database link. The fact that the DEVL database has the global name set to PROD is just to annoy more πŸ˜‰

SQL> select * from global_name;

GLOBAL_NAME
--------------------------------
PROD.LAURENTSCHNEIDER.COM

updatedb does not work with samba drives and cygwin

updatedb and locate are parts of the findutils package, which exists since a long time on most unix / linux flavors.

Something I never get worked is to search for files on network drives with Cygwin, I always got :

find: /cygdrive/y/Favorites/Links/del changed during execution of find (old inode number -474324984, new inode number -44545478
4, filesystem type is system) [ref 1114]
find: /cygdrive/y/Favorites/Links/del changed during execution of find (old inode number -513303800, new inode number -47432498
4, filesystem type is system) [ref 1114]

which is because the file system is mounted and unmounted on demand and get new inodes.

So I wrote a hack in /usr/bin/updatedb


# $find $NETPATHS $FINDOPTIONS …
# lschnei2
(
for d in c: y:
do
cd $d
/cygdrive/c/OS/system32/attrib /s
done
) |
sed ‘s,………..\(.\):,/cygdrive/\1,;y,\\,/,’ |
tr ‘\r’ ‘\0’ | tr -d ‘\n’

Then I can search efficiently


$ time updatedb

real 0m18.273s
user 0m3.806s
sys 0m7.332s

$ time locate hosts
/cygdrive/C/B28359_01/rac.111/b28252/img/cluster_hosts_table.gif
/cygdrive/C/B28359_01/rac.111/b28252/img_text/cluster_hosts_table.htm
/cygdrive/C/OS/system32/drivers/etc/hosts
/cygdrive/C/OS/system32/drivers/etc/lmhosts.sam
/cygdrive/Y/.ssh/known_hosts

real 0m0.261s
user 0m0.265s
sys 0m0.015s

Cycling

How to detect cycling records in 9i, remember CONNECT BY NOCYCLE does not exist in 9i


SQL> create table lsc_t as
2 select 1 parent, 2 child from dual
3 union all select 2,3 from dual
4 union all select 4,5 from dual
5 union all select 5,6 from dual
6 union all select 6,4 from dual;

Table created.

SQL> select parent,child
2 from lsc_t
3 where level=50
4 connect by parent=prior child
5 and level<=50 6 and prior dbms_random.value != dbms_random.value; PARENT CHILD ---------- ---------- 5 6 6 4 4 5

Ok, it is a bit abusing the connect by operator, but it is for hierarchic purpose :mrgreen:

Oracle Streams

If you have a datawarehouse and the data are getting to big for a full duplicate or tablespace transport, if you want to experience more about Streams or simply if you are in San Francisco and wants some distraction on Thursday after at 1pm, do not miss Chen session Oracle Streams – Live Demo

Oracle OpenWorld Unconference

11g release 1 patchset 1

I just notice on Sven Blog that 11.1.0.7 is available. I have recently upgraded my connection at home so it took a bit less than half an hour to download this 1.5G patchset


$ wget -O p6890831_111070_Linux-x86-64.zip http://oracle-updates.oracle…
–10:17:40– http://oracle-updates.oracle.com/ARUConnect/p6890831_111070_Linux-x86-64..
Resolving oracle-updates.oracle.com… 87.248.199.23, 87.248.199.24
Connecting to oracle-updates.oracle.com|87.248.199.23|:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 1,613,366,248 (1.5G) [application/zip]

100%[==================================>] 1,613,366,248 891.73K/s

10:47:31 (879.89 KB/s) – `p6890831_111070_Linux-x86-64.zip’ saved [1613366248/1613366248]

$ unzip p6890831_111070_Linux-x86-64.zip
$ cd Disk1
$ ./runInstaller
Starting Oracle Universal Installer…
Preparing to launch Oracle Universal Installer from
Oracle Universal Installer, Version 11.1.0.7.0 Production
Copyright (C) 1999, 2008, Oracle. All rights reserved.

$ su –
root’s password:
# /u00/app/oracle/product/11.1/db_1/root.sh
Running Oracle 11g root.sh script…
# exit
$ sqlplus / as sysdba
SQL*Plus: Release 11.1.0.7.0 – Production on Sat Sep 20 11:10:35 2008

Copyright (c) 1982, 2008, Oracle. All rights reserved.

Connected to an idle instance.

SQL> startup quiet migrate
ORACLE instance started.
Database mounted.
Database opened.
SQL> set time on
11:42:21 SQL> sho parameter sga_target

NAME TYPE VALUE
———————————— ———– ——————————
sga_target big integer 200M
11:42:25 SQL> alter system set sga_target=300m scope=spfile;

System altered.

11:42:28 SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
11:42:43 SQL> startup quiet migrate
ORACLE instance started.
Database mounted.
Database opened.
11:43:01 SQL> @?/rdbms/admin/catupgrd

11:54:03 SQL> Rem END catupgrd.sql
11:54:03 SQL> startup
ORACLE instance started.

Total System Global Area 313159680 bytes
Fixed Size 2159272 bytes
Variable Size 226495832 bytes
Database Buffers 79691776 bytes
Redo Buffers 4812800 bytes
Database mounted.
Database opened.
11:56:28 SQL> select comp_name,status,version from dba_registry;

COMP_NAME STATUS VERSION
———————————– ——– ———-
Oracle Ultra Search VALID 11.1.0.7.0
Oracle XML Database VALID 11.1.0.7.0
Oracle Text VALID 11.1.0.7.0
Oracle Expression Filter VALID 11.1.0.7.0
Oracle Rules Manager VALID 11.1.0.7.0
Oracle Workspace Manager VALID 11.1.0.7.0
Oracle Database Catalog Views VALID 11.1.0.7.0
Oracle Database Packages and Types VALID 11.1.0.7.0
JServer JAVA Virtual Machine VALID 11.1.0.7.0
Oracle XDK VALID 11.1.0.7.0
Oracle Database Java Packages VALID 11.1.0.7.0

My first try with 200Mb sga target did not succeeded. But with 300Mb sga target it worked fine.

About case sensitivity

SQL is a case insensitive language. That means, you can write any SQL statement in uppercase or lowercase.

SQL> SELECT DUMMY FROM DUAL;
D
-
X

SQL> select dummy from dual;
D
-
X

Some formatters like Toad and some courseware like Skillsoft E-Learning advise to use UPPERCASE for commands and lowercase for tables and columns.


/* Formatted on 2008/09/19 10:00
(Formatter Plus v4.8.8) */
SELECT dummy
FROM DUAL;

Well, Toad decided to put DUAL in uppercase. Anyway, this is no authority, define your own guideline and stick to it. If you use TOAD a lot, it is maybe OK to use lowercase for non-keywords.

The column dummy is actually the uppercase “DUMMY” column of “DUAL”. Putting double quotes around a column of table makes it case sensitive, so “DUMMY” is not “dummy”.

SQL> select "dummy" from "dual";
select "dummy" from "dual"
*
Error at line 1
ORA-00942: table or view does not exist

SQL> SELECT "DUMMY" FROM "DUAL";
D
-
X

OK, something very bad about Toad formatter is (at least the version I am using) that it considers unquoted password to be case insensitive. Which is wrong. The password, in 11g, is case sensitive, even when not in double quotes. Therefore, be sure to put the right case when creating scripts and do not format your CREATE USER statements with Toad or use double quotes for disambiguation!

SQL> ALTER USER scott IDENTIFIED BY BIG;
User altered.
SQL> connect scott/BIG
Connected.
SQL> /* Formatted on 2008/09/19 10:17 (Formatter Plus v4.8.8) */
SQL> ALTER USER scott IDENTIFIED BY big;
SQL> connect scott/BIG
ERROR:
ORA-01017: invalid username/password; logon denied
Warning: You are no longer connected to ORACLE.

Hey, we have a journeyman !

Congrats to Denes Kubicek for being the first journeyman on OTN.

OTN stars Justin and Nicolas (18954 and 15321 posts) do not get this title, as we Oracle Ace are sticked to our Ace logos. OTN upgraded the forums recently, many posts about this :

  • OTN Forums – Change the look and feel yourself
  • OTN Forums Update – Take Two
  • New OTN Forums – not great yet
  • OTN forums get a new look
  • OTN Forums Upgrade
  • Forums.oracle.comUpgrade: New Rewards System/Known Issues
  • In the last link, Justin explains the new ranking system. Aces are aces, and everyone else but Denes are newbies πŸ˜‰

    Ow, I forget, they got smileys too

    Happy :)
    Sad :(
    Grin :D
    Love :x
    Mischief ;\
    Cool B-)
    Devil ]:)
    Silly :p
    Angry X-(
    Laugh :^0
    Wink ;)
    Blush :8}
    Cry :_|
    Confused ?:|
    Shocked :0
    Plain :|

    puzzled by Toad

    one colleague just showed me how to insert duplicate rows in a table that has a primary key.


    create table t(x number primary key);[F5]
    Table created.
    insert into t values (1);[F5]
    1 row created.
    insert into t values (1);[F5]
    1 row created.

    Hey, what happened? It took me quite a while to figure out which feature of Toad was “allowing” this.

    Let’s look at Toad.ini (or View – ToadOptions – Transaction)

    [SETTINGS]
    ALWAYSROLLBACK=1
    THREADQUERIES=1

    Which means, Toad is starting a separate session each time a query is run (by F5 for instance) and at the end of this child session, it rollbacks. This is not the default, but this is pure magic!

    Let’s prove it :

    select count(*) from t where x=1;[F5]

    COUNT(*)
    ----------
    0

    1 row selected.

    :mrgreen:

    what is faster, select count(*) or select count(pk) ?

    Oh no, not another post about COUNT(*) and COUNT(1) :mrgreen:

    Well, it is not exactly the case. I just had the issue this morning that count(*) was too slow.


    SQL> create table t as select rownum id,
    2 lpad('a',4000,'a') a,
    3 lpad('b',4000,'b') b,
    4 lpad('c',4000,'c') c,
    5 lpad('d',4000,'d') d
    6 from dual connect by level<10000; Table created. SQL> create index i on t(id);

    Index created.

    SQL> alter table t add primary key (id)
    2 using index i disable novalidate;

    Table altered.

    SQL> exec dbms_stats.gather_table_stats(user,'T')

    PL/SQL procedure successfully completed.

    SQL> exec dbms_stats.gather_index_stats(user,'I')

    PL/SQL procedure successfully completed.

    SQL> set timi on
    SQL> select count(id) from t;

    COUNT(ID)
    ----------
    9999

    Elapsed: 00:00:00.01
    SQL> select count(*) from t;

    COUNT(*)
    ----------
    9999

    Elapsed: 00:00:01.43

    My count(*) just takes too long… Why that?

    I have no index on a not null column. The primary key is disabled.

    Of course the count(pk) does not count the rows with pk=null, but it is faster πŸ™‚

    Difference between rollbac and rollback

    What is the difference between rollbac and rollback?


    SQL> create table t as select 1 x from dual;

    Table created.

    SQL> update t set x=2;

    1 row updated.

    SQL> savepoint a;

    Savepoint created.

    SQL> update t set x=3;

    1 row updated.

    SQL> rollbac to savepoint a;
    Rollback complete.
    SQL> select * from t;
    X
    ----------
    1

    WTF! rollbac does not seem to work correctly πŸ˜‰

    Actually, ROLL, ROLLB, ROLLBA and ROLLBAC are not valid SQL statements. However, SQLPLUS recognizes it a sqlplus statement but this behavior is not documented.


    SQL> del *
    SQL> roll
    Rollback complete.
    SQL> list
    SP2-0223: No lines in SQL buffer.

    The statement does not end with semi-column and is not stored in the SQLPLUS buffer.

    So it is not a SQL command.

    read uncommitted

    the default isolation level is READ COMMITTED. It means, a session read the committed data.

    Session 1:

    SQL> set transaction isolation level read committed;

    Transaction set.

    Session 2:

    SQL> update emp set sal=4000 where ename='SCOTT';

    1 row updated.

    Session 1:

    SQL> select sal from emp where ename='SCOTT';

    SAL
    ----------
    3000

    Session 2:

    SQL> commit;
    Commit complete.

    Session 1:

    SQL> select sal from emp where ename='SCOTT';

    SAL
    ----------
    4000
    SQL> update emp set sal=3000 where ename='SCOTT';

    1 row updated.

    SQL> commit;
    Commit complete.

    When the session 1 reads the salary of Scott, it gets the value that is committed in the database.

    Another isolation level is SERIALIZABLE.

    Session 1:

    SQL> set transaction isolation level serializable;

    Transaction set.

    Session 2:

    SQL> update emp set sal=5000 where ename='SCOTT';

    1 row updated.

    SQL> commit;

    Commit complete.

    Session 1:

    SQL> select sal from emp where ename='SCOTT';

    SAL
    ----------
    3000

    SQL> update emp set sal=sal+1;
    update emp set sal=sal+1
    *
    ERROR at line 1:
    ORA-08177: can't serialize access for this transaction
    SQL> roll
    Rollback complete.
    SQL> select sal from emp where ename='SCOTT';

    SAL
    ----------
    5000

    SQL> update emp set sal=3000 where ename='SCOTT';

    1 row updated.

    SQL> commit;

    Commit complete.

    In session 1, the isolation level of the transaction is set to SERIALIZABLE. Session 2 update the salary of Scott to 5000 and commits. The session 1 therefore does not read committed data and any tentative to change the committed data will fail. Roll[back;] ends the transaction. The session 1 can then read committed data and update the salary to 3000.

    Ok, let’s imagine you have to interview an OCM and you want to ask him a very difficult question πŸ˜‰ :

    – Is it possible in Oracle to read uncommitted data from another session?

    Let’s try πŸ™‚

    Session 1:

    SQL> var rc number
    SQL> set autop on
    SQL> select sal from emp where ename='SCOTT';

    SAL
    ----------
    3000

    SQL> exec :rc:=DBMS_XA.XA_START(DBMS_XA_XID(1),
    DBMS_XA.TMNOFLAGS)

    PL/SQL procedure successfully completed.

    RC
    ----------
    0

    SQL>
    SQL> UPDATE emp SET sal=6000 WHERE ename='SCOTT';

    1 row updated.

    SQL> exec :rc:=DBMS_XA.XA_END(DBMS_XA_XID(1),
    DBMS_XA.TMSUSPEND)

    PL/SQL procedure successfully completed.

    RC
    ----------
    0

    Session 2:

    SQL> select sal from emp where ename='SCOTT';

    SAL
    ----------
    3000

    SQL> var sal number
    SQL> var rc number
    SQL> set autop on
    SQL> begin
    :rc:=DBMS_XA.XA_START(DBMS_XA_XID(1),DBMS_XA.TMRESUME);
    SELECT SAL INTO :SAL FROM EMP WHERE ENAME='SCOTT';
    :rc:=DBMS_XA.XA_END(DBMS_XA_XID(1), DBMS_XA.TMSUCCESS);
    :rc:=DBMS_XA.XA_ROLLBACK(DBMS_XA_XID(1));
    end;
    /

    PL/SQL procedure successfully completed.

    SAL
    ----------
    6000

    RC
    ----------
    0

    SQL> select sal from emp where ename='SCOTT';

    SAL
    ----------
    3000

    So yes, you can read uncommitted data in a global transaction from another session. But no, the SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED is not supported in Oracle

    return size of to_char

    The width of a columns is known before execution.

    Well, in most cases…


    SELECT TO_CHAR(SYSDATE,'DAY','NLS_DATE_LANGUAGE=FRENCH')
    FROM DUAL;
    TO_CHAR(
    --------
    SAMEDI

    The length is as most 8 characters (VENDREDI). Therefore the width of the column is 8.


    SELECT TO_CHAR(SYSDATE,'YEAR') FROM DUAL;
    TO_CHAR(SYSDATE,'YEAR')
    ------------------------------------------
    TWO THOUSAND EIGHT

    Oracle thinks the length is at most 42 characters. This is a bad guess, the year 7777 is the longest to spell and is only 27 characters. So the width is 42.

    SELECT TO_CHAR(SYSDATE,'JSP') FROM DUAL;
    TO_CHAR(SYSDATE,'JSP')
    ---------------------------------------------------------
    ---------------------
    TWO MILLION FOUR HUNDRED FIFTY-FOUR THOUSAND SIX HUNDRED
    EIGHTY-EIGHT

    again, this is a bad guess, the maximum length of a spelled Julian day is 77 (May 9, 4388) not 78.

    let’s try with spelling the nanoseconds :

    select to_char(current_timestamp,'FF9SP') from dual;
    TO_CHAR(CURRENT_TIMESTAMP,'FF9SP')
    -------------------------------------------------------
    -----------------------
    SEVENTY-FOUR MILLION

    here 78 is a really bad guess… the nanoseconds could be 100 character long !

    What happened then :

    select to_char(timestamp '0001-01-01 00:00:00.777777777',
    'FFSP') from dual;
    select to_char(timestamp '0001-01-01 00:00:00.777777777',
    *
    ERROR at line 1:
    ORA-01877: string is too long for internal buffer

    The query fails. Does it means the maximum length returned by TO_CHAR is 78? Not at all!

    It simply means Oracle sets the width column to something too small to contain the result.

    By setting the column to something longer, the query should work…

    select cast(to_char(timestamp '0001-01-01 00:00:00.
    777777777','FFSP') as varchar2(100)) from dual;
    CAST(TO_CHAR(TIMESTAMP'0001-01-0100:00:00.777777777','FFSP')
    ------------------------------------------------------------
    ASVARCHAR2(100))
    ----------------------------------------
    SEVEN HUNDRED SEVENTY-SEVEN MILLION SEVEN HUNDRED SEVENTY-
    SEVEN THOUSAND SEVEN HUNDRED SEVENTY-SEVEN

    Ok, let’s do something perverse :mrgreen:

    Let set the CURSOR_SHARING to FORCE !

    Have a look :


    SQL> alter session set cursor_sharing='FORCE';

    Session altered.

    SQL> select to_char(to_date(1000000,'J'),'JSP') from dual;
    TO_CHAR(TO_DATE(1000000,'J'),'JSP')
    ----------------------------------------------------------
    -----------------
    ONE MILLION

    the width of the column is evaluated to 75. 75 however is not the maximum length!


    SQL> select to_char(to_date(1777777,'J'),'JSP') from dual;
    select to_char(to_date(1777777,'J'),'JSP') from dual
    *
    ERROR at line 1:
    ORA-01801: date format is too long for internal buffer

    Not only CURSOR_SHARING=FORCE influence the output of the query, but it also make the SQL failing.

    Let’s revert to EXACT for confirmation.

    SQL> alter session set cursor_sharing='EXACT';

    Session altered.

    SQL> select to_char(to_date(1000000,'J'),'JSP') from dual;
    TO_CHAR(TO_
    -----------
    ONE MILLION

    SQL> select to_char(to_date(1777777,'J'),'JSP') from dual;
    TO_CHAR(TO_DATE(1777777,'J'),'JSP')
    --------------------------------------------------------------
    --------------
    ONE MILLION SEVEN HUNDRED SEVENTY-SEVEN THOUSAND SEVEN HUNDRED
    SEVENTY-SEVEN

    SET LONGCHUNKSIZE

    I noticed a side effect of SET LONGC today…

    The default setting for LONG and LONGC is 80. This is quite annoying when you SELECT TEXT FROM ALL_VIEWS as it truncates the text to 80.

    So why not setting it to the maximum?

    Let’s first demo the usage of LINESIZE, LONG and LONGCHUNKSIZE

    SQL> create view v as select
    '12345678910111213141516171819202' x
    from dual;

    View created.

    SQL> set lin 80 long 20 longc 20
    SQL> select text from user_views where view_name='V';

    TEXT
    --------------------
    select '123456789101

    SQL> set lin 80 long 1000000000 longc 20
    SQL> select text from user_views where view_name='V';

    TEXT
    --------------------
    select '123456789101
    11213141516171819202
    ' x from dual

    SQL> set lin 80 long 1000000000 longc 1000000000
    SQL> select text from user_views where view_name='V';

    TEXT
    -----------------------------------------------------
    select '12345678910111213141516171819202' x from dual

    When I use a LONG setting smaller than the length of the TEXT column, I got it truncated. When I use a huge LONG setting but a LONGCHUNKSIZE setting smaller than the length of the TEXT column, I got it wrapped. When both are huge, it seems I am getting the expecting result. So why not setting SET LONG 2000000000 LONGC 2000000000 in your login.sql ?

    Have a look :


    SQL> SET LONG 10 LONGC 10 LIN 80 TIMI ON
    SQL> SELECT TO_CLOB('X') FROM DUAL;

    TO_CLOB('X
    ----------
    X

    Elapsed: 00:00:00.01
    SQL> SET LONG 1000000 LONGC 1000000 LIN 80 TIMI ON
    SQL> SELECT TO_CLOB('X') FROM DUAL;

    TO_CLOB('X')
    ------------
    X

    Elapsed: 00:00:00.00
    SQL> SET LONG 1000000000 LONGC 1000000000 LIN 80 TIMI ON
    SQL> SELECT TO_CLOB('X') FROM DUAL;

    TO_CLOB('X')
    ------------
    X

    Elapsed: 00:00:02.06

    2 seconds to select 1 character from dual !

    I also tried to set it to 2000000000 but since I do not have 2Gb of free memory my notebook started swapping so badly I could not even move my mouse πŸ™

    certification blog

    I just notice a new blog on blogs.oracle.com :
    Oracle Certification Blog

    This is probably the right place to ask questions or get news about certification.

    Out of the many questions I may ask here are just a few I am preparing.

    – When will the OCM upgrade for 9i OCM be available ?
    – When will be the 9i exams retired ?
    – ocm upgrade : 10g upgrade has not been finalized yet. Why ?
    – What is the expected date for 11g OCM ?

    Ok, I have add this blog to my feed and will start posting comments soon …

    secondmax

    How do I retrieve the second highest salary of emp?

    There is no right or wrong treatment of duplicates, there are only buggy specifications…

    There are plenty of ways to do this.

    An Oracle 7 approach would be

    SELECT MAX(SAL) 
    FROM EMP, (
      SELECT MAX(SAL) MAXSAL FROM EMP) 
    WHERE SAL>MAXSAL;
    

    Using TOP-n queries I could use

     
    SELECT SAL 
    FROM (
      SELECT ROWNUM R,SAL FROM (
        SELECT SAL FROM EMP ORDER BY SAL DESC)) 
    WHERE R=2;
    

    Using ROW_NUMBER (or RANK or DENSE_RANK), I could use

    SELECT SAL 
    FROM (
      SELECT ROW_NUMBER() OVER (ORDER BY SAL DESC) R,SAL FROM EMP) 
    WHERE R=2;
    

    Another approach would be to create a SecondMax aggregate function, as the following example from the doc
    Example 11-12 How to Create and Use a User-Defined Aggregate Function

    SELECT SecondMax(sal)
    FROM emp;
    

    Ok, if I know I have 14 employees in EMP, retrieving the second highest is way easier πŸ™‚

    SELECT PERCENTILE_DISC(2/14) WITHIN GROUP (ORDER BY SAL DESC) 
    FROM EMP;
    

    Start Oracle in Vista with one click

    I have been using Vista for about 3 months and finally found a way to start my databases with a single click πŸ™‚

    The method I used until yesterday was a .BAT file that starts the services, I had then to right click on the shortcut, run as administrator, confirm the UAC warning. 3 Clicks. Way to much…

    I have googled quite a lot and found Vista setuid – How to elevate without prompting

    Ok, here we go :

    1) run mmc
    2) file – add snapin
    3) Task Scheduler Library – Create Task
    4) Name: startoracle
    Run with highest privileges
    Actions – New – Start a program – Program:net – Arguments: start OracleOraDb11g_home1TNSListener
    Actions – New – Start a program – Program:net – Arguments: start OracleServiceLSC01
    Actions – New – Start a program – Program:net – Arguments: start OracleServiceLSC02

    5) create a batch file that runs : schtasks /run /tn startoracle

    Same for stoporacle

    It seems to work fine. Do not play too much with mmc if you do not know it. It is a powerful tool ❗