oracle tips
===========================================================
Problem to connect as SYSDBA(zt from asktom)
===========================================================
Hi there,

I am running Oracle 8.1.7 EE on SUN Solaris. I created two databases
SUGAR and TestDb (I need one to do some testing). Both are set
remote_login_passwordfile = exclusive. The following shows how I had trouble to
connect as SYSDBA. The big problem is that I cannot connect to TestDb as SYSDBA.

$sqlplus /nolog
SQL> conn sys/change_on_install@testdb
connected
SQL> select * from v$pwfile_users;
username sysdb sysop
------------------------------
internal true true
sys true true
SQL> conn sys/change_on_install@testdb as sysdba
ERROR
ORA-01017: invalid username/password; logon denied
Warning: You are on longer connected to ORACLE
SQL> conn sys/change_on_install@SUGAR
connected
SQL> select * from v$pwfile_users;
username sysdb sysop
------------------------------
internal true true
sys true true
SQL> conn sys/change_on_install@SUGAR as sysdba
ERROR
ORA-01017: invalid username/password; logon denied
Warning: You are on longer connected to ORACLE
SQL> conn sys/change_on_install as sysdba
connected
SQL> select name from v$database;
name
------
SUGAR

Questions:
1. Why "conn sys/change_on_install@testdb/sugar as sysdba" always failed, but
"conn sys/change_on_install as sysdba" OK ?

2. Why I cannot connect to testdb as SYSDBA?

Thanks for any help.
and we said...
what was the password you used when you created the password file and have you 
tried that?

the sysdba trick is generally used to allow other NON-SYS users to connect btw,
best to use your OWN account that has been granted sysdba!

Anyway, hopeful this will clear up the confusion and show how this works:

$ orapwd file=orapw password=foobar entries=40

I just recreated my password file with a password foobar. My sys password is
NOT foobar


$ svrmgrl

SVRMGR> connect internal
Connected.

SVRMGR> startup
ORACLE instance started.
Total System Global Area 193073136 bytes
Fixed Size 69616 bytes
Variable Size 141639680 bytes
Database Buffers 45056000 bytes
Redo Buffers 6307840 bytes
Database mounted.
Database opened.

SVRMGR> connect sys/change_on_install@ora816dev
Connected.

that works OK, lets try as sysdba:

SVRMGR> connect sys/change_on_install@ora816dev as sysdba;
ORA-01017: invalid username/password; logon denied

there I got your error. My SYS password is change_on_install but the password
file has foobar in it. SYS is special -- sys connecting as sysdba is like
internal -- you have to use the password file password! Lets try that:


SVRMGR> connect sys/foobar@ora816dev as sysdba;
Connected.

SVRMGR> grant sysdba to scott;
Statement processed.

now, we'll see this does not hold true for other users:

SVRMGR> connect scott/tiger@ora816dev as sysdba;
Connected.

That worked great, now lets just modify sys's password (not really, didn't
change it but Oracle won't notice that


SVRMGR> alter user sys identified by change_on_install;
Statement processed.

SVRMGR> connect sys/change_on_install@ora816dev as sysdba;
Connected.
SVRMGR>
Hey, now we can use change_on_install -- that is because altering SYS's
password will sync up the password in the password file -- sys is a very very
close cousin of INTERNAL. sys's password will be burned into the password file
now. the password foobar is obsolete


SVRMGR> connect sys/foobar@ora816dev as sysdba;
ORA-01017: invalid username/password; logon denied
SVRMGR>

jametong 发表于:2005.06.14 16:04 ::分类: ( oracle refs ) ::阅读:(6231次) :: 评论 (46)
===========================================================
relation between consistent gets and arraysize(zt from asktom)
===========================================================
Consistenet gets is based upon re-constructing a block
for consistent read. Hence it is a function of only the
number of db_blocks to be read.
If you say that it is altered by the arraysize, do you
suggest that, due to arraysize, some blocks are read
muliple times and hence some blocks have > 1 
consistent read in the process
Thanks 
Followup:
No, you are wrong in your statement.
A consistent get is a block gotten in read consistent mode (point in time mode).  It MAY or MAY NOT involve reconstruction (rolling back).
Db Block Gets are CURRENT mode gets -- blocks read "as of right now".

Some blocks are processed more then once, yes, the blocks will have more then 1 
consistent read in the process.  Consider:

ops$tkyte@ORA817DEV.US.ORACLE.COM> create table t as select * from all_objects;
Table created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> exec show_space( 'T')
Free Blocks.............................0
Total Blocks............................320
Total Bytes.............................2621440
Unused Blocks...........................4
Unused Bytes............................32768
Last Used Ext FileId....................7
Last Used Ext BlockId...................40969
Last Used Block.........................60
PL/SQL procedure successfully completed.
Table has 316 blocks, 22,908 rows..

ops$tkyte@ORA817DEV.US.ORACLE.COM> set autotrace traceonly statistics;
ops$tkyte@ORA817DEV.US.ORACLE.COM> set arraysize 15
ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from t;
22908 rows selected.
here with an array size of 15, we expect
22908/15 + 316 = 1843 consistent mode gets.  db block gets -- they were for 
performing the FULL SCAN, they had nothing to do with the data itself we 
selected

Statistics
----------------------------------------------------------
          0  recursive calls
         12  db block gets
       1824  consistent gets
        170  physical reads
          0  redo size
    2704448  bytes sent via SQL*Net to client
     169922  bytes received via SQL*Net from client
       1529  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      22908  rows processed
ops$tkyte@ORA817DEV.US.ORACLE.COM> set arraysize 100
ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from t;
22908 rows selected.
Now, with 100 as the arraysize, we expect
22908/100 + 316 = 545 consistent mode gets.
Statistics
----------------------------------------------------------
          0  recursive calls
         12  db block gets
        546  consistent gets
        180  physical reads
          0  redo size
    2557774  bytes sent via SQL*Net to client
      25844  bytes received via SQL*Net from client
        231  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      22908  rows processed
ops$tkyte@ORA817DEV.US.ORACLE.COM> set arraysize 1000
ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from t;
22908 rows selected.
now, with arraysize = 1000, we expect:
22908/1000+316 = 338 consistent mode gets...
Statistics
----------------------------------------------------------
          0  recursive calls
         12  db block gets
        342  consistent gets
        222  physical reads
          0  redo size
    2534383  bytes sent via SQL*Net to client
       2867  bytes received via SQL*Net from client
         24  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      22908  rows processed

so yes, the blocks are gotten in consistent mode MORE THEN ONCE when the array 
fetch size is lower then the number of rows to be retrieved in this case
This is because we'll be 1/2 way through processing a block -- have enough rows 
to return to the client -- and we'll give UP that block.  When they ask for the 
next N rows, we need to get that halfway processed block again and pick up where 
we left off.
 

jametong 发表于:2005.06.07 09:03 ::分类: ( oracle refs ) ::阅读:(29617次) :: 评论 (550)
===========================================================
about tune db cache
===========================================================
i have 8174 db.
how can i know that i have the db buffer too small?
thanks

Followup:
trick question.

you have to first make sure your SQL is as good as it gets (reduce the number of
LIO's your sql does).

Then, you need to understand if a sql cache of any size can cache some
percentage of your data (maybe it can, maybe it can't)

Then you can look at ratio to see if you have a satisfactory hit.


But basically, you want to look at what you system is waiting for. Not waiting
on physical IO? then your cache is at least big enough. Waiting on physical
IO? DO NOT INCREASE YOUR BUFFER CACHE FIRST, rather look at your top SQL, if
you have a query that is executed lots and returns like 2 rows but does 100
LIO's to do it -- you need to look at that ( i would hope for single digit IO's
for a popular query that returns 2 rows). do you have a popular query that just
does a ton of LIO's (regardless of the rows) -- why? can you do anything about
it? if so -- fix it.

Then, you might find that your buffer cache is just fine after all (watch the
LIO's and the PIO's will take care of themselves).

Increasing the buffer cache to help a PIO problem is the last step -- you want
to exhaust other avenues first (more efficient sql, better algorithms, quit
running stuff you don't really need to run, that sort of stuff -- they'll give
you the big payoff. increasing the buffer cache doesn't always have the same
potential as those approaches)



jametong 发表于:2005.05.19 18:34 ::分类: ( oracle refs ) ::阅读:(1170次) :: 评论 (4)
===========================================================
DIFFERENCES BETWEEN PROCESSES, SESSIONS AND CONNECTIONS(zt from asktom)
===========================================================
-- Thanks for the question regarding "DIFFERENCES BETWEEN PROCESSES, SESSIONS AND CONNECTIONS", version 8.1.7.4
originally submitted on 28-Sep-2002 10:19 Eastern US time, last updated 27-Apr-2005 16:37

You Asked
Hi Tom

What's the difference between connections, sessions and processes?

I read a note from Metalink about the difference but I simply dont get it!

May you give a brief explanation?

Thank you
and we said...
A process is a physical process or thread.

On unix, you can see a process with "ps" for example. It is there.

There are many types of processes in Oracle -- background processes like SMON,
PMON, RECO, ARCH, CKPT, EMNn, DBWR, etc..... And user processes like dedicated
servers or shared server (multi-threaded server -- aka MTS -- configuration)


A connection is a "physical circuit", a pathway to a database. You can be
connected to a database yet have 0 or 1 or MORE sessions going on that
connection. We can see that with sqlplus, consider (single user system here,
its all about me)


[tkyte@tkyte-pc-isdn tkyte]$ ps -auxww | grep oracleora920
[tkyte@tkyte-pc-isdn tkyte]$ sqlplus /nolog

SQL*Plus: Release 9.2.0.1.0 - Production on Sat Sep 28 10:36:03 2002

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

idle> !ps -auxww | grep oracleora920
tkyte 19971 0.0 0.1 2196 916 pts/1 S 10:36 0:00 /bin/bash -c ps
-auxww | grep oracleora920
tkyte 19973 0.0 0.1 1736 564 pts/1 S 10:36 0:00 grep oracleora920

no process, no nothing

idle> connect /
Connected.
idle> !ps -auxww | grep oracleora920
ora920 19974 1.5 2.2 230976 11752 ? S 10:36 0:00 oracleora920
(DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
tkyte 19975 0.0 0.1 2196 916 pts/1 S 10:36 0:00 /bin/bash -c ps
-auxww | grep oracleora920
tkyte 19977 0.0 0.1 1736 564 pts/1 S 10:36 0:00 grep oracleora920

got my process now...

idle> disconnect
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production
idle> !ps -auxww | grep oracleora920
ora920 19974 0.6 2.3 230976 11876 ? S 10:36 0:00 oracleora920
(DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
tkyte 19978 0.0 0.1 2196 916 pts/1 S 10:36 0:00 /bin/bash -c ps
-auxww | grep oracleora920
tkyte 19980 0.0 0.1 1736 564 pts/1 S 10:36 0:00 grep oracleora920

idle> select * from dual;
SP2-0640: Not connected

still have my process, but no session, the message is a little "misleading".
Technically -- I have a connection, I don't have a session



further, autotrace in sqlplus can be used to show that you can have
a) a connection
b) that uses a single process
c) to service two sessions:


ops$tkyte@ORA920.US.ORACLE.COM> select username from v$session where username is
not null;

USERNAME
------------------------------
OPS$TKYTE

one session, ME

ops$tkyte@ORA920.US.ORACLE.COM> select username, program from v$process;

USERNAME PROGRAM
--------------- ------------------------------------------------
PSEUDO
ora920 oracle@tkyte-pc-isdn.us.oracle.com (PMON)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (DBW0)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (LGWR)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (CKPT)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (SMON)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (RECO)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (CJQ0)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (QMN0)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (S000)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (D000)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (ARC0)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (ARC1)
tkyte oracle@tkyte-pc-isdn.us.oracle.com (TNS V1-V3)

14 rows selected.

you can see all of the backgrounds and my dedicated server...

ops$tkyte@ORA920.US.ORACLE.COM> set autotrace on statistics;

Autotrace for statistics uses ANOTHER session so it can query up the stats for
your CURRENT session without impacting the STATS for that session!

/* 这种情况有几个人注意过啊^_^ 我是没有发现过.. */

ops$tkyte@ORA920.US.ORACLE.COM> select username from v$session where username is
not null;

USERNAME
------------------------------
OPS$TKYTE
OPS$TKYTE


see, two sessions but....

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
418 bytes sent via SQL*Net to client
499 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2 rows processed

ops$tkyte@ORA920.US.ORACLE.COM> select username, program from v$process;

USERNAME PROGRAM
--------------- ------------------------------------------------
PSEUDO
ora920 oracle@tkyte-pc-isdn.us.oracle.com (PMON)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (DBW0)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (LGWR)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (CKPT)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (SMON)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (RECO)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (CJQ0)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (QMN0)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (S000)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (D000)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (ARC0)
ora920 oracle@tkyte-pc-isdn.us.oracle.com (ARC1)
tkyte oracle@tkyte-pc-isdn.us.oracle.com (TNS V1-V3)

14 rows selected.

same 14 processes...

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
1095 bytes sent via SQL*Net to client
499 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
14 rows processed

ops$tkyte@ORA920.US.ORACLE.COM>


I'll try to put it into a single, simple paragraph:

A connection is a physical circuit between you and the database. A connection
might be one of many types -- most popular begin DEDICATED server and SHARED
server. Zero, one or more sessions may be established over a given connection
to the database as show above with sqlplus. A process will be used by a session
to execute statements. Sometimes there is a one to one relationship between
CONNECTION->SESSION->PROCESS (eg: a normal dedicated server connection).
Sometimes there is a one to many from connection to sessions (eg: like
autotrace, one connection, two sessions, one process). A process does not have
to be dedicated to a specific connection or session however, for example when
using shared server (MTS), your SESSION will grab a process from a pool of
processes in order to execute a statement. When the call is over, that process
is released back to the pool of processes.



jametong 发表于:2005.04.28 10:06 ::分类: ( oracle refs ) ::阅读:(4366次) :: 评论 (41)
===========================================================
Calling Export from Pl/sql using C external proc
===========================================================
http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:1993409963502

Sudee -- Thanks for the question regarding "Calling Export from Pl/sql using C external proc.", version 8.1.6
originally submitted on 16-Nov-2001 20:55 Eastern US time, last updated 27-Apr-2005 9:31

You Asked
Hi Tom,

Is there anything wrong with these steps,
the exp does not create a .dmp file.

Thanks


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

__declspec(dllexport) void sh(char *);

void sh( char *cmd )
{
int num;

num = system(cmd);
}


CREATE LIBRARY shell_lib is 'C:oracleextprocshell.dll';


create or replace procedure shell (
cmd IN char)
as external
name "sh"
library shell_lib
language C
parameters (
cmd string);

exec shell('C:oracleora81binexp userid=system/manager
file=C:oracleextproctest.dmp full=y rows=N');
and we said...
Ok, this is easily solved.  What I'll do however is show you the steps I went 
thru to diagnose this.

Step 1, after building the example, I tested it with something "non-oracle" --
to eliminate that from the mix. I have a program "touch.exe" which when
executed simply updates the timestamp on a file in the OS and if the file does
not exist, it creates hence.

Hence I ran "exec shell( c:bintouch c:temptest.dat" );"

Sure enough, the file test.dat appeared -- proving the extproc itself functions.

Then I tried export -- sure enough, that DID NOT work.

Step 2, lets capture the output. In order to diagnose this (and in order to be
able to verify the export actually WORKED) we need to capture the output. Using
SYSTEM, the easiest way is:


tkyte@TKYTE816> host erase tempexp.log
tkyte@TKYTE816> begin
2 shell( 'c:oraclebinexp userid=scott/tiger ' ||
3 ' file=c:temptest.dmp tables=emp 2> tempexp.log' );
4 end;
5 /

PL/SQL procedure successfully completed.


that would not only run our command but it would also redirect stderr to a file
we can look at. When I ran that, I saw clearly what the issue was:


tkyte@TKYTE816> host type tempexp.log

Export: Release 8.1.6.0.0 - Production on Sat Nov 17 13:02:35 2001

(c) Copyright 1999 Oracle Corporation. All rights reserved.


EXP-00056: ORACLE error 12560 encountered
ORA-12560: TNS:protocol adapter error
EXP-00000: Export terminated unsuccessfully

So, it is simply not able to connect (it in fact was running exp -- you just had
no way to see the output from exp and now you do). So, once we have that -- we
can go the next step. Well, I would really like to see the environment cause
12560 is almost always an environment issue. At this point, I stop running exp
and just run SET to see whats the environment looks like:

tkyte@TKYTE816> host erase tempexp.log

tkyte@TKYTE816>
tkyte@TKYTE816> begin
2 shell( 'command /c set > tempexp.log' );
3 end;
4 /

PL/SQL procedure successfully completed.

tkyte@TKYTE816> host type tempexp.log
COMSPEC=C:WINNTSYSTEM32COMMAND.COM
ORACLE_SID=extproc

ALLUSERSPROFILE=C:DOCUME~1ALLUSE~1
COMMONPROGRAMFILES=C:PROGRA~1COMMON~1
COMPUTERNAME=TKYTE-DELL
JSERV=C:oracle9i/Apache/Jserv/conf
NUMBER_OF_PROCESSORS=1
OLAP_HOME=C:oracle9iolap
OS=Windows_NT
OS2LIBPATH=C:WINNTsystem32os2dll;
PATH=C:oraclebin;C:oracle9ibin;C:orantbin;C:oracle9i/bin;C:oracle9iApach
ePerl
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 8 Stepping 3, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=0803
PROGRAMFILES=C:PROGRA~1
PROMPT=$P$G
SYSTEMDRIVE=C:
SYSTEMROOT=C:WINNT
TEMP=C:WINNTTEMP
TMP=C:WINNTTEMP
USERPROFILE=C:DOCUME~1DEFAUL~1
WV_GATEWAY_CFG=C:oracle9iApachemodplsqlcfgwdbsvr.app

Well, there is the problem in this case -- we are using the EXTPROC service, so
the ORACLE_SID is in fact "extproc".

At this point, we have a couple of choices, two of which I have below - one we
can use Net8:

tkyte@TKYTE816> host erase tempexp.log

tkyte@TKYTE816>
tkyte@TKYTE816> begin
2 shell( 'c:oraclebinexp userid=scott/tiger@tkyte816 ' ||
3 ' file=c:temptest.dmp tables=emp 2> tempexp.log' );
4 end;
5 /

PL/SQL procedure successfully completed.

tkyte@TKYTE816> host type tempexp.log

Export: Release 8.1.6.0.0 - Production on Sat Nov 17 13:05:36 2001

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.6.0.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
Export done in WE8ISO8859P1 character set and WE8ISO8859P1 NCHAR character set

About to export specified tables via Conventional Path ...
. . exporting table EMP 14 rows exported
Export terminated successfully without warnings.



The other is to run more than one command:

tkyte@TKYTE816> host erase tempexp.log

tkyte@TKYTE816>
tkyte@TKYTE816> begin
2 shell( 'set ORACLE_SID=tkyte816 && ' ||
3 'c:oraclebinexp
userid=scott/tiger@tkyte816 ' ||
4 ' file=c:temptest.dmp tables=emp 2> tempexp.log' );
5 end;
6 /

PL/SQL procedure successfully completed.

tkyte@TKYTE816> host type tempexp.log

Export: Release 8.1.6.0.0 - Production on Sat Nov 17 13:08:45 2001

(c) Copyright 1999 Oracle Corporation. All rights reserved.


Connected to: Oracle8i Enterprise Edition Release 8.1.6.0.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
Export done in WE8ISO8859P1 character set and WE8ISO8859P1 NCHAR character set

About to export specified tables via Conventional Path ...
. . exporting table EMP 14 rows exported
Export terminated successfully without warnings.



And there you go (you can get the ORACLE_SID you need from v$instance:

tkyte@TKYTE816> select instance_name from v$instance;

INSTANCE_NAME
----------------
tkyte816

if you would like to make this generic.


Hopefully, this will show you how to debug these sorts of issues in the future.
you should note that you should use UTL_FILE or a bfile to open, read and verify
the success of your command! You could use dbms_lob.loadfromfile as well to get
it into a database table for future reference.


jametong 发表于:2005.04.27 23:26 ::分类: ( oracle refs ) ::阅读:(37201次) :: 评论 (650)
===========================================================
如何sql查询出连续号码段
===========================================================
昨天在itpub看到这个帖子, 问题觉得有意思,, 就仔细想了想. 也给出了一种解决办法..:-)
问题求助,请高手指点..

我有一个表结构,
fphm,kshm
2014,00000001
2014,00000002
2014,00000003
2014,00000004
2014,00000005
2014,00000007
2014,00000008
2014,00000009
2013,00000120
2013,00000121
2013,00000122
2013,00000124
2013,00000125

(第二个字段内可能是连续的数据,可能存在断点。)

怎样能查询出来这样的结果,查询出连续的记录来。
就像下面的这样?
2014,00000001,00000005
2014,00000009,00000007
2013,00000120,00000122
2013,00000124,00000125

方法一: 引用自
hmxxyy.

SQL> select * from gap;

ID SEQ
---------- ----------
1 1
1 4
1 5
1 8
2 1
2 2
2 9

select res1.id, res2.seq str, res1.seq end
from (
select rownum rn, c.*
from (
select *
from gap a
where not exists (
select null from gap b where b.id = a.id and a.seq = b.seq - 1
)
order by id, seq
) c
) res1, (
select rownum rn, d.*
from (
select *
from gap a
where not exists (
select null from gap b where b.id = a.id and a.seq = b.seq + 1
)
order by id, seq
) d
) res2
where res1.id = res2.id
and res1.rn = res2.rn
/

ID STR END
--------- ---------- ----------
1 1 1
1 4 5
1 8 8
2 1 2
2 9 9

方法二: 使用lag/lead分析函数进行处理.. 楼上的方法确实挺好用就是觉得表扫描/表连接比较多, 可能数据量大了. 速度会比较慢, 当然我的这种方法由于使用分析函数使用的比较频繁.所以排序量可能比上一种要多..

SQL> select fphm,lpad(kshm,8,'0') kshm
2 from t
3 /

FPHM KSHM
---------- ----------------
2014 00000001
2014 00000002
2014 00000003
2014 00000004
2014 00000005
2014 00000007
2014 00000008
2014 00000009
2013 00000120
2013 00000121
2013 00000122

FPHM KSHM
---------- ----------------
2013 00000124
2013 00000125

13 rows selected.

SQL> set echo on
SQL> @bbb.sql
SQL> select fphm,lpad(kshm,8,'0') start_kshm,lpad(prev_prev_kshm,8,'0') end_kshm
2 from (
3 select fphm,kshm,next_kshm,prev_kshm,
4 lag(kshm,1,null) over (partition by fphm order by kshm )next_next_kshm,
5 lead(kshm,1,null) over (partition by fphm order by kshm ) prev_prev_kshm
6 from (
7 select *
8 from (
9 select fphm,kshm,
10 lead(kshm,1,null) over (partition by fphm order by kshm) next_kshm,
11 lag(kshm,1,null) over (partition by fphm order by kshm) prev_kshm
12 from t
13 )
14 where ( next_kshm - kshm <> 1 or kshm - prev_kshm <> 1 )
15 or ( next_kshm is null or prev_kshm is null )
16 )
17 )
18 where next_kshm - kshm = 1
19 /

FPHM START_KSHM END_KSHM
---------- ---------------- ----------------
2013 00000120 00000122
2013 00000124 00000125
2014 00000001 00000005
2014 00000007 00000009

SQL> spool off

 查看全文
jametong 发表于:2005.04.27 21:31 ::分类: ( Oracle tips ) ::阅读:(3588次) :: 评论 (23)
===========================================================
sql to get data from flat file(zt from asktom)
===========================================================
Nag -- Thanks for the question regarding "sql to get data from flat file-- this is mind blowing", version 8.1.7
originally submitted on 12-Oct-2001 19:26 Eastern US time, last updated 26-Apr-2005 20:08

You Asked
"In 9i, with the addition of external tables ( the ability to query a FLAT FILE  
with SQL) -- SQLLDR might be "moot". Using the external table and the insert
/*+ append */ I can basically do a direct path load from file to database
without running a command outside of the database."

Tom

We just cant wait, to see how the above is done, what are the new sql clauses we
need to use to achieve the above( there should be some new clauses to do the
above).

Kindly demonstrate the above, this feature will be trend setting and path
breaking.

Nag
and we said...
Ok, here is a demo I use for training internally:

For external tables, we need to use a directory object -- we'll
start with that, mapping to the temp directory

create or replace directory data_dir as 'c:temp'
/

Now, we'll create the external table.
part of its definition is what looks like a control file -- it is


create table external_table
(EMPNO NUMBER(4) ,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
DEPTNO NUMBER(2)
)
ORGANIZATION EXTERNAL
( type oracle_loader
default directory data_dir
access parameters
( fields terminated by ',' )
location ('emp.dat')
)
/


In tempemp.dat I have a file that looks like this:

7369,SMITH,CLERK,7902,17-DEC-80,800,,20
7499,ALLEN,SALESMAN,7698,20-FEB-81,1600,300,30
7521,WARD,SALESMAN,7698,22-FEB-81,1250,500,30
....


(its a dump of the emp table in csv format)


Now you can just:

select * from external_table
/



and now, if you modified the scott/tiger EMP table:

delete from emp where mod(empno,2) = 1
/
update emp set sal = sal/2
/
commit;

You could sync up the flat file with the database table using this single
command:


merge into EMP e1
using EXTERNAL_TABLE e2
on ( e2.empno = e1.empno )
when matched then
update set e1.sal = e2.sal
when not matched then
insert ( empno, ename, job, mgr, hiredate, sal, comm, deptno )
values ( e2.empno, e2.ename, e2.job, e2.mgr, e2.hiredate, e2.sal, e2.comm,
e2.deptno )
/
commit;


that'll update the records in the EMP table from the flat file if they exist OR
it will insert them.

Doing a direct path load would simply be:

insert /*+ append */ into emp select * from external_table;


jametong 发表于:2005.04.27 08:39 ::分类: ( oracle refs ) ::阅读:(4189次) :: 评论 (24)
===========================================================
how tom write pagenation sql
===========================================================
http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:25685777038588
in general your query won't get the "next n rows".

Why would you not just:


select /*+ FIRST_ROWS */ *
from ( select /*+ FIRST_ROWS */ a.*, rownum rnum
from (select /*+ FIRST_ROWS */ * from t where .... order by ... ) a
where rownum <= :MAX_ROW )
where rnum >= :MIN_ROW;


done. that is how I write all pagination queries.


(you do know that A||B has serious programming issues -- A=1, B=11 vs A=11, B=1
-- you need to encode the fields very very carefully. don't go there, really
bad, confusing idea.


jametong 发表于:2005.04.27 00:58 ::分类: ( oracle refs ) ::阅读:(15885次) :: 评论 (387)
===========================================================
DIAGNOSING AND RESOLVING ORA-04031 ERROR
===========================================================

The purpose of this document is to provide an easy to use, step by step guide to resolving ORA-04031 errors.

Contents:

1. Instance parameters related with the Shared Pool
2. Diagnosing ORA-04031 errors
3. Resolving error ORA-04031

    * Known Oracle BUGs
    * ORA-4031 when compiling Java code
    * Small shared pool size
          o Library Cache Hit Ratio
          o Shared Pool Size Calculation
    * Shared Pool Fragmentation
          o V$SQLAREA View
          o X$KSMLRU View
          o X$KSMSP View (Similar to Heapdump Information

4. ORA-04031 error and Large Pool
5. ORA-04031 and Flushing the SHARED POOL
6. Advanced analysis to ORA-04031 error

DIAGNOSING AND RESOLVING ORA-04031 ERROR


When any attempt to allocate a large piece of contiguous memory in the shared pool fails Oracle first flushes all objects that are not currently in use from the pool and the resulting free memory chunks are merged. If there is still not a single chunk large enough to satisfy the request the ORA-04031 error is returned.

The message that you will get when this error appears is the following:

    04031, 00000, "unable to allocate %s bytes of shared memory ("%s","%s","%s","%s")"
    // *Cause: More shared memory is needed than was allocated in the shared
    // pool.
    // *Action: If the shared pool is out of memory, either use the
    // dbms_shared_pool package to pin large packages,
    // reduce your use of shared memory, or increase the amount of
    // available shared memory by increasing the value of the
    // INIT.ORA parameters "shared_pool_reserved_size" and
    // "shared_pool_size".
    // If the large pool is out of memory, increase the INIT.ORA
    // parameter "large_pool_size".


1. Instance parameters related with the Shared Pool

    Before continuing, understanding the following instance parameters will be essential:
  • SHARED_POOL_SIZE - This parameter specifies the size of the shared pool in bytes and can accept

  • a numerical values or a number followed by the suffix "K" or "M" where "K" means "multiply by 1000"
    and "M" means "multiply by 1000000"
  • SHARED_POOL_RESERVED_SIZE - It specifies the shared pool space which is reserved for large contiguous requests for shared pool memory. This parameter along with the SHARED_POOL_RESERVED_MIN_ALLOC parameter, can be used to avoid the occurrence of this error from situations where shared pool fragmentation forces Oracle to search for and free
    chunks of unused pool to satisfy the current request.

    Ideally, this parameter should be large enough to satisfy any request scanning for memory on the reserved list without flushing objects from the shared pool. Since the operating system memory may constraint the size of the shared pool, in general, you should set this parameter to 10% of the SHARED_POOL_SIZE parameter.

  • SHARED_POOL_RESERVED_MIN_ALLOC - The value of this parameter controls allocation of reserved memory. Memory allocation larger than this value can allocate space from the reserved list if a chunk of memory of sufficient size is not found on the shared pool free lists. The default value is adequate for most systems. If you increase the value, then the Oracle server will allow fewer allocations from the reserved list and will request more memory from the shared pool list. This parameter is hidden in Oracle 8i and higer, but it can be found by executing the following SQL statement:

    select nam.ksppinm NAME,
    val.KSPPSTVL VALUE
    from x$ksppi nam,
    x$ksppsv val
    where nam.indx = val.indx
    and nam.ksppinm like '%shared%'
    order by 1;

  • 10g Note: In Oracle 10g a new feature called "automatic memory management" allows the dba to reserve a pool of shared memory that is used to allocate the shared pool, the buffer cache, the java pool and the large pool.
    In general, when the database needs to allocate a large object into the shared pool and cannot find contiguous space available, it will automatically increase the shared pool size using free space from other SGA structure.
    Since the space allocation is automatically managed by Oracle, the probability of getting ora-4031 errors may be greatly reduced. Automatic Memory Management is enabled when the parameter SGA_TARGET is greater than zero and the current setting can be obtained quering the v$sga_dynamic_components view.

    Please refer to the 10g Administration Manual for further reference.

2. Diagnosing error ORA-04031:

Note: Most common ORA-4031 occurrences are related to the SHARED POOL SIZE, therefore the diagnostic steps provided in this article will mostly address issues related to the shared pool. For other areas like large_pool or java_pool where the memory allocation algorith is simpler, normally the error is caused by an undersized structure.

ORA-04031 error can be due to either an inadequeate sizing of the SHARED POOL size or due to heavy fragmentation leading the database to not finding large enough chuncks of memory.

    Inadequate Sizing: The first thing is determining if the ORA-04031 error is a result of lack of contiguous space in the library cache by verifying the following:

    REQUEST_FAILURES is > 0 and LAST_FAILURE_SIZE is <
    SHARED_POOL_RESERVED_MIN_ALLOC

    or

    REQUEST_FAILURES is 0 and LAST_FAILURE_SIZE is < SHARED_POOL_RESERVED_MIN_ALLOC

    If this is the case, consider lowering SHARED_POOL_RESERVED_MIN_ALLOC to
    allow the database putting more objects into the shared pool reserved space and then increase the
    SHARED_POOL_SIZE if the problem is not resolved.

    Fragmentation: If this is not the case, then you must determine if the ORA-04031 was a result of fragmentation in the library cache or in the shared pool reserved space by following this rule:

    REQUEST_FAILURES is > 0 and LAST_FAILURE_SIZE is >
    SHARED_POOL_RESERVED_MIN_ALLOC.

    To resolve this consider increasing SHARED_POOL_RESERVED_MIN_ALLOC to lower
    the number of objects being cached into the shared pool reserved space and
    increase SHARED_POOL_RESERVED_SIZE and SHARED_POOL_SIZE to increase the
    available memory in the shared pool reserved space.

3. Resolving error ORA-04031:
  • Oracle BUGs
  • Oracle recommends to apply the latest patchser available for your platform. Most of the ORA-4031 errors related to BUGs can be avoided by applying these patchsets. The following table summarize the most common BUGs related with this error, possible workaround and the patchset that fixes the problem.

    BUG Description Workaround Fixed
    <Bug:1397603> ORA-4031 / SGA memory leak of PERMANENT memory occurs for buffer handles. _db_handles_cached = 0 8172, 901
    <Bug:1640583> ORA-4031 due to leak / cache buffer chain contention from AND-EQUAL access Not available 8171, 901
    Bug:1318267
    Not Public
    INSERT AS SELECT statements may not be shared when they should be if TIMED_STATISTICS. It can lead to ORA-4031 _SQLEXEC_PROGRESSION_COST=0 8171, 8200
    Bug:1193003
    Not Public
    Cursors may not be shared in 8.1 when they should be Not available 8162, 8170, 901
    <Bug:2104071> ORA-4031/excessive "miscellaneous"
    shared pool usage possible.
    (many PINS)
    None-> This is known to affect the XML parser. 8174, 9013, 9201
    <Note:263791.1> Several number of BUGs related
    to ORA-4031 erros were fixed
    in the 9.2.0.5 patchset

    9205

  • ORA-4031 when compiling Java code:


  • If you run out of memory while compiling a java code (within loadjava or deployejb), you should see an error:

    A SQL exception occurred while compiling: : ORA-04031: unable to allocate bytes of shared memory ("shared pool","unknown object","joxlod: init h", "JOX: ioc_allocate_pal")

    The solution is to shut down the database and set JAVA_POOL_SIZE to a larger value. The mention of "shared pool" in the error message is a misleading reference to running out of memory in the "Shared Global Area". It does not mean you should increase your SHARED_POOL_SIZE. Instead, you must increase your JAVA_POOL_SIZE, restart your server, and try again.

    See <Bug:2736601>

  • Small shared pool size
  • In many cases, a small shared pool can be the cause of the ORA-04031 error.

    The following information will help you to adjust the size of the shared
    pool:

    Library Cache Hit Ratio
    The hit ratio helps to measure the usage of the shared pool based on how many times a SQL/PLSQL statement needed to be parsed instead of being

      reused. The following SQL statement help you to calculate the library cache
      hit ratio:

      SELECT SUM(PINS) "EXECUTIONS",


      SUM(RELOADS) "CACHE MISSES WHILE EXECUTING"


      FROM V$LIBRARYCACHE;

      If the ratio of misses to executions is more than 1%, then try to reduce
      the library cache misses by increasing the shared pool size.

    • Shared Pool Size Calculation
      To calculate the size of the shared pool that best fits to your current
      workload, please refer to:

      <Note:1012046.6>:
      HOW TO CALCULATE YOUR SHARED POOL SIZE.

  • Shared Pool Fragmentation:


  • Every time a SQL or PL/SQL statement needs to be executed the
    parse representation is loaded in the library cache requiring a specific
    amount of free contiguous space. The first resource where the database
    scans is the free memory available in the shared pool. Once the free memory
    is exhausted, the database looks for reusing an already allocated piece
    not in use. If a chunk with the exact size is not available, the scan continues
    looking for space based on the following criteria:
    - The chuck size is larger than the required size

    - The space is contiguous

    - The chuck is available (not in use)
    Then that chunk is split and the remaining free space is added to the appropriate free space list. When the database is operating in this way for a certain period of time the shared pool structure will be fragmented.

    When the shared pool is suffering fragmentation ORA-04031
    errors (when the database cannot find a contiguous piece of free memory) may occur.
    Also as a concequence , the allocation of a
    piece of free space takes more time an the performance may be affected
    (the "chunk allocation" is protected by a single latch called
    "shared pool latch" which is held during the whole operation). However, ORA-4031
    errors don't always affect the performance of the database.

    See <Note:61623.1>:
    for a detailed discussion on shared pool fragmentation.

    If the SHARED_POOL_SIZE is large enough, most ORA-04031 errors are a
    result of dynamic sql fragmenting the shared pool. This can
    be caused by:

    o Not sharing SQL

    o Making unnecessary parse
    calls (soft)

    o Not using bind variables

    To reduce fragmentation you will need to address one or more of the
    causes described before. In general to reduce fragmentation you must analyze
    how the application is using the shared pool and maximize the use of sharable cursors.

    Please refer to <Note:62143.1>,
    which describes these options in greater detail. This note contains as well
    further detail on how the shared pool works.

    The following views will help you to identify non-sharable versions
    of SQL/PLSQL text in the shared pool:

    • V$SQLAREA View
      This view keeps information of every SQL statement and
      PL/SQL block executed in the database. The following SQL can show you statements
      with literal values or candidates to include bind variables:

      SELECT substr(sql_text,1,40) "SQL",

      count(*) ,

      sum(executions) "TotExecs"

      FROM v$sqlarea

      WHERE executions < 5

      GROUP BY substr(sql_text,1,40)

      HAVING count(*) > 30

      ORDER BY 2;

      Note: The number "30" in the having section of the statement can be
      adjusted as needed to get more detailed information.


    • X$KSMLRU View
      There is a fixed table called x$ksmlru that tracks allocations in the
      shared pool that cause other objects in the shared pool to be aged out.
      This fixed table can be used to identify what is causing the large allocation.

      If many objects are being periodically flushed from the shared pool
      then this will cause response time problems and will likely cause library
      cache latch contention problems when the objects are reloaded into the
      shared pool.

      One unusual thing about the x$ksmlru fixed table is that the contents
      of the fixed table are erased whenever someone selects from the fixed table.
      This is done since the fixed table stores only the largest allocations
      that have occurred. The values are reset after being selected so that subsequent
      large allocations can be noted even if they were not quite as large as
      others that occurred previously. Because of this resetting, the output
      of selecting from this table should be carefully kept since it cannot be
      retrieved back after the query is issued.

      To monitor this fixed table just run the following:

      SELECT * FROM X$KSMLRU WHERE ksmlrsiz > 0;

      This view can only be queried by connected as the SYS.


    • X$KSMSP View (Similar to Heapdump Information)
      Using this view you will be able to find out how the free space
      is currently allocated, which will be helpful to undrestand the level of
      fragmentation of the shared pool. As it was described before, the first place to
      find a chunck big enough for the cursor allocation is the free list. The following SQL shows the chucks available in the free list:

      select '0 (<140)' BUCKET, KSMCHCLS, 10*trunc(KSMCHSIZ/10) "From",

      count(*) "Count" , max(KSMCHSIZ) "Biggest",

      trunc(avg(KSMCHSIZ)) "AvgSize", trunc(sum(KSMCHSIZ)) "Total"

      from x$ksmsp

      where KSMCHSIZ<140

      and KSMCHCLS='free'

      group by KSMCHCLS, 10*trunc(KSMCHSIZ/10)

      UNION ALL

      select '1 (140-267)' BUCKET, KSMCHCLS, 20*trunc(KSMCHSIZ/20) ,

      count(*) , max(KSMCHSIZ) ,

      trunc(avg(KSMCHSIZ)) "AvgSize", trunc(sum(KSMCHSIZ)) "Total"

      from x$ksmsp

      where KSMCHSIZ between 140 and 267

      and KSMCHCLS='free'

      group by KSMCHCLS, 20*trunc(KSMCHSIZ/20)

      UNION ALL

      select '2 (268-523)' BUCKET, KSMCHCLS, 50*trunc(KSMCHSIZ/50) ,

      count(*) , max(KSMCHSIZ) ,

      trunc(avg(KSMCHSIZ)) "AvgSize", trunc(sum(KSMCHSIZ)) "Total"

      from x$ksmsp

      where KSMCHSIZ between 268 and 523

      and KSMCHCLS='free'

      group by KSMCHCLS, 50*trunc(KSMCHSIZ/50)

      UNION ALL

      select '3-5 (524-4107)' BUCKET, KSMCHCLS, 500*trunc(KSMCHSIZ/500) ,

      count(*) , max(KSMCHSIZ) ,

      trunc(avg(KSMCHSIZ)) "AvgSize", trunc(sum(KSMCHSIZ)) "Total"

      from x$ksmsp

      where KSMCHSIZ between 524 and 4107

      and KSMCHCLS='free'

      group by KSMCHCLS, 500*trunc(KSMCHSIZ/500)

      UNION ALL

      select '6+ (4108+)' BUCKET, KSMCHCLS, 1000*trunc(KSMCHSIZ/1000) ,

      count(*) , max(KSMCHSIZ) ,

      trunc(avg(KSMCHSIZ)) "AvgSize", trunc(sum(KSMCHSIZ)) "Total"

      from x$ksmsp

      where KSMCHSIZ >= 4108

      and KSMCHCLS='free'

      group by KSMCHCLS, 1000*trunc(KSMCHSIZ/1000);

      Note: The information available in this view is the same that is generated as part of a HEAPDUMP level 2.

      If the result of the above query shows that must of the space available is on the top part of the list (meaning available only in very small chuncks). It is very likely that the error is due to a heavy fragmentation.


4. ORA-04031 error and Large Pool

The Large pool is an optional memory area that can be configured to provide large memory allocations for one of the following operations :
  • session memory for the multi-threaded server and the Oracle XA interface.
  • The memory ( Buffers ) for Oracle backup and restore operations and for I/O server processes.
  • Parallel Execution messaging buffers.
  • The Large pool does not have a LRU list. It is different from reserved space in the shared pool, which uses the same LRU list as other memory allocated from the shared pool.
    Chunks of memory are never aged out of the large pool,memory has to be explicitly allocated and freed by each session.
    If there is no free memory left when a request is made then an ORA-4031 will be signalled similar to this :

    ORA-04031: unable to allocate XXXX bytes of shared memory
    ("large pool","unknown object","session heap","frame")

    Few things can be checked when this error occurs:

    1- Check V$SGASTAT and see how much memory is used and free using the following SQL statement:


      SELECT pool,name,bytes FROM v$sgastat where pool = 'large pool';

    2- You can also take a heapdump level 32 to dump the large pool heap and check free chunks sizes.

    Memory is allocated from the large pool in chunks of LARGE_POOL_MIN_ALLOC bytes to help avoid fragmentation. Any request to allocate a chunk size less LARGE_POOL_MIN_ALLOC will be allocated with size of LARGE_POOL_MIN_ALLOC. In general you may see more memory usage when using Large Pool compared to Shared Pool.

    Usually to resolve an ORA-4031 in the large pool the LARGE_POOL_SIZE size must be increased.


    5. ORA-04031 and SHARED POOL FLUSHING

    There are several technics to increase cursor sharability so that shared pool fragmentation is reduce as well as likeability of ORA-4031 errors. The best way is by modifying the application to use bind variables. Another workaround when the application cannot be modified is using CURSOR_SHARING to a value different of FORCE (Be aware that this may cause changes in execution plan, so it is advisable to test the application first). When none of the above techniques can be used and fragmentation is considearble heavy in the system, flushing the shared pool might help alliviating the fragmentation. However some considerations must be taken into account:
    • Flushing the shared pool will cause that all the cursor that are not in use are removed from the library cache. Therefore just after the shared pool flusing is issued, most of the SQL and PL/SQL cursors will have to be hard parsed. This will increase the CPU usage of the system and will also increase the latch activity.
    • When applications don't use bind variables and have heavy possibilities of many users doing frequen similar operations (like in OLTP systems) it is common that soon after the flush is issued the fragmentation is back in place. So be advice that flushing the shared pool is not always the solution for a bad application.
    • For large shared pool flushing the shared pool may cause a halt of the system, specially when the instance is very active. It is recommended to flush the shared pool during off-peak hours.


    6. Advanced analysis to ORA-04031error

    If none of the techniques provided cannot resolve the occurence of ORA-04031 errors, additional tracing may be needed to get a snapshot of the shared pool when the problem is in place.

      Modify the init.ora paramater to add the following events to get a trace file with additional information about the problem:
      event = "4031 trace name errorstack level 3"
      event = "4031 trace name HEAPDUMP level 3"

      Note: This parameter will take not effect unless the instance is bounced.

      If the problem is reproducible, the event can be set at session level using the following statement before the execution of the faulty SQL statement:
      SQL> alter session set events '4031 trace name errorstack level 3';
      SQL> alter session set events '4031 trace name HEAPDUMP level 3';

    This trace file should be sent to Oracle Support for troubleshooting.

    Important Note: In Oracle 9.2.0.5 and Oracle 10g releases a trace file is generated BY DEFAULT every time an ORA-4031 error occurs, and can be located in the user_dump_dest directory. If your database version is one of these, you don't need to follow the steps described before to generate additional tracing.


    RELATED DOCUMENTS

    <Note:1012046.6> How to Calculate Your Shared Pool Size
    <Note:62143.1> Understanding and Tuning the Shared Pool
    <Note:1012049.6> Tuning Library Cache Latch Contention
    <Note:61623.1> Resolving Shared Pool Fragmentation




    jametong 发表于:2005.04.26 07:41 ::分类: ( oracle refs ) ::阅读:(2312次) :: 评论 (41)
    ===========================================================
    如何确定今天是本月的第几周.
    ===========================================================
    1. 我自己想出来的方法.
    思路.
    a. 先确定元月1号是星期几. 这样可以退出第二周的第一天从哪天开始.
    b. 计算出每个月第一天属于全年的那一周.
    c. 这样就可以计算出具体某个日期属于哪一天了^_^.
    SQL> @bbb.sql
    SQL> select date_col,
      2           to_number(to_char(trunc(sysdate,'yyyy'),'d')) year_week_day,
      3           first_day_week,week_no,week_no - first_day_week + 1 week_no
      4  from (
      5      select date_col,
      6          to_number(to_char(trunc(sysdate,'mm') + 7 - 1 ,'ww')) first_day_week,
      7          to_number(to_char(date_col + 7 - 1,'ww')) week_no
      8      from (
      9        select trunc(sysdate,'mm') + rownum - 1 date_col
     10       from dba_objects
     11       where rownum <= to_number(to_char(last_day(sysdate),'dd'))
     12    )
     13  )
     14  /

    DATE_COL  YEAR_WEEK_DAY FIRST_DAY_WEEK    WEEK_NO    WEEK_NO                   
    --------- ------------- -------------- ---------- ----------                   
    01-APR-05             7             14         14          1                   
    02-APR-05             7             14         14          1                   
    03-APR-05             7             14         15          2                   
    04-APR-05             7             14         15          2                   
    05-APR-05             7             14         15          2                   
    06-APR-05             7             14         15          2                   
    07-APR-05             7             14         15          2                   
    08-APR-05             7             14         15          2                   
    09-APR-05             7             14         15          2                   
    10-APR-05             7             14         16          3                   
    11-APR-05             7             14         16          3                   

    DATE_COL  YEAR_WEEK_DAY FIRST_DAY_WEEK    WEEK_NO    WEEK_NO                   
    --------- ------------- -------------- ---------- ----------                   
    12-APR-05             7             14         16          3                   
    13-APR-05             7             14         16          3                   
    14-APR-05             7             14         16          3                   
    15-APR-05             7             14         16          3                   
    16-APR-05             7             14         16          3                   
    17-APR-05             7             14         17          4                   
    18-APR-05             7             14         17          4                   
    19-APR-05             7             14         17          4                   
    20-APR-05             7             14         17          4                   
    21-APR-05             7             14         17          4                   
    22-APR-05             7             14         17          4                   

    DATE_COL  YEAR_WEEK_DAY FIRST_DAY_WEEK    WEEK_NO    WEEK_NO                   
    --------- ------------- -------------- ---------- ----------                   
    23-APR-05             7             14         17          4                   
    24-APR-05             7             14         18          5                   
    25-APR-05             7             14         18          5                   
    26-APR-05             7             14         18          5                   
    27-APR-05             7             14         18          5                   
    28-APR-05             7             14         18          5                   
    29-APR-05             7             14         18          5                   
    30-APR-05             7             14         18          5                   

    30 rows selected.

    SQL> spool off

    2. Tom使用的办法. ( 不得不说这个方法比我的方法要简单多咯:-) )
    思路:
    a.  取出本月1号的前一个星期天的日期
    b.  再取出与该星期天的星期的差距.

    SQL> @bbb.sql
    SQL> select x,next_day(trunc(x,'mm')-8,'sun') next_day,
      2          trunc((x-next_day(trunc(x,'mm')-8,'sun'))/7)+1 "week"
      3  from (
      4    select trunc(sysdate,'mm') + rownum - 1 x
      5    from dba_objects
      6    where rownum <= to_number(to_char(last_day(sysdate),'dd'))
      7  )
      8  /

    X         NEXT_DAY        week                                                 
    --------- --------- ----------                                                 
    01-APR-05 27-MAR-05          1                                                 
    02-APR-05 27-MAR-05          1                                                 
    03-APR-05 27-MAR-05          2                                                 
    04-APR-05 27-MAR-05          2                                                 
    05-APR-05 27-MAR-05          2                                                 
    06-APR-05 27-MAR-05          2                                                 
    07-APR-05 27-MAR-05          2                                                 
    08-APR-05 27-MAR-05          2                                                 
    09-APR-05 27-MAR-05          2                                                 
    10-APR-05 27-MAR-05          3                                                 
    11-APR-05 27-MAR-05          3                                                 

    X         NEXT_DAY        week                                                 
    --------- --------- ----------                                                 
    12-APR-05 27-MAR-05          3                                                 
    13-APR-05 27-MAR-05          3                                                 
    14-APR-05 27-MAR-05          3                                                 
    15-APR-05 27-MAR-05          3                                                 
    16-APR-05 27-MAR-05          3                                                 
    17-APR-05 27-MAR-05          4                                                 
    18-APR-05 27-MAR-05          4                                                 
    19-APR-05 27-MAR-05          4                                                 
    20-APR-05 27-MAR-05          4                                                 
    21-APR-05 27-MAR-05          4                                                 
    22-APR-05 27-MAR-05          4                                                 

    X         NEXT_DAY        week                                                 
    --------- --------- ----------                                                 
    23-APR-05 27-MAR-05          4                                                 
    24-APR-05 27-MAR-05          5                                                 
    25-APR-05 27-MAR-05          5                                                 
    26-APR-05 27-MAR-05          5                                                 
    27-APR-05 27-MAR-05          5                                                 
    28-APR-05 27-MAR-05          5                                                 
    29-APR-05 27-MAR-05          5                                                 
    30-APR-05 27-MAR-05          5                                                 

    30 rows selected.

    SQL> spool off



    jametong 发表于:2005.04.26 05:54 ::分类: ( Oracle tips ) ::阅读:(6739次) :: 评论 (201)
    ===========================================================
    about date manipulation(zt asktom)
    ===========================================================
    How to get the the date of first day of the week for a given week #?  For 
    example, the beginning day for week# 34 in 2003 is AUG-18-2003, how do I find
    the beginning date for the same week # 34 in 2002? 'iw' can't be used in the
    to_date function.

    Thanks!

    Followup:
    well, we can use the fact that at least from 1800 to 2199, jan 4th is in the 
    first week... this:

    ops$tkyte@ORA920> select *
    2 from (
    3 select dt1, to_char( dt1, 'yyyy' ),
    4 to_char( dt4, 'iw' ),
    5 decode( to_char( dt4, 'iw' ), '01', null, '******' ) xxx
    6 from (
    7 select add_months( to_date( '01-jan-1800', 'dd-mon-yyyy'), (rownum-1)*12 )
    dt1,
    8 add_months( to_date( '02-jan-1800', 'dd-mon-yyyy'), (rownum-1)*12 )
    dt2,
    9 add_months( to_date( '03-jan-1800', 'dd-mon-yyyy'), (rownum-1)*12 )
    dt3,
    10 add_months( to_date( '04-jan-1800', 'dd-mon-yyyy'), (rownum-1)*12 )
    dt4,
    11 add_months( to_date( '05-jan-1800', 'dd-mon-yyyy'), (rownum-1)*12 )
    dt5,
    12 add_months( to_date( '06-jan-1800', 'dd-mon-yyyy'), (rownum-1)*12 )
    dt6,
    13 add_months( to_date( '07-jan-1800', 'dd-mon-yyyy'), (rownum-1)*12 )
    dt7
    14 from all_objects
    15 where rownum <= 400
    16 )
    17 )
    18 where xxx is not null
    19 /

    no rows selected


    shows that.

    Then, we can use the fact that next_day(dt-7,'mon') returns the monday of that
    week that DT falls in.

    sooo, it would seem that if we

    take jan-4th of the year of interest.

    we add to that the (week-2)* 7 days (-1 becuase we start at week one, -1 again
    because we back off 7 days) .

    and then ask for the next monday -- we get it:

    ops$tkyte@ORA920> variable year varchar2(4)
    ops$tkyte@ORA920> variable week number
    ops$tkyte@ORA920>
    ops$tkyte@ORA920> exec :year := '2003'; :week := 34

    PL/SQL procedure successfully completed.

    ops$tkyte@ORA920>
    ops$tkyte@ORA920> select next_day( to_date( '04-jan-' || :year, 'dd-mon-yyyy' )
    + (:week-2)*7, 'mon' )
    2 from dual
    3 /

    NEXT_DAY(TO_DATE('04
    --------------------
    18-aug-2003 00:00:00



    this query generates all of the "first days of the week" by IW week for a year:

    ops$tkyte@ORA920> select year, week,
    2 next_day( to_date( '04-jan-' || year, 'dd-mon-yyyy' ) + (week-2)*7,
    'mon' )
    3 from (select '2003' year, rownum week from all_objects where rownum <= 53
    )
    4 /

    YEAR WEEK NEXT_DAY(TO_DATE('04
    ---- ---------- --------------------
    2003 1 30-dec-2002 00:00:00
    2003 2 06-jan-2003 00:00:00
    2003 3 13-jan-2003 00:00:00
    2003 4 20-jan-2003 00:00:00
    2003 5 27-jan-2003 00:00:00
    2003 6 03-feb-2003 00:00:00
    2003 7 10-feb-2003 00:00:00
    2003 8 17-feb-2003 00:00:00
    2003 9 24-feb-2003 00:00:00
    2003 10 03-mar-2003 00:00:00
    2003 11 10-mar-2003 00:00:00
    2003 12 17-mar-2003 00:00:00
    2003 13 24-mar-2003 00:00:00
    2003 14 31-mar-2003 00:00:00
    2003 15 07-apr-2003 00:00:00
    2003 16 14-apr-2003 00:00:00
    2003 17 21-apr-2003 00:00:00
    2003 18 28-apr-2003 00:00:00
    2003 19 05-may-2003 00:00:00
    2003 20 12-may-2003 00:00:00
    2003 21 19-may-2003 00:00:00
    2003 22 26-may-2003 00:00:00
    2003 23 02-jun-2003 00:00:00
    2003 24 09-jun-2003 00:00:00
    2003 25 16-jun-2003 00:00:00
    2003 26 23-jun-2003 00:00:00
    2003 27 30-jun-2003 00:00:00
    2003 28 07-jul-2003 00:00:00
    2003 29 14-jul-2003 00:00:00
    2003 30 21-jul-2003 00:00:00
    2003 31 28-jul-2003 00:00:00
    2003 32 04-aug-2003 00:00:00
    2003 33 11-aug-2003 00:00:00
    2003 34 18-aug-2003 00:00:00
    2003 35 25-aug-2003 00:00:00
    2003 36 01-sep-2003 00:00:00
    2003 37 08-sep-2003 00:00:00
    2003 38 15-sep-2003 00:00:00
    2003 39 22-sep-2003 00:00:00
    2003 40 29-sep-2003 00:00:00
    2003 41 06-oct-2003 00:00:00
    2003 42 13-oct-2003 00:00:00
    2003 43 20-oct-2003 00:00:00
    2003 44 27-oct-2003 00:00:00
    2003 45 03-nov-2003 00:00:00
    2003 46 10-nov-2003 00:00:00
    2003 47 17-nov-2003 00:00:00
    2003 48 24-nov-2003 00:00:00
    2003 49 01-dec-2003 00:00:00
    2003 50 08-dec-2003 00:00:00
    2003 51 15-dec-2003 00:00:00
    2003 52 22-dec-2003 00:00:00
    2003 53 29-dec-2003 00:00:00

    53 rows selected.



    please -- check out the boundary value conditions!!! (eg: test this, date things
    can be tricky)


    jametong 发表于:2005.04.26 05:29 ::分类: ( oracle refs ) ::阅读:(582次) :: 评论 (0)
    ===========================================================
    不要和陌生人喝酒(安全警告)
    ===========================================================
    如果是真的,那就太恐怖了

    <<特级警告>>不要和陌生人喝酒(为了人身安全一定要
    看!!!!!!!!!!!!!)
    广州大学庆祝期中考结束是个传统。这个男生去参加上星期六晚上的庆祝。他觉得很
    快乐,喝了很多酒,而且有些女孩对他有兴趣,于是邀请他参加另一个庆祝会。他很快的
    就答应了,并且自己一个与女孩们坐出租车(有车哦)同去。庆祝会是在另一楼公寓。
    他们继续地喝酒,并吃了一些不知名的药。等他再醒来,发现他全身赤裸地在浴缸中,而
    且浴缸里满满的都是冰。药效仍然没对完全退去,不过他看了看四周,发现只有他一个
    人。他看了自己的胸部,发现上面用口红写了*打110,否则你会死*。他接着看到了一支
    电话就在浴缸旁,于是他就打了电话到110去。他向110说明目前的情况并表示他不知道
    自己在何处,他吃了什么,与他为什么要打这电话。110建议他离开浴缸,并照照镜子,他
    照做了,并无发现任何异状。110再建议他检查自己的背,而他只发现了两条九寸长的切
    割伤口在背部下方。110要他马上躺回满是冰的浴缸,并马上派一组急救队来。在仔细
    检查之后,明显地,他发现事实超出预期。他的肾脏被偷了!在黑市里,一对肾脏值
    300,000元!这件事可能是:第二个庆祝会是个骗局,参与的人中至少有医学院学生。
    被害人所吃的药也可能不只是单纯的迷幻药。不管如何,被害人现在正躺在医院里靠维
    生系统过活,并且等待肾脏的捐赠。中山大学正与广州大学医学中心合作,在寻找这个
    大四学生的肾脏。警告大家,一种新型态的犯罪正在发生,并且以旅行者为目标。这个
    犯罪组织很有规模,有钱,并且有训练有素的人员。这犯罪行为正发生在绝大多数的主
    要城市,最近尤其是在广州。犯罪过程往往从旅行者一整天工作完后晚上到酒馆喝酒开
    始。有陌生人从吧台走过来,好象他是单独的一人,并且请旅行者喝酒。最后就是旅行
    者发现自己躺在旅馆的浴缸中,颈部以下全埋在冰块中,而旅行者只记得他在喝小酒。
    浴缸旁的墙上有纸片贴着,并写着要旅行者不要动,打电话给110。而电话就在浴缸旁的
    小桌子上,以方便旅行者打电话。打到110后,110很熟悉这类的犯罪方法便请旅行者小
    心,并慢慢的触摸他的背部下方,是否有管子突出。如果有,110会要求他保持不动,并派
    人来求援。110知道这位旅行者的肾脏被取走了。这不是恶作剧的故事,也不是超科幻
    小说,这是真实的故事。这故事被纪录并被当事人确认过的...当你在旅行时,有陌生人
    靠近时,请务必小心。他们接到了有关这方面有组织的犯罪的消息,这是很严重的。一
    位消防队朋友的女儿也遭到了这不幸,而且有专业技术的医生参与其中!此外,军方也
    接到了这方面的警告。所以,这故事的最后一句应该是:请将这个故事转达给你所爱的
    人,你所关心的人,与所有你认识的人

    jametong 发表于:2005.04.25 11:39 ::分类: ( My life ) ::阅读:(553次) :: 评论 (1)
    ===========================================================
    how to send html email through utl_smtp
    ===========================================================
    You Asked (Jump to Tom's latest followup)
    Hi Tom

    I hope I'm phrasing this correctly...

    I'd like to be able to send an HTML formatted email from the database using the
    UTL_SMTP package. I don't see any way of setting the MIME type.

    Is this beyond the scope of UTL_SMTP?

    thanks in advance!

    Ken
    and we said...
    I asked Tyler Muth (tyler.muth@oracle.com) to answer this one since I knew he 
    already had the code (we use it on our Oracle Calendar software shipped with the
    email server to send reminders for appointments). Tyler provided this answer
    for us:

    ...

    You are correct in you observation that there is no MIME type parameter in
    UTL_SMTP, but this does not limit the types of email you can send. It's
    actually very flexible, in that UTL_SMTP allows you to contruct and pass in
    the whole email message. What this means to you is that constructing an
    HTML message is possible using UTL_SMTP, but your going to have to do some
    work to create it.

    The folowing is the basic structure of the message you need to construct:


    Normal Headers
    Content-Type: multipart/alternative;
    boundary="some_unique_string_not_in_email"

    --some_unique_string_not_in_email
    Content-Type: text/plain; charset=us-ascii

    Text email message here.

    --some_unique_string_not_in_email
    Content-Type: text/html; charset=us-ascii

    <html>
    <head>
    <title>some subject</title>
    </head>
    <body>
    Your <b>Html</b> email message here.
    </body>
    </html>

    --some_unique_string_not_in_email--


    Ok, that looks hard, but if you use this procedure I wrote, its really quite
    easy, it does all of the work for you:


    create or replace procedure html_email(
    p_to in varchar2,
    p_from in varchar2,
    p_subject in varchar2,
    p_text in varchar2 default null,
    p_html in varchar2 default null,
    p_smtp_hostname in varchar2,
    p_smtp_portnum in varchar2)
    is
    l_boundary varchar2(255) default 'a1b2c3d4e3f2g1';
    l_connection utl_smtp.connection;
    l_body_html clob := empty_clob; --This LOB will be the email message
    l_offset number;
    l_ammount number;
    l_temp varchar2(32767) default null;
    begin
    l_connection := utl_smtp.open_connection( p_smtp_hostname, p_smtp_portnum );
    utl_smtp.helo( l_connection, p_smtp_hostname );
    utl_smtp.mail( l_connection, p_from );
    utl_smtp.rcpt( l_connection, p_to );

    l_temp := l_temp || 'MIME-Version: 1.0' || chr(13) || chr(10);
    l_temp := l_temp || 'To: ' || p_to || chr(13) || chr(10);
    l_temp := l_temp || 'From: ' || p_from || chr(13) || chr(10);
    l_temp := l_temp || 'Subject: ' || p_subject || chr(13) || chr(10);
    l_temp := l_temp || 'Reply-To: ' || p_from || chr(13) || chr(10);
    l_temp := l_temp || 'Content-Type: multipart/alternative; boundary=' ||
    chr(34) || l_boundary || chr(34) || chr(13) ||
    chr(10);

    ----------------------------------------------------
    -- Write the headers
    dbms_lob.createtemporary( l_body_html, false, 10 );
    dbms_lob.write(l_body_html,length(l_temp),1,l_temp);


    ----------------------------------------------------
    -- Write the text boundary
    l_offset := dbms_lob.getlength(l_body_html) + 1;
    l_temp := '--' || l_boundary || chr(13)||chr(10);
    l_temp := l_temp || 'content-type: text/plain; charset=us-ascii' ||
    chr(13) || chr(10) || chr(13) || chr(10);
    dbms_lob.write(l_body_html,length(l_temp),l_offset,l_temp);

    ----------------------------------------------------
    -- Write the plain text portion of the email
    l_offset := dbms_lob.getlength(l_body_html) + 1;
    dbms_lob.write(l_body_html,length(p_text),l_offset,p_text);

    ----------------------------------------------------
    -- Write the HTML boundary
    l_temp := chr(13)||chr(10)||chr(13)||chr(10)||'--' || l_boundary ||
    chr(13) || chr(10);
    l_temp := l_temp || 'content-type: text/html;' ||
    chr(13) || chr(10) || chr(13) || chr(10);
    l_offset := dbms_lob.getlength(l_body_html) + 1;
    dbms_lob.write(l_body_html,length(l_temp),l_offset,l_temp);

    ----------------------------------------------------
    -- Write the HTML portion of the message
    l_offset := dbms_lob.getlength(l_body_html) + 1;
    dbms_lob.write(l_body_html,length(p_html),l_offset,p_html);

    ----------------------------------------------------
    -- Write the final html boundary
    l_temp := chr(13) || chr(10) || '--' || l_boundary || '--' || chr(13);
    l_offset := dbms_lob.getlength(l_body_html) + 1;
    dbms_lob.write(l_body_html,length(l_temp),l_offset,l_temp);


    ----------------------------------------------------
    -- Send the email in 1900 byte chunks to UTL_SMTP
    l_offset := 1;
    l_ammount := 1900;
    utl_smtp.open_data(l_connection);
    while l_offset < dbms_lob.getlength(l_body_html) loop
    utl_smtp.write_data(l_connection,
    dbms_lob.substr(l_body_html,l_ammount,l_offset));
    l_offset := l_offset + l_ammount ;
    l_ammount := least(1900,dbms_lob.getlength(l_body_html) - l_ammount);
    end loop;
    utl_smtp.close_data(l_connection);
    utl_smtp.quit( l_connection );
    dbms_lob.freetemporary(l_body_html);
    end;
    /
    show errors



    jametong 发表于:2005.04.25 11:09 ::分类: ( oracle refs ) ::阅读:(837次) :: 评论 (1)
    ===========================================================
    One way for str2table(zt asktom)
    ===========================================================
    Mohammad -- Thanks for the question regarding "list all user(s) group by group_list", version 8.1.7
    originally submitted on 27-Jun-2003 10:46 Eastern US time, last updated 21-Apr-2005 12:02 You Asked (Jump to Tom's latest followup)
    Hello Tom,

    i have the follwing table:

    LOGIN_NAME GROUP_LIST
    --------------- --------------------------------------------------
    Demo 1; 9000; 1000;
    Koo 1000;
    Feh 1000; 1006; 1021; 1030;
    Hene 1006; 1000; 1021;
    Jaehrling 1000;
    Koell 1000;
    Woeh 1000; 1001;


    Now I am trying to write a query to get the below results

    Demo 1
    Demo 9000
    Demo 1000
    .
    ..

    Could you plaese help me to solve this problem

    Best regards
    Mohammad
    and we said...
    oh yuck.  hate it when people do that.  "relational" database... ok

    ops$tkyte@ORA817DEV> create or replace type myArray as table of number
    2 /

    Type created.

    ops$tkyte@ORA817DEV>
    ops$tkyte@ORA817DEV> create or replace function str2table( p_string in varchar2
    ) return myArray
    2 as
    3 l_data myArray := myArray();
    4 l_string long := p_string;
    5 l_n number;
    6 begin
    7 while (l_string is not null)
    8 loop
    9 l_n := instr( l_string, ';' );
    10 if ( l_n = 0 )
    11 then
    12 l_n := length(l_string)+1;
    13 end if;
    14 l_data.extend;
    15 l_data(l_data.count) := substr( l_string, 1, l_n-1 );
    16 l_string := substr( l_string, l_n+1 );
    17 end loop;
    18 return l_data;
    19 end;
    20 /

    Function created.

    ops$tkyte@ORA817DEV>
    ops$tkyte@ORA817DEV> drop table t;

    Table dropped.

    ops$tkyte@ORA817DEV> create table t ( login_name varchar2(10), group_list
    varchar2(200) );

    Table created.

    ops$tkyte@ORA817DEV>
    ops$tkyte@ORA817DEV> insert into t values ( 'demo', '1; 9000; 1000;' );

    1 row created.

    ops$tkyte@ORA817DEV> insert into t values ( 'feh', '1000; 1006; 1021; 1030;' );

    1 row created.

    ops$tkyte@ORA817DEV>
    ops$tkyte@ORA817DEV> select t.login_name, t2.column_value
    2 from t, TABLE(cast( str2table(t.group_list) as myArray )) t2
    3 /

    LOGIN_NAME COLUMN_VALUE
    ---------- ------------
    demo 1
    demo 9000
    demo 1000
    feh 1000
    feh 1006
    feh 1021
    feh 1030

    7 rows selected.


    is one way.