2015年11月21日 (土)

WITH clause in-line PL/SQL functionって....

12cの新機能でオイタをしてみたw

with句に関数仕込んで内部でSQL文を実行してオイタしてみました。

実際にこのような使い方するんでしょうか?
これをやるなら素直にスカラー副問合せの方がいいと思うんですね.....
(スカラー副問合せのように使われたら、同じく12cの新機能、Scalar subquery unnestingもできなし。)

なんでこんな機能必要なんだろう?
どのような場面で、有効なんだろう?

今の所、使いどころが思い浮かばないので、誰か教えて〜〜〜〜〜! 
とモヤモヤしてたんですが、今日はお留守番で時間だけはあったので、ごにょごにょとw


SCOTT> set serveroutput on
SCOTT> set feed off
SCOTT> r
1 with
2 function hoge return varchar2
3 deterministic
4 as
5 begin
6 for rec in (select empno,ename from emp order by empno) loop
7 dbms_output.put_line('**** '||rec.empno||':'||rec.ename||' ****');
8 end loop;
9 return null;
10 end;
11 select
12 hoge
13 from
14 dual
15 where
16* hoge is not null

**** 7369:SMITH ****
**** 7499:ALLEN ****
**** 7521:WARD ****
**** 7566:JONES ****
**** 7654:MARTIN ****
**** 7698:BLAKE ****
**** 7782:CLARK ****
**** 7839:KING ****
**** 7844:TURNER ****
**** 7900:JAMES ****
**** 7902:FORD ****
**** 7934:MILLER ****

経過: 00:00:00.01

こんなことをやられると....
実行計画には現れないしw (ちなみにスカラー副問合せは実行計画を見ただけでわかりますです。はい)

ただのチューナーいじめじゃ >< w
SQLトレースなら補足できるけど、なんぎじゃのう。げほげほ

(WITH句のインラインPL/SQLファンクション(名称あってるのかな?)内部でSQL文は実行しない方がいいと思うけど。。。。???)


SCOTT> 
SCOTT> set autot trace exp stat
SCOTT> r
1 with
2 function hoge return varchar2
3 deterministic
4 as
5 begin
6 for rec in (select empno,ename from emp order by empno) loop
7 dbms_output.put_line('**** '||rec.empno||':'||rec.ename||' ****');
8 end loop;
9 return null;
10 end;
11 select
12 hoge
13 from
14 dual
15 where
16* hoge is not null

**** 7369:SMITH ****
**** 7499:ALLEN ****
**** 7521:WARD ****
**** 7566:JONES ****
**** 7654:MARTIN ****
**** 7698:BLAKE ****
**** 7782:CLARK ****
**** 7839:KING ****
**** 7844:TURNER ****
**** 7900:JAMES ****
**** 7902:FORD ****
**** 7934:MILLER ****

経過: 00:00:00.03

実行計画
----------------------------------------------------------
Plan hash value: 4034615273

-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
|* 1 | FILTER | | | | |
| 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("HOGE"() IS NOT NULL)


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




WITH句のインラインPL/SQLファンクション内でのSQL文の実行はダークサイドな香りしかしないので、使うならデータの加工等、計算中心目的かねぇ〜。とマニュアル読んでたら見つけたw
 
(マニュアルのサンプルも加工のみ! )

SCOTT> r
1 with
2 function hoge(eno number) return varchar2
3 deterministic
4 as
5 begin
6 dbms_output.put_line('Called');
7 return '**** '||eno||' ****';
8 end;
9 select
10 hoge(empno)
11 from
12* emp

HOGE(EMPNO)
---------------------------------------------------------------------
**** 7369 ****
**** 7499 ****
**** 7521 ****
**** 7566 ****
**** 7654 ****
**** 7698 ****
**** 7782 ****
**** 7839 ****
**** 7844 ****
**** 7900 ****
**** 7902 ****
**** 7934 ****
Called
Called
Called
Called
Called
Called
Called
Called
Called
Called
Called
Called
経過: 00:00:00.02

Database SQL Language Reference (12.1)
Database SQL Language Reference (12.1) - SELECT


みなさん、ダークサイドに落ちないように注意しましょうね! :)

| | コメント (0) | トラックバック (0)

2012年1月30日 (月)

AWRレポート、AWR SQLレポート一括取得スクリプトを作ったよ。

Statspackレポートもそうなのですが、AWRレポート/AWR SQLレポートも個別に取得していると凄ーく辛いんですよね。一日分出力するとか、AWRレポートで処理時間の長いSQL文のAWR SQLレポートを個別に取得しようとなると...

ただでさえ忙しいのに、AWRレポート取得するのに時間掛けたくないですよね。

ということで、やっつけで作ったのですが、そのまま載せるのもあれなんで、やっつけで作った感じを多少減らしてgithubに公開しました。;)

https://github.com/discus/Oracle-AWR-batch-generation-script/blob/master/awrreport_batch.sql


もっといい感じに改造してくれるといいな〜とかとか... :)

Oracle11g R1/R2 Enterprise Edition、HTML形式で出力します。(RAC環境では試してないので多分だめかと。)。
AWRを利用するには追加ライセンスが必要なのでご注意を


使い方は・・

SQL*plusを起動し、select any dictionaryシステム権限、dbms_repositoryパッケージの実行権限が付与されたユーザで接続して実行するだけ。
SYSTEMユーザでやる事が多いけど、所変わればなんとやらなので・・・そこんとこよろしく。(w


一括取得なので実行当日を含めてn日分のAWRレポートを取得し、同時に処理時間の長いTop20のAWR SQLレポートも取得します。
レポートは各スナップショット間(今のところ固定)で取得します。

指定するパラメータは、以下の3つ。

Enter snap_id for starting AWR report generation. [NULL] : 
AWRレポートを取得する最初のSNAP_IDを指定します。 NULLがデフォルトでほとんどの場合デフォルトのままで事足りると思います。


Enter number of days for reporting period. [1] : 

一括取得する日数を指定します。当日を含みます。
当日分のAWRレポートを出力するのであれば、デフォルト値の1のままでOKです。


Enter suffix for AWR reports filename. [NULL] : test

保存するAWRレポートのファイル名に付加するsuffixを指定します。
試験名とか設定するといいですよね。

"test"と指定した場合

awrrpt_nnnn_nnnn_test.htmlや
awrsqrpt_nnnn_nnnn_test_sqlid.html

の形式で保存します。(nnnnはSNAP_ID)


実行例1)当日分の全レポートを取得する例

SYSTEM> 
SYSTEM> !ls -l awr*.sql
-rw-r--r-- 1 oracle oinstall 6065 1月 29 18:23 awrreport_batch.sql

SYSTEM> @awrreport_batch
--
-- Oracle AWR and AWR SQL report batch generation script
--
-- ***** This script always generate html format AWR reports. *****
--
Enter snap_id for starting AWR report generation. [NULL] :
Enter number of days for reporting period. [1] :
Enter suffix for AWR reports filename. [NULL] : test
--
--
--
clear break compute;
repfooter off;
ttitle off;
btitle off;

・・・中略・・・

<p />
<br /><a class="awr" href="#top">Back to Top</a><p />
</body></html>

SYSTEM>


実行例2)当日分かつsnap_id=291以降で一括取得。(事前にsnap_idを調べておいてね)

SYSTEM> 
SYSTEM> @awrreport_batch
--
-- Oracle AWR and AWR SQL report batch generation script
--
-- ***** This script always generate html format AWR reports. *****
--
Enter snap_id for starting AWR report generation. [NULL] : 291
Enter number of days for reporting period. [1] :
Enter suffix for AWR reports filename. [NULL] : test
--
--
--
clear break compute;
repfooter off;
ttitle off;
btitle off;

・・・中略・・・

<p />
<br /><a class="awr" href="#top">Back to Top</a><p />
</body></html>

SYSTEM>
SYSTEM>
SYSTEM> !ls -l *.html
-rw-r--r-- 1 oracle oinstall 379083 1月 29 22:23 awrrpt_291_292_test.html
-rw-r--r-- 1 oracle oinstall 11899 1月 29 22:23 awrsqrpt_291_292_test_0c83z9rqx45hu.html
-rw-r--r-- 1 oracle oinstall 11899 1月 29 22:23 awrsqrpt_291_292_test_0h3mfbzk6uyw0.html
-rw-r--r-- 1 oracle oinstall 11897 1月 29 22:23 awrsqrpt_291_292_test_2p7t0mw7zvu5z.html

・・・中略・・・

-rw-r--r-- 1 oracle oinstall 11899 1月 29 22:23 awrsqrpt_291_292_test_bhtycgwkxhfj9.html
-rw-r--r-- 1 oracle oinstall 11900 1月 29 22:23 awrsqrpt_291_292_test_bpaggvtfkar9k.html
-rw-r--r-- 1 oracle oinstall 11899 1月 29 22:23 awrsqrpt_291_292_test_c50hdbyuwhfn6.html
-rw-r--r-- 1 oracle oinstall 11892 1月 29 22:23 awrsqrpt_291_292_test_g3f3cw3zy5aat.html

SYSTEM>

なお、Oracleインスタンスが再起動された期間でawrrpt.sqlなどを実行すると、レポートが作成できずエラーでSQL*Plusも終了してしまいますが、本スクリプトでは該当部分のレポートはスキップするようにしてあります。:)

Instance     DB Name      Snap Id   Snap Started       Level
------------ ------------ --------- ------------------ -----
lampeye LAMPEYE 274 29 1月 2012 09:33 1
275 29 1月 2012 10:00 1
276 29 1月 2012 10:30 1
277 29 1月 2012 11:00 1
278 29 1月 2012 11:30 1
279 29 1月 2012 12:00 1
280 29 1月 2012 12:30 1
281 29 1月 2012 13:00 1
282 29 1月 2012 13:30 1
283 29 1月 2012 14:00 1
284 29 1月 2012 14:30 1
285 29 1月 2012 15:00 1
286 29 1月 2012 15:30 1
287 29 1月 2012 16:00 1
288 29 1月 2012 16:30 1
289 29 1月 2012 17:00 1
290 29 1月 2012 17:30 1

291 29 1月 2012 18:31 1 ←再起動されてる
292 29 1月 2012 18:34 1

293 29 1月 2012 22:26 1 ←再起動されてる


Enjoy!

| | コメント (0) | トラックバック (0)

2011年12月14日 (水)

PL/SQL de Conditional Compile #6

随分前にPL/SQL de Conditional Compile #5ってエントリ書いてたのを思い出して、11g R1/R2用のを見てみたらソースに丁寧なコメント(マニュアルよりいいんじゃね?w )が書かれていてうれしくなった。

オラクルさんとして見せたくない部分は見えないようになっているけど、見せても問題ないところはコードが見える(all_sourceビュー)わけで、それはそれでうれしいわけです。はい。マニュアルが意外に不親切だったりするので。

(マニュアル、良くなりましたよ。昔より。 > 褒めておかないとね、だれとなくw。)...文字サイズも多くしておきましたw

● Oracle11g R1 11.1 の DBMS_DB_VERSION

package dbms_db_version is
version constant pls_integer := 11; -- RDBMS version number
release constant pls_integer := 1; -- RDBMS release number

/* The following boolean constants follow a naming convention. Each
constant gives a name for a boolean expression. For example,
ver_le_9_1 represents version <= 9 and release <= 1
ver_le_10_2 represents version <= 10 and release <= 2
ver_le_10 represents version <= 10

A typical usage of these boolean constants is

$if dbms_db_version.ver_le_10 $then
version 10 and ealier code
$elsif dbms_db_version.ver_le_11 $then
version 11 code
$else
version 12 and later code
$end

This code structure will protect any reference to the code
for version 12. It also prevents the controlling package
constant dbms_db_version.ver_le_11 from being referenced
when the program is compiled under version 10. A similar
observation applies to version 11. This scheme works even
though the static constant ver_le_11 is not defined in
version 10 database because conditional compilation protects
the $elsif from evaluation if the dbms_db_version.ver_le_10 is
TRUE.
*/

ver_le_9_1 constant boolean := FALSE;
ver_le_9_2 constant boolean := FALSE;
ver_le_9 constant boolean := FALSE;
ver_le_10_1 constant boolean := FALSE;
ver_le_10_2 constant boolean := FALSE;
ver_le_10 constant boolean := FALSE;
ver_le_11_1 constant boolean := TRUE;
ver_le_11 constant boolean := TRUE;

end dbms_db_version;


● Oracle11g R2 11.2 の DBMS_DB_VERSION

package dbms_db_version is
version constant pls_integer := 11; -- RDBMS version number
release constant pls_integer := 2; -- RDBMS release number

/* The following boolean constants follow a naming convention. Each
constant gives a name for a boolean expression. For example,
ver_le_9_1 represents version <= 9 and release <= 1
ver_le_10_2 represents version <= 10 and release <= 2
ver_le_10 represents version <= 10

A typical usage of these boolean constants is

$if dbms_db_version.ver_le_10 $then
version 10 and ealier code
$elsif dbms_db_version.ver_le_11 $then
version 11 code
$else
version 12 and later code
$end

This code structure will protect any reference to the code
for version 12. It also prevents the controlling package
constant dbms_db_version.ver_le_11 from being referenced
when the program is compiled under version 10. A similar
observation applies to version 11. This scheme works even
though the static constant ver_le_11 is not defined in
version 10 database because conditional compilation protects
the $elsif from evaluation if the dbms_db_version.ver_le_10 is
TRUE.
*/

ver_le_9_1 constant boolean := FALSE;
ver_le_9_2 constant boolean := FALSE;
ver_le_9 constant boolean := FALSE;
ver_le_10_1 constant boolean := FALSE;
ver_le_10_2 constant boolean := FALSE;
ver_le_10 constant boolean := FALSE;
ver_le_11_1 constant boolean := FALSE;
ver_le_11_2 constant boolean := TRUE;
ver_le_11 constant boolean := TRUE;

end dbms_db_version;

version 12 and later codeなんて箇所、いいですね〜w


PL/SQL de Conditional Compile #1
PL/SQL de Conditional Compile #2
PL/SQL de Conditional Compile #3
PL/SQL de Conditional Compile #4
PL/SQL de Conditional Compile #5

| | コメント (0) | トラックバック (0)

2010年3月24日 (水)

PL/SQLでCASE式を使わずに条件分岐 #3

PL/SQLでCASE式を使わずに条件分岐の3回目です。

前回作成したプロシージャをパッケージ化し、コマンドを外部から与えられるようにしてみます。

前回作成したsimpleCommandプロシージャを削除してパッケージ化します。store()プロシージャでコマンドを登録、execute()プロシージャで実行です。

SCOTT> drop procedure simpleCommand;

プロシージャが削除されました。

SCOTT>
SCOTT> l
1 CREATE OR REPLACE PACKAGE simpleCommand
2 AS
3 PROCEDURE store(
4 commandName IN VARCHAR2
5 ,commandSource IN command
6 );
7 --
8 PROCEDURE execute(
9 commandName IN VARCHAR2
10 );
11* END;
SCOTT> /

パッケージが作成されました。

SCOTT>
SCOTT> l
1 CREATE OR REPLACE PACKAGE BODY simpleCommand
2 AS
3 TYPE command_type IS TABLE OF command INDEX BY VARCHAR2(4000);
4 commands command_type;
5 --
6 PROCEDURE store(
7 commandName IN VARCHAR2
8 ,commandSource IN command
9 )
10 IS
11 BEGIN
12 commands(commandName) := commandSource;
13 END;
14 --
15 PROCEDURE execute(
16 commandName IN VARCHAR2
17 )
18 IS
19 BEGIN
20 commands(commandName).execute();
21 EXCEPTION
22 WHEN NO_DATA_FOUND THEN
23 DBMS_OUTPUT.PUT_LINE('そんなコマンド知りません! >< ');
24 END;
25* END;
SCOTT> /

パッケージ本体が作成されました。

SCOTT>

では早速試してみます。まず、コマンドを登録!

SCOTT> l
1 BEGIN
2 simpleCommand.store(
3 'いま何時?',
4 Command(
5 'BEGIN '||
6 'DBMS_OUTPUT.PUT_LINE(''現在時刻:''||TO_CHAR(systimestamp, ''yyyy-mm-dd hh24:mi:ss''));'||
7 'END;'
8 )
9 );
10 simpleCommand.store(
11 '従業員数は?',
12 Command(
13 'DECLARE '||
14 'numberOfEmployees NUMBER;'||
15 'BEGIN '||
16 'SELECT COUNT(*) INTO numberOFEmployees FROM emp;'||
17 'DBMS_OUTPUT.PUT_LINE(''従業員数:''||TO_CHAR(numberOfEmployees));'||
18 'END;'
19 )
20 );
21 simpleCommand.store(
22 '従業員リスト',
23 Command(
24 'DECLARE '||
25 'CURSOR empList IS '||
26 'SELECT '||
27 'empno '||
28 ',ename '||
29 ',dname '||
30 'FROM '||
31 'emp JOIN dept '||
32 'ON emp.deptno = dept.deptno '||
33 'ORDER BY '||
34 'dname, empno, ename;'||
35 'BEGIN '||
36 'FOR empRec IN empList LOOP '||
37 'DBMS_OUTPUT.PUT_LINE(empRec.empno || '' '' || empRec.ename || '' '' || empRec.dname);'||
38 'END LOOP; '||
39 'END;'
40 )
41 );
42* END;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT>


実行!.これで適用範囲を広げらるかも・・・w

SCOTT> set serveroutput on size 100000
SCOTT>
SCOTT> exec simpleCommand.execute('従業員リスト');
7782 CLARK ACCOUNTING
7839 KING ACCOUNTING
7934 MILLER ACCOUNTING
7369 SMITH RESEARCH
7566 JONES RESEARCH
7788 SCOTT RESEARCH
7876 ADAMS RESEARCH
7902 FORD RESEARCH
7499 ALLEN SALES
7521 WARD SALES
7654 MARTIN SALES
7698 BLAKE SALES
7844 TURNER SALES
7900 JAMES SALES

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec simpleCommand.execute('いま何時?');
現在時刻:2010-03-20 23:53:22

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec simpleCommand.execute('従業員数は?');
従業員数:14

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec simpleCommand.execute('ほげほげ');
そんなコマンド知りません! ><

PL/SQLプロシージャが正常に完了しました。

SCOTT>




・バックナンバー
PL/SQLでCASE式を使わずに条件分岐 #1
PL/SQLでCASE式を使わずに条件分岐 #2

| | コメント (0) | トラックバック (0)

2010年3月23日 (火)

PL/SQLでCASE式を使わずに条件分岐 #2

PL/SQLでCASE式を使わずに条件分岐の2回目です。

前回作成したプロシージャから、とにかくCASE式を無くてみましょ。

まず、以下の様なオブジェクト型を定義して・・・・・

SCOTT> l
1 CREATE OR REPLACE TYPE command AS OBJECT
2 (
3 commandStr CLOB,
4 MEMBER PROCEDURE execute
5* );
SCOTT> /

型が作成されました。

SCOTT>
SCOTT> l
1 CREATE OR REPLACE TYPE BODY command
2 AS
3 MEMBER PROCEDURE execute
4 IS
5 BEGIN
6 EXECUTE IMMEDIATE commandStr;
7 END;
8* END;
SCOTT> /

型本体が作成されました。

SCOTT>

PL/SQLの結合配列のINDEXにVARCHAR2型を利用すればハッシュテーブルと同じように使えることを利用して実行するコマンドはCLOBに格納してEXECUTE IMMEDIATE文で実行しちゃうという方法です。実行するコマンドは外部から与えるようにすることもできますが、とりあえず内部に直書き。

SCOTT> l
1 CREATE OR REPLACE PROCEDURE simpleCommand
2 (
3 commandName IN VARCHAR2
4 )
5 IS
6 TYPE command_type IS TABLE OF command INDEX BY VARCHAR2(4000);
7 commands command_type;
8 --
9 PROCEDURE init IS
10 BEGIN
11 commands('いま何時?')
12 := Command(
13 'BEGIN '||
14 'DBMS_OUTPUT.PUT_LINE(''現在時刻:''||TO_CHAR(systimestamp, ''yyyy-mm-dd hh24:mi:ss''));'||
15 'END;'
16 );
17 commands('従業員数は?')
18 := Command(
19 'DECLARE '||
20 'numberOfEmployees NUMBER;'||
21 'BEGIN '||
22 'SELECT COUNT(*) INTO numberOFEmployees FROM emp;'||
23 'DBMS_OUTPUT.PUT_LINE(''従業員数:''||TO_CHAR(numberOfEmployees));'||
24 'END;'
25 );
26 commands('従業員リスト')
27 := Command(
28 'DECLARE '||
29 'CURSOR empList IS '||
30 'SELECT '||
31 'empno '||
32 ',ename '||
33 ',dname '||
34 'FROM '||
35 'emp JOIN dept '||
36 'ON emp.deptno = dept.deptno '||
37 'ORDER BY '||
38 'dname, empno, ename;'||
39 'BEGIN '||
40 'FOR empRec IN empList LOOP '||
41 'DBMS_OUTPUT.PUT_LINE(empRec.empno || '' '' || empRec.ename || '' '' || empRec.dname);'||
42 'END LOOP; '||
43 'END;'
44 );
45 END;
46 --
47 BEGIN
48 init();
49 --
50 commands(commandName).execute();
51 EXCEPTION
52 WHEN NO_DATA_FOUND THEN
53 DBMS_OUTPUT.PUT_LINE('そんなコマンド知りません! >< ');
54* END;
SCOTT>
SCOTT> /

プロシージャが作成されました。

SCOTT>


できた!!! :)

SCOTT> set serveroutput on size 100000
SCOTT> exec simpleCommand('いま何時?');
現在時刻:2010-03-20 15:50:27

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec simpleCommand('従業員リスト');
7782 CLARK ACCOUNTING
7839 KING ACCOUNTING
7934 MILLER ACCOUNTING
7369 SMITH RESEARCH
7566 JONES RESEARCH
7788 SCOTT RESEARCH
7876 ADAMS RESEARCH
7902 FORD RESEARCH
7499 ALLEN SALES
7521 WARD SALES
7654 MARTIN SALES
7698 BLAKE SALES
7844 TURNER SALES
7900 JAMES SALES

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec simpleCommand('従業員数は?');
従業員数:14

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec simpleCommand('ほげほげ');
そんなコマンド知りません! ><

PL/SQLプロシージャが正常に完了しました。

SCOTT>

次回はコマンドを外部から与えられるように改造してみます。 次回へつづく。


・バックナンバー
PL/SQLでCASE式を使わずに条件分岐 #1

| | コメント (0) | トラックバック (0)

2010年3月22日 (月)

PL/SQLでCASE式を使わずに条件分岐 #1

随分前ですが、html5-developers-jpのディスカッションでJavaScriptでswitch文を使わずに条件分岐という話題があって、あ、そうそう、PL/SQLでもできるよね、って瞬間的に思っていたのですが、忙しくて、ず〜っと放置してたネタでございます。:)

今回は使うのは、Oracle11g R2 for Linux x86。

SCOTT> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

まずは、CASE式を使って書けば以下のような感じになるよね! ってところから。

SCOTT> l
1 CREATE OR REPLACE PROCEDURE simpleCommand
2 (
3 commandName IN VARCHAR2
4 )
5 IS
6 CURSOR empList IS
7 SELECT
8 empno
9 ,ename
10 ,dname
11 FROM
12 emp JOIN dept
13 ON emp.deptno = dept.deptno
14 ORDER BY
15 dname, empno, ename
16 ;
17 --
18 numberOfEmployees NUMBER;
19 BEGIN
20 CASE commandName
21 WHEN 'いま何時?' THEN
22 DBMS_OUTPUT.PUT_LINE('現在時刻:'||TO_CHAR(systimestamp, 'yyyy-mm-dd hh24:mi:ss'));
23 WHEN '従業員数は?' THEN
24 SELECT COUNT(*) INTO numberOFEmployees FROM emp;
25 DBMS_OUTPUT.PUT_LINE('従業員数:'||TO_CHAR(numberOfEmployees));
26 WHEN '従業員リスト' THEN
27 FOR empRec IN empList LOOP
28 DBMS_OUTPUT.PUT_LINE(empRec.empno || ' ' || empRec.ename || ' ' || empRec.dname);
29 END LOOP;
30 ELSE
31 DBMS_OUTPUT.PUT_LINE('そんなコマンド知りません! >< ');
32 END CASE;
33 --
34* END;
SCOTT> /

プロシージャが作成されました。

SCOTT>
SCOTT> set serveroutput on size 100000
SCOTT> exec simpleCommand('いま何時?');
現在時刻:2010-03-21 00:10:17

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec simpleCommand('従業員リスト');
7782 CLARK ACCOUNTING
7839 KING ACCOUNTING
7934 MILLER ACCOUNTING
7369 SMITH RESEARCH
7566 JONES RESEARCH
7788 SCOTT RESEARCH
7876 ADAMS RESEARCH
7902 FORD RESEARCH
7499 ALLEN SALES
7521 WARD SALES
7654 MARTIN SALES
7698 BLAKE SALES
7844 TURNER SALES
7900 JAMES SALES

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec simpleCommand('従業員数は?');
従業員数:14

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec simpleCommand('ほげほげ');
そんなコマンド知りません! ><

PL/SQLプロシージャが正常に完了しました。

SCOTT>


上記のようなPL/SQLプロシージャ中のCASE式を排除してコマンドパターンっぽくできるのか。。。方法はいろいろあるな〜と思いつつ、PL/SQLの結合配列を使う方法で試してみた。
ということで、次回へつづく :) …

| | コメント (0) | トラックバック (0)

2010年2月20日 (土)

UTL_FILE.FCOPY()とかFRENAME()とか

UTL_FILE.FRENAME()プロシージャとか、UTL_FILE.FCOPY()プロシージャって何かと便利っていうお話。

テストでOracleデータベース側に格納されたデータと紐づけながら画像ファイルを複製してみたり、名称を紐づけたりするときにも重宝するプロシージャなんですよね。
特に、shellなどがないWindows環境で画像を大量に複製したりする場合にはかなり便利だなと。

まずは、OS上のディレクトリとの紐付け。ディレクトリオブジェクトを作成しておきます。(今回はSCOTTユーザにディレクトリオブジェクトを作成できるように権限を付与しておきました)

SCOTT> 
SCOTT> create directory ora_dir as '/home/oracle/ora_dir';

ディレクトリが作成されました。

SCOTT>

UTL_FILE.FRENAME()プロシージャは、Linux/Unixのmvコマンドライク。
以下は、リネーム後のファイル名(hogehoge.png)と同じファイルが既に存在する場合には置き換えない場合の例。overwriteパラメータをFALSE(デフォルト)にしてあげる。

SCOTT> !ls -l ora_dir
-rw-r--r-- 1 oracle oinstall 28800 2月 20 09:26 hogehoge.png
-rw-r--r-- 1 oracle oinstall 28800 2月 19 23:57 test.png

SCOTT> l
1 BEGIN
2 UTL_FILE.FRENAME('ORA_DIR','test.png','ORA_DIR','hogehoge.png',FALSE);
3* END;
SCOTT> /
BEGIN
*
行1でエラーが発生しました。:
ORA-29292: ファイル名の変更操作に失敗しました。 ORA-06512:
"SYS.UTL_FILE", 行348
ORA-06512: "SYS.UTL_FILE", 行1290
ORA-06512: 行2

SCOTT> !ls -l ora_dir
-rw-r--r-- 1 oracle oinstall 28800 2月 20 09:26 hogehoge.png
-rw-r--r-- 1 oracle oinstall 28800 2月 19 23:57 test.png


以下は、リネーム後のファイル名(hogehoge.png)と同じファイルが既に存在する場合に置き換えてしまう例。overwriteパラメータをTRUEにしてあげる。

SCOTT> !ls -l ora_dir
-rw-r--r-- 1 oracle oinstall 28800 2月 20 09:26 hogehoge.png
-rw-r--r-- 1 oracle oinstall 28800 2月 19 23:57 test.png

SCOTT> l
1 BEGIN
2 UTL_FILE.FRENAME('ORA_DIR','test.png','ORA_DIR','hogehoge.png',TRUE);
3* END;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT> !ls -l ora_dir
-rw-r--r-- 1 oracle oinstall 28800 2月 19 23:57 hogehoge.png

SCOTT>


せっかくUTL_FILE.FRENAME()プロシージャを試したので、次いでにUTL_FILE.FCOPY()でファイルコピーも!
といきたいところですが、UTL_FILE.FCOPY()プロシージャはテキストファイルのコピーしか行えない!(パラメータからも想像できると思うけど)
では、画像ファイルなどのバイナリファイルはどうすんのさ!オラクルさん!。ってことで、そのようなプロシージャは無いので自前で作りましょ。
以下は、そのサンプル、バイナリモードで画像ファイルを読み込んでバイナリモードで別ファイルへ書き出す。だたそれだけ。

SCOTT> !ls -l ora_dir 
-rw-r--r-- 1 oracle oinstall 28800 2月 19 23:13 test2.png

SCOTT>
SCOTT> l
1 DECLARE
2 src_file UTL_FILE.FILE_TYPE;
3 dst_file UTL_FILE.FILE_TYPE;
4 buffer RAW(32767);
5 BEGIN
6 src_file := UTL_FILE.FOPEN('ORA_DIR','test2.png', 'rb', 32767);
7 dst_file := UTL_FILE.FOPEN('ORA_DIR','hogehogehoge.png', 'wb', 32767);
8 LOOP
9 BEGIN
10 UTL_FILE.GET_RAW(src_file, buffer, 32767);
11 UTL_FILE.PUT_RAW(dst_file, buffer, TRUE);
12 EXCEPTION
13 WHEN NO_DATA_FOUND THEN
14 EXIT;
15 END;
16 END LOOP;
17 UTL_FILE.FCLOSE(src_file);
18 UTL_FILE.FCLOSE(dst_file);
19* END;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT> !ls -l ora_dir
-rw-r--r-- 1 oracle oinstall 28800 2月 19 23:57 hogehogehoge.png
-rw-r--r-- 1 oracle oinstall 28800 2月 19 23:13 test2.png

SCOTT>

| | コメント (2) | トラックバック (0)

2009年9月 6日 (日)

PL/SQL で Python Challenge Level 18 - 完

ということで、Python Challenge Level18の最終回。
前回報告した通り level 18 はPL/SQLだけで解けます。今回は問題の元ネタの抽出と回答を抽出した後の確認はOSに付属している機能を使ったが大切なのは問題の元ネタから解答を抽出する所なので。

SQL*Plusから実行したストアドプロシージャで問題を解いたところ....例によってヒントになりそうな部分はもやもやさせてます。 :)


Level18_exec

ヒントになりまくりの答えのスナップショット。(これ以外にも私のブログにヒントになる記事もあるのだが・・・・・それは書きませんよ。。。。)

ちなみに絵を見れば分かると思いますが、MacOS XからX11のX forwordingを使って今回利用したLinuxのDesktopを表示/操作しています。X11のxtermからssh -Y user@hostで接続してgnome-sessionを実行しているだけ。


Level18_eureka

Python Challenge Level19へつづく!(?)

| | コメント (0) | トラックバック (0)

2009年9月 2日 (水)

PL/SQL で Python Challenge Level 18 解けた

一年以上間が空いてしまったが・・・Python Challenge Level18はPL/SQLだけで解けますよん。ヒントになるようなならないようなモヤモヤした記事は明日にでも。。

| | コメント (2) | トラックバック (0)

2009年8月31日 (月)

PL/SQL de O(ND) Difference Algorithm

かなり久々ですが、まあ、シリーズもののネタを毎日アップするのもなかなか難しい状況なので単発ネタでも。

ということで今回は、PL/SQLでAn O(ND) Difference Algorithmを実装して頭の体操。

文書比較のアルゴリズムとしてはAn O(NP) Sequence Comparison Algorithmが効率は良いのだが、先日javascriptで書かれたO(ND)のコードを見つけたことをキッカケにPL/SQLで写経したくなったというわけ。

文書比較アルゴリズムは2、3年くらい前、文書比較アブゴリズムdiff(1)/diff(2)/diff(3)等をみたことがあったが、最近pyhthonやらjavascriptのコードを目にするようになり (^^) な顔して眺めていて時間があったらPL/SQLで遊んでみようと思っていた。。他の言語でやってもMac De Oracle的にはおもしろくないので。

ちなみに、pythonだどdifflib使えば文書比較はできるので実際新たに書く必要はそんなにないんじゃなかろうかとも思うわけですが、私のようにわざわざPL/SQLで書いてみようと思う人間もいるわけで、頭の体操にはいいと思います!。理解するのは大変だったけど。wwww

最近見つけたO(ND)やO(NP)に関するブログ等のリンクは以下。

レコメンデーションとエディットグラフ
diff O(np) javascript implementation
"An O(NP) Sequence Comparison Algorithm" with Python
"An O(NP) Sequence Comparison Algorithm" with Python の添削
Javascriptでdiffる ( with 形態素解析 )
google-diff-match-patch


今回はレコメンデーションとエディットグラフにあるO(ND)コードを写経してPL/SQLでやってみた。O(NP)も集中できる時間があったらやってみたい。。。脳トレにも丁度いいかもよ。。。
※Oracle11g 11.1.0.7.0を使ったが、Oracle10g 10.1.0.3.0以上なら動作するはず。。。。(^^;;;

まずは、結果からどうぞ。O(ND)をPL/SQLストアドファンクション化し、SQLから実行できるようにしてあります。また、pythonのdifflibにあるdifferクラスで利用されている差異コード('?'を除く)を出力するようにしてあります。)

SCOTT> set timi on
SCOTT> l
1 SELECT
2 '"' || diffs.code || diffs.string || '"' AS "diff O(ND) results"
3 FROM
4 TABLE(
5 SELECT diffOND('BFEABD', 'ABCDA') from dual
6 ) diffs
7 ORDER BY
8* diffs.seq DESC
SCOTT> /

diff O(ND) results
--------------------------------------------------------------------------------
"- B"
"- F"
"- E"
" A"
" B"
"+ C"
" D"
"+ A"

8行が選択されました。

経過: 00:00:00.00

SCOTT>
SCOTT> l
1 SELECT
2 '"' || diffs.code || diffs.string || '"' AS "diff O(ND) results"
3 FROM
4 TABLE(
5 SELECT diffOND('aaebdd ', 'aedajkd') from dual
6 ) diffs
7 ORDER BY
8* diffs.seq DESC
SCOTT> /

diff O(ND) results
--------------------------------------------------------------------------------
" a"
"- a"
" e"
"- b"
" d"
"+ a"
"+ j"
"+ k"
" d"
"- "

10行が選択されました。

経過: 00:00:00.00

SCOTT>
SCOTT> l
1 SELECT
2 '"' || diffs.code || diffs.string || '"' AS "diff O(ND) results"
3 FROM
4 TABLE(
5 SELECT diffOND('ABCDE', 'ABCDE') from dual
6 ) diffs
7 ORDER BY
8* diffs.seq DESC
SCOTT> /

diff O(ND) results
--------------------------------------------------------------------------------
" A"
" B"
" C"
" D"
" E"

経過: 00:00:00.00

SCOTT>
SCOTT> l
1 SELECT
2 '"' || diffs.code || diffs.string || '"' AS "diff O(ND) results"
3 FROM
4 TABLE(
5 SELECT diffOND('あいうえお','かきくけこ') from dual
6 ) diffs
7 ORDER BY
8* diffs.seq DESC
SCOTT> /

diff O(ND) results
--------------------------------------------------------------------------------
"- あ"
"- い"
"- う"
"- え"
"- お"
"+ か"
"+ き"
"+ く"
"+ け"
"+ こ"

10行が選択されました。

経過: 00:00:00.00

SCOTT>

PL/SQLのコードは以下の通り。

SCOTT> !cat ond.sql

CREATE OR REPLACE TYPE vRecType AS OBJECT
(
x NUMBER
,y NUMBER
,parent ANYDATA
);
/
show errors

BEGIN
FOR functionNames
IN (SELECT object_name FROM USER_OBJECTS WHERE object_name='DIFFOND' AND OBJECT_TYPE='FUNCTION')
LOOP
EXECUTE IMMEDIATE 'DROP FUNCTION ' || functionNames.object_name;
END LOOP;

FOR typeNames
IN (SELECT type_name FROM USER_TYPES WHERE type_name='DIFFLISTTYPE')
LOOP
EXECUTE IMMEDIATE 'DROP TYPE ' || typeNames.type_name;
END LOOP;
END;
/

CREATE OR REPLACE TYPE diffType AS OBJECT
(
seq NUMBER
,code CHAR(2)
,string VARCHAR2(32767)
);
/
show errors

CREATE OR REPLACE TYPE diffListType AS TABLE OF diffType;
/
show errors

CREATE FUNCTION diffOND
(
str1 IN VARCHAR2
,str2 IN VARCHAR2
)
RETURN diffListType
IS
STAT_INIT CONSTANT PLS_INTEGER := 0;
STAT_X CONSTANT PLS_INTEGER := 1;
STAT_Y CONSTANT PLS_INTEGER := 2;

TYPE vType IS TABLE OF vRecType;
v vType := vType();

FUNCTION isVRecNotEmpty(
vRec IN vRecType
)
RETURN BOOLEAN
IS
BEGIN
RETURN (CASE WHEN vRec.x IS NULL AND vRec.y IS NULL AND vRec.parent IS NULL THEN FALSE ELSE TRUE END);
END isVRecNotEmpty;

FUNCTION getDirection
(
vMinus IN vRecType
,vPlus IN vRecType
)
RETURN PLS_INTEGER
IS
BEGIN
IF NOT isVRecNotEmpty(vMinus) AND NOT isVRecNotEmpty(vPlus) THEN
RETURN STAT_INIT;
END IF;

IF NOT isVRecNotEmpty(vMinus) THEN
RETURN STAT_X;
END IF;

IF NOT isVRecNotEmpty(vPlus) THEN
RETURN STAT_Y;
END IF;

RETURN (CASE WHEN vMinus.x < vPlus.x THEN STAT_X ELSE STAT_Y END);
END getDirection;

FUNCTION OND
(
str1 IN VARCHAR2
,str2 IN VARCHAR2
)
RETURN vRecType
IS
offset PLS_INTEGER;
kMax PLS_INTEGER;
kMin PLS_INTEGER;
k PLS_INTEGER;
vIndex PLS_INTEGER;
x PLS_INTEGER;
y PLS_INTEGER;
str1Len PLS_INTEGER;
str2Len PLS_INTEGER;
parent vRecType;
BEGIN
str1Len := LENGTH(str1);
str2Len := LENGTH(str2);
v.EXTEND(str1Len + str2Len + 3);
offset:= str2Len + 2;

FOR d IN 0..str1Len + str2Len LOOP
kMax := (CASE WHEN d <= str1Len THEN d ELSE str1Len - (d - str1Len) END);
kMin := (CASE WHEN d <= str2Len THEN d ELSE str2Len - (d - str2Len) END);

k := kMin * -1;
WHILE k <= kMax LOOP
vIndex := offset + k;
CASE getDirection(v(vIndex-1), v(vIndex+1))
WHEN STAT_INIT THEN
x := 0;
y := 0;
parent := vRecType(0, 0, NULL);
WHEN STAT_X THEN
x := v(vIndex+1).x;
y := v(vIndex+1).y + 1;
parent := v(vIndex+1);
WHEN STAT_Y THEN
x := v(vIndex-1).x + 1;
y := v(vIndex-1).y;
parent := v(vIndex-1);
END CASE;

-- snake
WHILE (x < str1Len AND y < str2Len)
AND (SUBSTR(str1, x+1, 1) = SUBSTR(str2, y+1, 1))
LOOP
x := x + 1;
y := y + 1;
END LOOP;
v(vIndex) := vRecType(x, y, ANYDATA.ConvertObject(parent));

IF str1Len <= x AND str2Len <= y THEN
RETURN v(vIndex);
END IF;

k := k + 2;
END LOOP;
END LOOP;
END OND;

FUNCTION diff
(
str1 IN VARCHAR2
,str2 IN VARCHAR2
)
RETURN diffListType
IS
endPoint vRecType;
parent vRecType;
diff_x PLS_INTEGER;
diff_y PLS_INTEGER;
same_len PLS_INTEGER;
isSuccessGetObject PLS_INTEGER;
diffs diffListType := diffListType();
seq PLS_INTEGER := 0;
BEGIN
endPoint := OND(str1, str2);
WHILE endPoint.parent IS NOT NULL LOOP
IF ANYDATA.getObject(endPoint.parent, parent) != DBMS_TYPES.SUCCESS THEN
RAISE_APPLICATION_ERROR(-20000,'DBMS_TYPES.NO_DATA');
END IF;

diff_x := endPoint.x - parent.x;
diff_y := endPoint.y - parent.y;
same_len := CASE WHEN diff_x <= diff_y THEN diff_x ELSE diff_y END;

FOR i IN 0..same_len-1 LOOP
-- common
diffs.EXTEND();
seq := seq + 1;
diffs(diffs.COUNT()) := diffType(seq, ' ', SUBSTR(str1, endPoint.x-i, 1));
END LOOP;

IF diff_y != diff_x THEN
diffs.EXTEND();
seq := seq + 1;
IF diff_y < diff_x THEN
-- del
diffs(diffs.COUNT()) := diffType(seq, '- ', SUBSTR(str1, parent.x+1, 1));
ELSE
-- add
diffs(diffs.COUNT()) := diffType(seq, '+ ', SUBSTR(str2, parent.y+1, 1));
END IF;
END IF;

endPoint := parent;
END LOOP;

RETURN diffs;
END diff;
BEGIN
RETURN diff(str1, str2);
END diffOND;
/
show errors

Enjoy PL/SQL! というより Enjoy Programming! のほうがいいか。。

| | コメント (0) | トラックバック (0)

2009年6月 8日 (月)

OraTweet 1.0 あそび始めた。

OraTweet v1.0が公開されたということなので早速試してみた。といってもちょっとだけ。細かいところはみてないけどとりあえずは日本語も使えるみたい。ちょうどPL/SQL gatewayからTwitter APIを使って遊んでみようと思っていたところだから少し遊ぶか。
Oratweet01_2

Oratweet02

| | コメント (0) | トラックバック (0)

2009年6月 5日 (金)

Leopard de Oracle10g R2 (Intel x86-64) #18 (APEX3.2と遊ぶ #11)

Oracle10g R2 10.2.0.4.0 for MacOSX (Intel x68-64)でAPEX3.2と遊ぶの第十話。

Oracle HTTP ServerとPL/SQL gatewayをORACLE_HOMEごとPowerMacからIntel Mac移動して、Intel Macへインストール、構築したOracle 10g R2 10.2.0.4.0 for MacOSX(Intel x86-64) + APEX3.2へアクセスしちゃいます。RosettaがPowerPC版のOracle HTTP Server mod_plsqlをIntel Mac上で動かしてくれます。


まず、MacBook Proのオラクル所有者の環境変数の設定などはLeopard de Oracle10g R2 (Intel x86-64) #2の設定に加え、Oracle HTTP Server向けaliasと環境変数を追加。
ちなみに、/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apexをIntel Mac上でのAPExのHOMEディレクトリとしてOracle HTTP Serverを起動、停止スクリプトをaliasとして定義。(Oracle 10g R1 10.1.0.3.0 for MacOSXのCompanionCDでインストールされるOracle HTTP Serverは ORACLE_HOME(Oracle HTTP Serverの)/opmn/bin/opmnctl stopall 又は startallではなくORACLE_HOME(Oracle HTTP Serverの)/Apache/Apache/bin/apachectl start又はstopで起動/停止できます。)

guppy:˜ oracle$ cat .bashrc
alias ll='ls -lv'
alias startohs='$ORACLE_HTMLDB_HOME/bin/apachectl start'
alias stopohs='$ORACLE_HTMLDB_HOME/bin/apachectl stop'

export LANG=ja_JP.UTF-8
export ORACLE_BASE=/Users/shared/u01/app/oracle
export ORACLE_SID=leopard1
export ORACLE_HOME=$ORACLE_BASE/oracle/product/10.2.0/db_1
export NLS_LANG=Japanese_Japan.AL32UTF8
export DYLD_LIBRARY_PATH=$ORACLE_HOME/lib:$ORACLE_HOME/rdbms/lib:$ORACLE_HOME/network/lib:$DYLD_LIBRARY_PATH
export PATH=$ORACLE_HOME/bin:$PATH

#for Oracle11g and Jdeveloper Oracle Middleware HOME
export ORACLE_MIDDLEWARE_HOME=/Users/Shared/Oracle/Middleware

#for Oracle10g R1 Oracle HTTP ServerHome (include mod_plsql)
export ORACLE_HTMLDB_HOME=/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache
guppy:˜ oracle$

次に、PowerPC上でzipしたORACLE HTTP ServerのORACLE_HOMEディレクトリ以下を丸ごとIntel Mac上のOracle HTTP ServerのあたらしいHOMEディレクトリへ移動します。移動方法はrcpでもいいし、環境によってはscpでもいいしUSBメモリ経由でもmobileme経由でもお好きな方法でIntel Macへコピー/解凍します。PowerPC上のORACLE HTTP Serverホームディレクトリ以下は不要なのでHOMEディレクトリごと削除するもよし、ちゃんとOUIで削除してもいいですよん。
以下、MacBook Pro上で解凍した状態。MacBook Pro上のあたらしいHOMEディレクトリは、/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex



1

APEX3.2のimagesディレクトリのコピー。
APEX3.2のimagesディレクトリでOracle HTTP Serverのホームディレクトリ/marvel以下にあるimagesディレクトリを置き換えます。
この作業はAPEXのアップデート作業でもよく作業なのでお忘れなく。HTML DB1.5をAPEX3.2にアップデートしたようなものなので。

guppy:apex oracle$ pwd
/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/marvel
guppy:marvel oracle$ ls
10ins.sql core doc ins.sql jlib readme.html upgrade.sql
builder coreins.sql images install.lst logs sbs utilities
guppy:marvel oracle$ mv images images_htmldb_1_5
guppy:marvel oracle$ cp -rf /Users/oracle/Downloads/apex/images .
guppy:marvel oracle$


.confファイルの変更
ここからがメイン。PowerPC上でインストール構築したので各種.confファイルなどのパスはホスト名がPowerPC上の値に設定されています。それら全てを移動してきたMacBook Pro(Intel x86)上の値に変更していきます。
最初はOracle HTTP Server向けコンフィグファイルから。(全てのconfファイルを確認し要変更と確定できた変更前の*.confファイルは、*.conf.15として退避しておくことにします。)

/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apexは、MacBook Pro上でのOracle HTTP Serverのホームディレクトリ。


guppy:conf oracle$ pwd

/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf
guppy:conf oracle$
guppy:conf oracle$ ll
total 680
-rwxr-xr-x 1 oracle oinstall 348 11 16 2004 access.conf
-rwxr-xr-x 1 oracle oinstall 348 11 16 2004 access.conf.default
-rw------- 1 oracle oinstall 1623 5 18 14:16 dms.conf
-rw------- 1 oracle oinstall 1633 5 18 14:14 dms.conf.15
-rw------- 1 oracle oinstall 1626 7 2 2004 dms.conf.sbs
-rwxr-xr-x 1 oracle oinstall 41721 5 18 14:41 httpd.conf
-rwxr-xr-x 1 oracle oinstall 42011 5 18 14:16 httpd.conf.15
-rwxr-xr-x 1 oracle oinstall 42011 5 17 12:23 httpd.conf.default
-rwxr-xr-x 1 oracle oinstall 39710 12 17 2004 httpd.conf.tmp
-rwxr-xr-x 1 oracle oinstall 12965 11 16 2004 magic
-rwxr-xr-x 1 oracle oinstall 12965 11 16 2004 magic.default
-rwxr-xr-x 1 oracle oinstall 15161 11 16 2004 mime.types
-rwxr-xr-x 1 oracle oinstall 15161 11 16 2004 mime.types.default
-rw-r--r-- 1 oracle oinstall 484 5 18 14:42 mod_oc4j.conf
-rw-r--r-- 1 oracle oinstall 490 5 18 14:41 mod_oc4j.conf.15
-rw-r--r-- 1 oracle oinstall 490 5 17 12:25 mod_oc4j.conf.default
-rw-r--r-- 1 oracle oinstall 503 7 2 2004 mod_oc4j.conf.tmp
-rwxr-xr-x 1 oracle oinstall 779 5 17 12:23 mod_osso.conf
-rwxr-xr-x 1 oracle oinstall 779 12 17 2004 mod_osso.conf.tmp
-rwxr-xr-x 1 oracle oinstall 323 5 17 12:23 ohs_opmn.xml
-rwxr-xr-x 1 oracle oinstall 323 12 17 2004 ohs_opmn.xml.sbs
-rwxr-xr-x 1 oracle oinstall 566 5 18 14:44 ohstarget.xml
-rwxr-xr-x 1 oracle oinstall 575 5 18 14:44 ohstarget.xml.15
-rwxr-xr-x 1 oracle oinstall 585 12 17 2004 ohstarget.xml.tmp
-rwxr-xr-x 1 oracle oinstall 197 5 18 14:45 oracle_apache.conf
-rwxr-xr-x 1 oracle oinstall 217 5 18 14:45 oracle_apache.conf.15
drwxr-xr-x 2 oracle oinstall 68 5 17 12:23 osso
-rwxr-xr-x 1 oracle oinstall 357 11 16 2004 srm.conf
-rwxr-xr-x 1 oracle oinstall 357 11 16 2004 srm.conf.default
-rwxr-xr-x 1 oracle oinstall 7861 5 18 14:51 ssl.conf
-rwxr-xr-x 1 oracle oinstall 8016 5 18 14:46 ssl.conf.15
-rwxr-xr-x 1 oracle oinstall 7192 12 17 2004 ssl.conf.tmp
drwxr-xr-x 4 oracle oinstall 136 5 17 12:23 ssl.crl
drwxr-xr-x 3 oracle oinstall 102 5 17 12:23 ssl.wlt
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$ ls *.*.15
dms.conf.15 httpd.conf.15 mod_oc4j.conf.15
ohstarget.xml.15 oracle_apache.conf.15 ssl.conf.15

guppy:conf oracle$
guppy:conf oracle$

以下、変更したconfファイルのdiff。


PowerPC上のORACLE_HOMEのパスとIntel Mac上のパスが異なるのでパス関連及び、ホスト名関連は変更対象。


例えば、PowerMac G5上でOracle HTTP Server用のORACLE_HOMEは

/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex


だったが、Intel Mac上では
/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex
とした。

guppy:conf oracle$
guppy:conf oracle$ diff dms.conf.15 dms.conf
30c30
< Alias /index.html /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/htdocs/index.html
---
> Alias /index.html /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/htdocs/index.html
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$ diff mod_oc4j.conf.15 mod_oc4j.conf
15c15
< Allow from localhost g5server g5server
---
> Allow from localhost guppy guppy
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$ diff ohstarget.xml.15 ohstarget.xml
5c5
< <Property NAME="OracleHome" VALUE="/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex"/>
---
> <Property NAME="OracleHome" VALUE="/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex" />
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$ diff httpd.conf.15 httpd.conf
65c65
< ServerRoot "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache"
---
> ServerRoot "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache"
76c76
< #LockFile /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/httpd.lock
---
> #LockFile /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/httpd.lock
82c82
< PidFile /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/httpd.pid
---
> PidFile /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/httpd.pid
90c90
< ScoreBoardFile /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/httpd.scoreboard
---
> ScoreBoardFile /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/httpd.scoreboard
321c321
< ServerName g5server
---
> ServerName guppy
328c328
< DocumentRoot "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/htdocs"
---
> DocumentRoot "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/htdocs"
353c353
< <Directory "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/htdocs">
---
> <Directory "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/htdocs">
456c456
< TypesConfig /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf/mime.types
---
> TypesConfig /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf/mime.types
482c482
< MIMEMagicFile /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf/magic
---
> MIMEMagicFile /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf/magic
502c502
< ErrorLog /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/error_log
---
> ErrorLog /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/error_log
547c547
< CustomLog /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/access_log common
---
> CustomLog /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/access_log common
553,554c553,554
< #CustomLog /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/referer_log referer
< #CustomLog /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/agent_log agent
---
> #CustomLog /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/referer_log referer
> #CustomLog /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/agent_log agent
560c560
< #CustomLog /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/access_log combined
---
> #CustomLog /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/access_log combined
582,584c582,584
< Alias /icons/ "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/icons/"
< Alias /jservdocs/ "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Jserv/docs/"
< Alias /javacachedocs/ "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/javacache/javadoc/"
---
> Alias /icons/ "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/icons/"
> Alias /jservdocs/ "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Jserv/docs/"
> Alias /javacachedocs/ "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/javacache/javadoc/"
586c586
< Alias /perl/ "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/cgi-bin/"
---
> Alias /perl/ "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/cgi-bin/"
589c589
< <Directory "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/icons">
---
> <Directory "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/icons">
604c604
< ScriptAlias /cgi-bin/ "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/cgi-bin/"
---
> ScriptAlias /cgi-bin/ "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/cgi-bin/"
608c608
< # "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/cgi-bin" should be changed to whatever your ScriptAliased
---
> # "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/cgi-bin" should be changed to whatever your ScriptAliased
611c611
< <Directory "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/cgi-bin">
---
> <Directory "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/cgi-bin">
824a825,826
> AddType text/xml .xbl
> AddType text/x-compoment .htc
938c940
< Allow from localhost g5server g5server
---
> Allow from localhost quppy guppy
950c952
< # Allow from localhost g5server g5server
---
> # Allow from localhsot guppy guppy
989c991
< # CacheRoot "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/proxy"
---
> # CacheRoot "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/proxy"
1038c1040
< SetEnv PERL5LIB "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/perl/lib/5.6.1:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/perl/lib/site_perl/5.6.1"
---
> SetEnv PERL5LIB "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/perl/lib/5.6.1:
/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/perl/lib/site_perl/5.6.1"
1047c1049
< # PerlSetEnv PERL5LIB "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/perl/lib/5.6.1:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/perl/lib/site_perl/5.6.1"
---
> # PerlSetEnv PERL5LIB "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/perl/lib/5.6.1:
/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/perl/lib/site_perl/5.6.1"
1084,1086c1086,1088
< Alias /fastcgi/ "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/fastcgi/"
< ScriptAlias /fcgi-bin/ "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/fcgi-bin/"
< <Directory "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/fcgi-bin">
---
> Alias /fastcgi/ "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/fastcgi/"
> ScriptAlias /fcgi-bin/ "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/fcgi-bin/"
> <Directory "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/fcgi-bin">
1104c1106
< #include "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Jserv/etc/jserv.conf"
---
> #include "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Jserv/etc/jserv.conf"
1128c1130
< Allow from localhost g5server g5server
---
> Allow from localhost guppy guppy
1134c1136
< Allow from localhost g5server g5server
---
> Allow from localhost guppy guppy
1139c1141
< include "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf/mod_oc4j.conf"
---
> include "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf/mod_oc4j.conf"
1142c1144
< include "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf/dms.conf"
---
> include "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf/dms.conf"
1148c1150
< include "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf/ssl.conf"
---
> include "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf/ssl.conf"
1151c1153
< #include "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf/mod_osso.conf"
---
> #include "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf/mod_osso.conf"
1154c1156
< include "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf/oracle_apache.conf"
---
> include "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf/oracle_apache.conf"
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$ diff oracle_apache.conf.15 oracle_apache.conf
1,2c1,2
< include "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf/plsql.conf"
< include "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf/marvel.conf"
---
> include "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/modplsql/conf/plsql.conf"
> include "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/modplsql/conf/marvel.conf"
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$ diff ssl.conf.15 ssl.conf
23,25c23,25
< #SSLSessionCache dbm:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_scache
< #SSLSessionCache shmht:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_scache(512000)
< SSLSessionCache shmcb:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_scache(512000)
---
> #SSLSessionCache dbm:/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_scache
> #SSLSessionCache shmht:/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_scache(512000)
> SSLSessionCache shmcb:/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_scache(512000)
36c36
< SSLMutex file:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_mutex
---
> SSLMutex file:/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_mutex
45c45
< SSLLog /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_engine_log
---
> SSLLog /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_engine_log
81,85c81,85
< DocumentRoot "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/htdocs"
< ServerName g5server
< ServerAdmin you@your.address
< ErrorLog /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/error_log
< TransferLog /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/access_log
---
> DocumentRoot "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/htdocs"
> ServerName guppy
> ServerAdmin your@mail.address
> ErrorLog /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/error_log
> TransferLog /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/access_log
100c100
< SSLWallet file:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf/ssl.wlt/default
---
> SSLWallet file/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf/ssl.wlt/default
117,118c117,118
< #SSLCARevocationPath /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf/ssl.crl
< #SSLCARevocationFile /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf/ssl.crl/ca-bundle.crl
---
> #SSLCARevocationPath /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf/ssl.crl
> #SSLCARevocationFile /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf/ssl.crl/ca-bundle.crl
177c177
< <Directory "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/cgi-bin">
---
> <Directory "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/cgi-bin">
186c186
< CustomLog /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_request_log \
---
> CustomLog /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/ssl_request_log \
guppy:conf oracle$


modplsql関連コンフィグファイルの変更
パスの変更とPlsqlDatabaseUsernameとPlsqlDefaultPageの値が変っているので注意。また接続先は、MacBook proにインストールしたOracle 10g R2 10.2.0.4.0 for MacOSX(Intel x86-64)になるので忘れずに変更する。

変更対象の.confファイルは予め、*.conf.15として退避しておいた。

guppy:conf oracle$ pwd
/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/modplsql/conf
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$ diff cache.conf.15 cache.conf
12c12
< PlsqlCacheDirectory /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/cache
---
> PlsqlCacheDirectory /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/modplsql/cache
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$ diff marvel.conf.15 marvel.conf
1,2c1,2
< Alias /i/ "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/marvel/images/"
< <Location /pls/htmldb>
---
> Alias /i/ "/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/marvel/images/"
> <Location /pls/apex>
7c7
< PlsqlDatabaseUsername HTMLDB_PUBLIC_USER
---
> PlsqlDatabaseUsername APEX_PUBLIC_USER
9,10c9,10
< PlsqlDatabaseConnectString localhost:1521:tiger.macdeoracle.info ServiceNameFormat
< PlsqlDefaultPage htmldb
---
> PlsqlDatabaseConnectString localhost:1521:leopard1.macdeoracle.jp ServiceNameFormat
> PlsqlDefaultPage apex
15c15
< PlsqlNLSLanguage AMERICAN_AMERICA.AL32UTF8
---
> PlsqlNLSLanguage JAPANESE_JAPAN..AL32UTF8
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$
guppy:conf oracle$ diff plsql.conf.15 plsql.conf
9c9
< LoadModule plsql_module /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/bin/modplsql.so
---
> LoadModule plsql_module /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/modplsql/bin/modplsql.so
20c20
< PlsqlLogDirectory /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/logs
---
> PlsqlLogDirectory /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/modplsql/logs
29c29
< include /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf/dads.conf
---
> include /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/modplsql/conf/dads.conf
34c34
< include /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf/cache.conf
---
> include /Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/modplsql/conf/cache.conf
guppy:conf oracle$


Oracle HTTP ServerのHOMEディレクトリ以下にあるtnsnames.oraもMacBook ProのOracle 10g R2へ接続するよう変更(念のため)

変更前のtnsnames.oraはtnsnames.ora.15として事前に退避しておいた。

guppy:admin oracle$ pwd
/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/network/admin
guppy:admin oracle$
guppy:admin oracle$
guppy:admin oracle$ guppy:admin oracle$ diff tnsnames.ora.15 tnsnames.ora
1c1
< (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=tiger.macdeoracle.info))) =
---
> (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=leopard1.macdeoracle.jp))) =
7,16c7
< (SERVICE_NAME = tiger.macdeoracle.info)
< )
< )
< (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=tiger.macdeoracle.info))) =
< (DESCRIPTION =
< (ADDRESS_LIST =
< (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
< )
< (CONNECT_DATA =
< (SERVICE_NAME = tiger.macdeoracle.info)
---
> (SERVICE_NAME = leopard1.macdeoracle.jp)
guppy:admin oracle$

apache起動用シェルスクリプトの書き換え(パスの変更が主)

要変更と判断したshell scriptは事前に、*.15として退避しておいた。

guppy:bin oracle$ pwd
/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/bin
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$ diff apachectl.15 apachectl
25,26c25,26
< ORACLE_HOME=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex; export ORACLE_HOME
< NLS_LANG=${NLS_LANG="JAPANESE_JAPAN.JA16EUC"}; export NLS_LANG
---
> ORACLE_HOME=/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex; export ORACLE_HOME
> NLS_LANG=${NLS_LANG="JAPANESE_JAPAN.AL32UTF8"}; export NLS_LANG
29c29
< PERL5LIB=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/perl/lib/5.8.3:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/perl/lib/site_perl/5.8.3 ; export PERL5LIB
---
> PERL5LIB=/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/perl/lib/5.8.3:
/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/perl/lib/site_perl/5.8.3; export PERL5LIB
32c32
< TNS_ADMIN=${TNS_ADMIN="/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/network/admin"}; export TNS_ADMIN
---
> TNS_ADMIN=${TNS_ADMIN="/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/network/admin"}; export TNS_ADMIN
37c37
< LD_LIBRARY_PATH=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/lib:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/opmn/lib ; export LD_LIBRARY_PATH
---
> LD_LIBRARY_PATH=/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/lib:
/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/opmn/lib; export LD_LIBRAR_PATH
39c39
< LD_LIBRARY_PATH=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/lib:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/opmn/lib:${LD_LIBRARY_PATH} ; export LD_LIBRARY_PATH
---
> LD_LIBRARY_PATH=/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/lib:
/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/opmn/lib:${LD_LIBRARY_PATH}; export LD_LIBRARY_PATH
45c45
< DYLD_LIBRARY_PATH=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/lib:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/opmn/lib ; export DYLD_LIBRARY_PATH
---
> DYLD_LIBRARY_PATH=/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/lib:
/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/opmn/lib; export DYLD_LIBRARY_PATH
47c47
< DYLD_LIBRARY_PATH=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/lib:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/opmn/lib:${DYLD_LIBRARY_PATH} ; export DYLD_LIBRARY_PATH
---
> DYLD_LIBRARY_PATH=/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/lib:
/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/opmn/lib:${DYLD_LIBRARY_PATH}; export DYLD_LIBRARY_PATH
52c52
< PIDFILE=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/httpd.pid
---
> PIDFILE=/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/httpd.pid
55c55
< HTTPD=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/bin/httpd
---
> HTTPD=/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/bin/httpd
91c91
< if eval $HTTPD -d /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache $args
---
> if eval $HTTPD -d /Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache $args
129c129
< if eval $HTTPD -d /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache $args
---
> if eval $HTTPD -d /Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache $args
149c149
< if eval $HTTPD -d /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache -t $args > /dev/null
---
> if eval $HTTPD -d /Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache -t $args > /del/null
261c261
< if eval $HTTPD -d /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache -t "$args"
---
> if eval $HTTPD -d /Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache -t "$args"
guppy:bin oracle$

以下、apachectlと同じディレクトリにあるが利用されているか不明なシェルスクリプトもとりあえず変更した。

guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$ diff apxs.15 apxs
1c1
< #!/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/perl/bin/perl
---
> #!/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/perl/bin/perl
78,79c78,79
< my $CFG_PREFIX = q(/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache);
# substituted via APACI install
< my $CFG_SBINDIR = q(/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/bin);
# substituted via APACI install
---
> my $CFG_PREFIX = q(/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache);
> my $CFG_SBINDIR = q(/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/bin);
81,82c81,82
< my $CFG_LIBEXECDIR = q(/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/libexec);
# substituted via APACI install
< my $CFG_SYSCONFDIR = q(/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/conf);
# substituted via APACI install
---
> my $CFG_LIBEXECDIR = q(/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/libexec);
> my $CFG_SYSCONFDIR = q(/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/conf);
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$ diff dbmmanage.15 dbmmanage
1c1
< #!/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/perl/bin/perl
---
> #!/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/perl/bin/perl
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$ diff iasobf.15 iasobf
11c11
< ORACLE_HOME=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex
---
> ORACLE_HOME=/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$ diff log_server_status.15 log_server_status
1c1
< #!/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/perl/bin/perl
---
> #!/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/perl/bin/perl
70c70
< $wherelog = "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/graph/";
# Logs will be like "/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/logs/graph/19960312"
---
> $wherelog = "/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/graph/";
# Logs will be like "/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/logs/graph/19960312"
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$ diff root_sh_append.sh.15 root_sh_append.sh
3c3
< ORACLE_HOME="/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex";export ORACLE_HOME
---
> ORACLE_HOME="/Users/shared/u01/app/oracle/oracle/product/10.1.0/apex"; export ORACLE_HOME
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$
guppy:bin oracle$ diff ssl2ossl.15 ssl2ossl
8c8
< ORACLE_HOME=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex
---
> ORACLE_HOME=Users/shared/u01/app/oracle/oracle/product/10.1.0/apex
guppy:bin oracle$


実行してみる(listenerおよびOracle Databaseインスタンスは起動ずみ)
尚、startohsは、apachectl startをalias定義しておいたもの(本エントリの最初の部分参照)

guppy:˜ oracle$ startohs
/Users/Shared/u01/app/oracle/oracle/product/10.1.0/apex/Apache/Apache/bin/apachectl start: httpd started
guppy:˜ oracle$


まずOralce HTTP Serverにアクセスしてみる・・・・OK.

4


APEX3.2の管理画面にアクセスしてログイン.....OK
ログインしたついでに開発ユーザと作業領域を作成しておく。


5

6

13

14


開発ユーザでログインしてみる。......OK。やった〜〜〜!!!!! うまくいった

15

16


最後にバージョン等も確認しておく。

3


19

「Oracle 10g R2 10.2.0.4.0 for MacOSX (Intel x86-64)で未サポートとなっているOracle HTTP ServerとPL/SQL gatewayをOracle 10g R1 10.1.0.3.0 for MacOSX (PowerPC)環境から移動し、Rosettaの力でそれらを動かしてAPEX3.2を使う!。」・・・・・一件落着。。。。次回はOraTweetでも遊んでみますか...


バックナンバー
Oracle10g R2 for MacOSX (Intel x86-64) released !!!
Leopard de Oracle10g release 2 (Intel x86-64)
Leopard de Oracle10g R2 (Intel x86-64) #1
Leopard de Oracle10g R2 (Intel x86-64) #2
Leopard de Oracle10g R2 (Intel x86-64) #3 (ちょいと寄り道)
Leopard de Oracle10g R2 (Intel x86-64) #4 (Companion CD installation)
Leopard de Oracle10g R2 (Intel x86-64) #5 (dbstart and dbshut does not work!! But....)
Leopard de Oracle10g R2 (Intel x86-64) #6 (onsがバグっている?件..)
Leopard de Oracle10g R2 (Intel x86-64) #7 (iSQL*Plusのメッセージがものすごく怖い件)
Leopard de Oracle10g R2 (Intel x86-64) #8 - (APEX3.2と遊ぶ #1)
Leopard de Oracle10g R2 (Intel x86-64) #9 - (APEX3.2と遊ぶ #2)
Leopard de Oracle10g R2 (Intel x86-64) #10 (APEX3.2と遊ぶ #3)
Leopard de Oracle10g R2 (Intel x86-64) #11 (APEX3.2と遊ぶ #4)
Leopard de Oracle10g R2 (Intel x86-64) #12 (APEX3.2と遊ぶ #5)
Leopard de Oracle10g R2 (Intel x86-64) #13 (APEX3.2と遊ぶ #6)
Leopard de Oracle10g R2 (Intel x86-64) #14 (APEX3.2と遊ぶ #7)
Leopard de Oracle10g R2 (Intel x86-64) #15 (APEX3.2と遊ぶ #8)
Leopard de Oracle10g R2 (Intel x86-64) #16 (APEX3.2と遊ぶ #9)
Leopard de Oracle10g R2 (Intel x86-64) #17 (APEX3.2と遊ぶ #10)

| | コメント (0) | トラックバック (0)

2009年6月 2日 (火)

Leopard de Oracle10g R2 (Intel x86-64) #17 (APEX3.2と遊ぶ #10)

Oracle10g R2 10.2.0.4.0 for MacOSX (Intel x68-64)でAPEX3.2と遊ぶの第九話。

Intel版MacへOracle HTTP ServerとPL/SQL gatewayをORACLE_HOMEごと移動するための環境作りとしてPowerPC上でOracle 10g R1 10.1.0.3.0 + Oracle HTTP Server + HTMLDB 1.5をインストール及び構成する。のづづき。
前回、HTMLDB 1.5の構成でエラーが発生したが今回はそれを解決後、再実行してHTMLDBのログイン画面にアクセスするまで




78


発生したエラーを確認すると、前々回の場合と同様にjavaへのパスがおかしなことになってる。

--------------------------------------
次のConfiguration Assistantが正常に完了していません。これらのアシスタントは、製品を完全に構成するため、完了する必要があります。
ファイル/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/cfgtoollogs/configToolCommandsを実行して、
スキップまたは失敗したすべてのConfiguration Assistantを再実行します。
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/jdk/jre/bin/java
-classpath /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/marvel/jlib/htmlDBConfigClasses.jar:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/jdbc/lib/classes12.jar:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/jdk/jre/lib/rt.jar:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/jlib/ojmisc.jar:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/oui/jlib/OraInstaller.jar: htmlDBConfig
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex
localhost 1521 tiger.macdeoracle.info SYSAUX * 保護された値。ログは取られません。
* * 保護された値。ログは取られません。 *
en,ja (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))
(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=tiger.macdeoracle.info)))
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/marvel
--------------------------------------

上記赤太字部分を実行してみると・・・・

G5Server:˜ oracle$ /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/jdk/jre/bin/java
-su: /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/jdk/jre/bin/java: No such file or directory
G5Server:˜ oracle$

javaが見えてないね。細かく見ていくとシンボリックリンクjreが原因。ただ前々回のようにconfigToolCommandsを変更して再実行することはできない。
理由はconfigToolCommands内に全てのパラメータが記録されていない(「保護された値。ログは取られません。」となっている部分があるから...

ということでjavaへパスが通るように修正・・・・・

Oracle HTTP ServerをインストールしたORACLE_HOME/jdkへ移動してシンボリックリンクjreを作り直す。

G5Server:˜ oracle$ cd /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/jdk
drwxr-xr-x 42 oracle oinstall 1428 May 17 12:22 bin
lrwxrwxr-x 1 oracle oinstall 26 May 17 12:22 include -> /Library/Java/Home/include
lrwxrwxr-x 1 oracle oinstall 22 May 17 12:22 jre -> /Library/Java/Home/jre
drwxr-xr-x 38 oracle oinstall 1292 May 17 12:22 lib
lrwxrwxr-x 1 oracle oinstall 22 May 17 12:22 man -> /Library/Java/Home/man
G5Server:˜/u01/app/oracle/product/10.1.0/apex/jdk oracle$ rm jre
G5Server:˜/u01/app/oracle/product/10.1.0/apex/jdk oracle$ ln -s /System/Library/Frameworks/JavaVM.framework/Home jre
G5Server:˜/u01/app/oracle/product/10.1.0/apex/jdk oracle$ ll
total 24
drwxr-xr-x 42 oracle oinstall 1428 May 17 12:22 bin
lrwxrwxr-x 1 oracle oinstall 26 May 17 12:22 include -> /Library/Java/Home/include
lrwxr-xr-x 1 oracle oinstall 48 May 17 12:58 jre -> /System/Library/Frameworks/JavaVM.framework/Home
drwxr-xr-x 38 oracle oinstall 1292 May 17 12:22 lib
lrwxrwxr-x 1 oracle oinstall 22 May 17 12:22 man -> /Library/Java/Home/man
G5Server:˜/u01/app/oracle/product/10.1.0/apex/jdk oracle$


次Oracle HTTP ServerをインストールしたORACLE_HOME/oui/binへ移動後、OUIを起動。HTMLDBだけを再インストール、構成しちゃえば解決!!(これが嫌な場合はJDK1.4.2か1.5をデフォルトにしておいた方が無難だと思う。(但し、それでこの問題が再現しなくなるか確認したわけではありません。)

また、念には念ということでJAVA_HOME環境変数へもシンボリックリンクjreへ設定したパスを設定しておいた。JAVA_HOMEの設定が必要なのかどうか? という点に関して、ちょいとヤッツケモードだったので本当に必要なのかどうか確認していません。m(_ _)m

G5Server:˜/u01/app/oracle/product/10.1.0/apex/oui/bin oracle$ pwd
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/oui/bin
G5Server:˜/u01/app/oracle/product/10.1.0/apex/oui/bin oracle$ ll
total 336
-rwxr-xr-x 1 oracle oinstall 412 May 17 12:22 addNode.sh
-rwxr-xr-x 1 oracle oinstall 20576 Aug 17 2004 lsnodes
drwxr-xr-x 12 oracle oinstall 408 May 17 12:22 resource
-rwxr-xr-x 1 oracle oinstall 136524 Aug 17 2004 runInstaller
-rwxr-xr-x 1 oracle oinstall 105 May 17 12:22 runInstaller.sh
G5Server:˜/u01/app/oracle/product/10.1.0/apex/oui/bin oracle$ export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
G5Server:˜/u01/app/oracle/product/10.1.0/apex/oui/bin oracle$ ./runInstaller &
[1] 7026
G5Server:˜/u01/app/oracle/product/10.1.0/apex/oui/bin oracle$ Starting Oracle Universal Installer...
No pre-requisite checks found in oraparam.ini, no system pre-requisite checks will be executed.
Preparing to launch Oracle Universal Installer from /tmp/OraInstall2009-05-17_01-26-05PM.
Please wait ...Oracle Universal Installer, バージョン 10.1.0.3.0 製品版
Copyright (C) 1999, 2004, Oracle. All rights reserved.

Executing install_name_tool...
Done Executing install_name_tool...



83

84

85

86

87

88

89

90

91

Oracle HTTP Serverにアクセスしてみると・・・OK.うまくいってる。
92

HTML DBにアクセスしてみる・・・OK .準備完了。
93

[1]+  Done                    ./runInstaller
G5Server:˜/u01/app/oracle/product/10.1.0/apex/oui/bin oracle$
G5Server:˜/u01/app/oracle/product/10.1.0/apex/oui/bin oracle$ unset JAVA_HOME
G5Server:˜/u01/app/oracle/product/10.1.0/apex/oui/bin oracle$


うまくいった。わははは!


さてPowerMac上での最後の作業は、Oracle HTTP Server+HTMLDBをインストールしたORACLE_HOMEごとIntel Macへ移動する前にmarvel.confのPlsqlDatabasePasswordを再設定しておきます。(OUIで設定したHTML DBのパスワードとIntel MacにインストールしたAPEX3.2のパスワードを同じパスワードにすればこの作業は不要だと思われます。また、パスワードが分からなくなった場合でもAPEX3.2のパスワードを再設定後、以下の方法でmarvel.confのPlsqlDatabasePasswordを再設定、暗号化すれば解決できます。)

Oracle HTTP Server+HTMLDBをインストールしたORACLE_HOME/Apache/modplsql/confに移動して....
(ちなみに、Oracle HTTP Serverはdads.confでもmarvel.confでも使えるようになっているが、HTML DBの構成情報はmarvel.confに書き込まれるためmarvel.confを編集している。)

G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ pwd 
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ cp dads.conf dads.conf.org
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ cp marvel.conf marvel.conf.org
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ cp marvel.conf dads.conf
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ export ORACLE_HOME=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex
G5Server:~˜u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ perl dadTool.pl -o
----------------------------------------------------------------------------
Error : Cannot invoke utility 'dadobf'
Reason: The environment setting for PATH/LD_LIBRARY_PATH is not setup to load
the required libraries.
Action: Verify the environment settings needed for running this script


----------------------------------------------------------------------------
Hint: Use the '-h' option to get details on how to invoke the script
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ export PATH=$ORACLE_HOME:bin:.:$PATH
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ perl dadTool.pl -o

Information
----------------------------------------------------------------------------
Backed up older dads.conf as /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf/dads.conf.orig.2009-05-17_19-09

All passwords successfully obfuscated. New obfuscations : 0
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$
Information
----------------------------------------------------------------------------
Backed up older dads.conf as /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf/dads.conf.orig.2009-05-17_19-11

All passwords successfully obfuscated. New obfuscations : 1
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ mv dads.conf marvel.conf
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ mv dads.conf.org dads.conf
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$ diff marvel.conf.org marvel.conf
8c8
< PlsqlDatabasePassword apex
---
> PlsqlDatabasePassword @BTpCAhnG7HjcGKTr0ns63KI=
G5Server:˜/u01/app/oracle/product/10.1.0/apex/Apache/modplsql/conf oracle$

Oracle HTTP ServerとHTML DB(関連するPL/SQLパッケージを除く)のORACLE_HOMEごとIntel Macへの移動準備完了。Rosettaの力を借りる。To be continued!


バックナンバー
Oracle10g R2 for MacOSX (Intel x86-64) released !!!
Leopard de Oracle10g release 2 (Intel x86-64)
Leopard de Oracle10g R2 (Intel x86-64) #1
Leopard de Oracle10g R2 (Intel x86-64) #2
Leopard de Oracle10g R2 (Intel x86-64) #3 (ちょいと寄り道)
Leopard de Oracle10g R2 (Intel x86-64) #4 (Companion CD installation)
Leopard de Oracle10g R2 (Intel x86-64) #5 (dbstart and dbshut does not work!! But....)
Leopard de Oracle10g R2 (Intel x86-64) #6 (onsがバグっている?件..)
Leopard de Oracle10g R2 (Intel x86-64) #7 (iSQL*Plusのメッセージがものすごく怖い件)
Leopard de Oracle10g R2 (Intel x86-64) #8 - (APEX3.2と遊ぶ #1)
Leopard de Oracle10g R2 (Intel x86-64) #9 - (APEX3.2と遊ぶ #2)
Leopard de Oracle10g R2 (Intel x86-64) #10 (APEX3.2と遊ぶ #3)
Leopard de Oracle10g R2 (Intel x86-64) #11 (APEX3.2と遊ぶ #4)
Leopard de Oracle10g R2 (Intel x86-64) #12 (APEX3.2と遊ぶ #5)
Leopard de Oracle10g R2 (Intel x86-64) #13 (APEX3.2と遊ぶ #6)
Leopard de Oracle10g R2 (Intel x86-64) #14 (APEX3.2と遊ぶ #7)
Leopard de Oracle10g R2 (Intel x86-64) #15 (APEX3.2と遊ぶ #8)
Leopard de Oracle10g R2 (Intel x86-64) #16 (APEX3.2と遊ぶ #9)

| | コメント (0) | トラックバック (0)

2009年6月 1日 (月)

Leopard de Oracle10g R2 (Intel x86-64) #16 (APEX3.2と遊ぶ #9)

Oracle10g R2 10.2.0.4.0 for MacOSX (Intel x68-64)でAPEX3.2と遊ぶの第九話。

Intel版MacへOracle HTTP ServerとPL/SQL gatewayをORACLE_HOMEごと移動するための環境作りとしてPowerPC上でOracle 10g R1 10.1.0.3.0 + Oracle HTTP Server + HTMLDB 1.5をインストール及び構成する。のづづき。
CompanionCDからOracle HTTP ServerとHTMLDB(現在はAPEX)をインストール、構成しちゃいます。


OTNからOracle 10g R1 10.1.0.3.0 for MacOSX(PowerPC)のCompanion CDをダウンロード、解凍。解凍後に作成されるDisk1ディレクトリへ移動しOUIによるインストール、構成を行います。

G5Server:˜ oracle$ cd /Volumes/DiscusWork/temp/Disk1/ 
G5Server:/Volumes/DiscusWork/temp/Disk1 oracle$ ll
total 24
drwxr-xr-x 15 oracle oinstall 510 May 16 23:34 doc
drwxr-xr-x 7 oracle oinstall 238 May 16 23:34 fonts
drwxr-xr-x 12 oracle oinstall 408 May 16 23:34 install
-rwxr-xr-x 1 oracle oinstall 1259 Dec 17 2004 runInstaller
drwxr-xr-x 15 oracle oinstall 510 May 16 23:36 stage
-rwxr-xr-x 1 oracle oinstall 4188 Dec 17 2004 welcome.htm
G5Server:/Volumes/DiscusWork/temp/Disk1 oracle$ ./runInstaller &
[1] 5831
G5Server:/Volumes/DiscusWork/temp/Disk1 oracle$ Starting Oracle Universal Installer...
No pre-requisite checks found in oraparam.ini, no system pre-requisite checks will be executed.
・・・・以下略・・・・

以下、OUI各画面のスナップショット。インストール構成が今回のテーマではないのでポイントになる箇所以外解説はしていません。(過去の記事なども参考にしてみてください。)



60

61

ちなみに、インストールするORACLE_HOMEは他のDatabase等とは異なるディレクトリにするところがポイントですよん。
63

64

68

71

HTML DBのパスワードはIntel MacでインストールしたAPEX3.2で設定予定のパスワード(現時点では未設定)と同じにしておくと楽です。(異なっても問題はないです。)
それ以外の項目はこのデータベースのインストールで設定したりした値やパスワードです。
HTML DB(APEX)はSYSAUX以外の表領域でもいいですが、今回はSYSAUX以外にする必要はないのでSYSAUXにしてあります。

73_2

74

77

HTML DB Configuration Assistantでエラーが発生してますが、あとで再実行するのでここでは「OK」ボタンクリック後、エラーを無視してインストールを続行します。
78

79

お約束のroot.shの実行です。指示された場所にあるroot.shをrootユーザで実行します。が・・・・以前とは違いちょっとしたエラーが・・・・
80

お約束のroot.shを実行したら・・・・エラーですか・・・・
root_sh_append.shの該当行を見てみると・・・chownとchmodをfull path指定が間違っていたので修正。

G5Server:˜/u01/app/oracle/product/10.1.0/apex oracle$ sudo sh
Password:
sh-2.05b# /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/root.sh
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/
Apache/bin/root_sh_append.sh: line 7: /usr/bin/chown: No such file or directory
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/
Apache/bin/root_sh_append.sh: line 8: /usr/bin/chmod: No such file or directory
Running Oracle10 root.sh script...
¥nThe following environment variables are set as:
ORACLE_OWNER= oracle
ORACLE_HOME= /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex

Enter the full pathname of the local bin directory: [/usr/local/bin]:

The file "dbhome" already exists in /usr/local/bin. Overwrite it? (y/n) [n]:n
The file "oraenv" already exists in /usr/local/bin. Overwrite it? (y/n) [n]:n
The file "coraenv" already exists in /usr/local/bin. Overwrite it? (y/n) [n]:n

Adding entry to /etc/oratab file...
Entries will be added to the /etc/oratab file as needed by
Database Configuration Assistant when a database is created
Finished running generic part of root.sh script.
Now product-specific root actions will be performed.
sh-2.05b#
sh-2.05b# which chmod
/bin/chmod
sh-2.05b# which chown
/usr/sbin/chown
sh-2.05b#
sh-2.05b#

root_sh_append.shの修正内容

sh-2.05b#
sh-2.05b# vi /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/bin/root_sh_append.sh
sh-2.05b# diff /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/bin/root_sh_append.sh.org
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/Apache/Apache/bin/root_sh_append.sh
7,8c7,8
< /usr/bin/chown root $SSOMIGRATE
< /usr/bin/chmod 6750 $SSOMIGRATE
---
> chown root $SSOMIGRATE
> chmod 6750 $SSOMIGRATE
sh-2.05b#

root.shを再実行。(こんどは上手く行った)

sh-2.05b#
sh-2.05b#
sh-2.05b# /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex/root.sh
Running Oracle10 root.sh script...
¥nThe following environment variables are set as:
ORACLE_OWNER= oracle
ORACLE_HOME= /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/apex

Enter the full pathname of the local bin directory: [/usr/local/bin]:
The file "dbhome" already exists in /usr/local/bin. Overwrite it? (y/n) [n]:n
The file "oraenv" already exists in /usr/local/bin. Overwrite it? (y/n) [n]:n
The file "coraenv" already exists in /usr/local/bin. Overwrite it? (y/n) [n]:n

Adding entry to /etc/oratab file...
Entries will be added to the /etc/oratab file as needed by
Database Configuration Assistant when a database is created
Finished running generic part of root.sh script.
Now product-specific root actions will be performed.
sh-2.05b#

root.shを実行したらOUIを終了しておわり。
81

82


以前は発生していなかったのですが、HTMLDB Configuration Assistantで問題が発生しました。原因は前々回と同じくJavaSE6.0 Developer Preview 1をデフォルトにしていることが影響しているようです。ということで解決方法なども含めて、To be continued.


バックナンバー
Oracle10g R2 for MacOSX (Intel x86-64) released !!!
Leopard de Oracle10g release 2 (Intel x86-64)
Leopard de Oracle10g R2 (Intel x86-64) #1
Leopard de Oracle10g R2 (Intel x86-64) #2
Leopard de Oracle10g R2 (Intel x86-64) #3 (ちょいと寄り道)
Leopard de Oracle10g R2 (Intel x86-64) #4 (Companion CD installation)
Leopard de Oracle10g R2 (Intel x86-64) #5 (dbstart and dbshut does not work!! But....)
Leopard de Oracle10g R2 (Intel x86-64) #6 (onsがバグっている?件..)
Leopard de Oracle10g R2 (Intel x86-64) #7 (iSQL*Plusのメッセージがものすごく怖い件)
Leopard de Oracle10g R2 (Intel x86-64) #8 - (APEX3.2と遊ぶ #1)
Leopard de Oracle10g R2 (Intel x86-64) #9 - (APEX3.2と遊ぶ #2)
Leopard de Oracle10g R2 (Intel x86-64) #10 (APEX3.2と遊ぶ #3)
Leopard de Oracle10g R2 (Intel x86-64) #11 (APEX3.2と遊ぶ #4)
Leopard de Oracle10g R2 (Intel x86-64) #12 (APEX3.2と遊ぶ #5)
Leopard de Oracle10g R2 (Intel x86-64) #13 (APEX3.2と遊ぶ #6)
Leopard de Oracle10g R2 (Intel x86-64) #14 (APEX3.2と遊ぶ #7)
Leopard de Oracle10g R2 (Intel x86-64) #15 (APEX3.2と遊ぶ #8)

| | コメント (0) | トラックバック (0)

2009年5月31日 (日)

Leopard de Oracle10g R2 (Intel x86-64) #15 (APEX3.2と遊ぶ #8)

Oracle10g R2 10.2.0.4.0 for MacOSX (Intel x68-64)でAPEX3.2と遊ぶの第八話。

Intel版MacへOracle HTTP ServerとPL/SQL gatewayをORACLE_HOMEごと移動するための環境作りとしてPowerPC上でOracle 10g R1 10.1.0.3.0 + Oracle HTTP Server + HTMLDB 1.5をインストール及び構成する。のづづき。
dbcaでデータベースインスタンスを作っちゃいます。Oracle10g R1 10.1.0.3.0 for MacOSXをMacOSX Tigerで動作させるためのお約束の作業から開始!


OTNからダウンロードできるOracle 10g R1 10.1.0.3.0 for MacOSX(PowerPC)MacOSX Tiger以降ではdbcaがこけて起動しないのでUS OTNのフォーラムでもおなじみの以下の方法で解決する。

G5Server:˜ oracle$ cd $ORACLE_HOME/lib
G5Server:˜/u01/app/oracle/product/10.1.0/tiger/lib oracle$ mv libnnz10.dylib libnnz10.dylib.org
G5Server:˜/u01/app/oracle/product/10.1.0/tiger/lib oracle$ relink all
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/bin/genclntsh
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/lib/nautab.o

・・・・中略・・・・

Enterprise Manager native components relinked
IMPORTANT NOTE: To complete this Install/upgrade, please login as root and
execute the root.sh script.
G5Server:˜/u01/app/oracle/product/10.1.0/tiger/lib oracle$ mv libnnz10.dylib.org libnnz10.dylib
G5Server:˜/u01/app/oracle/product/10.1.0/tiger/lib oracle$ cd
G5Server:˜ oracle$

relinkが済んだらdbcaを起動してデータベースを作成。

G5Server:˜ oracle$ dbca &
[1] 5600
G5Server:˜ oracle$

以下dbcaの各画面。dbcaの使い方は今回のメインネタじゃないので各画面毎の解説はしていません。Tiger Server de Oracle10gマニュアルを参考にしてくださいね。)



Dbca_1

Dbca_2

Dbca_3

Dbca_4

Dbca_5_2

Dbca_6

Dbca_7

Dbca_8

Dbca_9_2

Dbca_10_2

Dbca_11

Dbca_12

Dbca_13

Dbca_14

Dbca_15

Dbca_16

Dbca_17

Dbca_18

Dbca_21

Dbca_22


データベースが作成できたら、リスナーの状態を確認してデータベースインスタンスの起動を確認!

G5Server:˜ oracle$ lsnrctl status

LSNRCTL for MacOS X Server: Version 10.1.0.3.0 - Production on 17-5月 -2009 12:06:27

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

(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=g5server)(PORT=1521)))に接続中
リスナーのステータス
------------------------
別名 LISTENER
バージョン TNSLSNR for MacOS X Server: Version 10.1.0.3.0 - Production
開始日 17-5月 -2009 11:46:47
稼働時間 0 日 0 時間 19 分 40 秒
トレース・レベル off
セキュリティ ON: Local OS Authentication
SNMP OFF
パラメータ・ファイル /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/admin/listener.ora
ログ・ファイル /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/log/listener.log
リスニング・エンドポイントのサマリー...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=g5server)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=g5server)(PORT=8080))(Presentation=HTTP)(Session=RAW))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=g5server)(PORT=2100))(Presentation=FTP)(Session=RAW))
サービスのサマリー...
サービス"PLSExtProc"には、1件のインスタンスがあります。
インスタンス"PLSExtProc"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
サービス"tiger.macdeoracle.info"には、1件のインスタンスがあります。
インスタンス"tiger"、状態READYには、このサービスに対する1件のハンドラがあります...
サービス"tigerXDB.macdeoracle.info"には、1件のインスタンスがあります。
インスタンス"tiger"、状態READYには、このサービスに対する1件のハンドラがあります...
コマンドは正常に終了しました。
G5Server:˜ oracle$ sqlplus /nolog

SQL*Plus: Release 10.1.0.3.0 - Production on 日 5月 17 12:06:32 2009

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

SQL> conn sys@tiger as sysdba
パスワードを入力してください:
接続されました。
SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Prod
PL/SQL Release 10.1.0.3.0 - Production
CORE 10.1.0.3.0 Production
TNS for MacOS X Server: Version 10.1.0.3.0 - Production
NLSRTL Version 10.1.0.3.0 - Production

SQL> col comp_name for a50
SQL> set linesize 132
SQL> select comp_name,version,status from dba_registry;

COMP_NAME VERSION STATUS
-------------------------------------------------- ------------------------------ -----------
Oracle Database Catalog Views 10.1.0.3.0 VALID
Oracle Database Packages and Types 10.1.0.3.0 VALID
Oracle Workspace Manager 10.1.0.2.0 VALID
JServer JAVA Virtual Machine 10.1.0.3.0 VALID
Oracle XDK 10.1.0.3.0 VALID
Oracle Database Java Packages 10.1.0.3.0 VALID
Oracle Expression Filter 10.1.0.3.0 VALID
Oracle interMedia 10.1.0.3.0 VALID
Oracle Data Mining 10.1.0.3.0 VALID
Oracle Text 10.1.0.3.0 VALID
Oracle XML Database 10.1.0.3.0 VALID
OLAP Analytic Workspace 10.1.0.3.0 VALID
Oracle OLAP API 10.1.0.3.0 INVALID
OLAP Catalog 10.1.0.3.0 VALID
Spatial 10.1.0.3.0 VALID
Oracle Ultra Search 10.1.0.3.0 VALID
Oracle Enterprise Manager 10.1.0.3.0 VALID

17行が選択されました。

SQL>
SQL> select tablespace_name from dba_tablespaces;

TABLESPACE_NAME
------------------------------
SYSTEM
UNDOTBS1
SYSAUX
TEMP
USERS

SQL>


次回は当時HTMLDBと呼ばれていたAPEXとOracle HTTP ServerをPowerMac上でインストール、構成しちゃいます。

今回はここまで、To be continued.



バックナンバー
Oracle10g R2 for MacOSX (Intel x86-64) released !!!
Leopard de Oracle10g release 2 (Intel x86-64)
Leopard de Oracle10g R2 (Intel x86-64) #1
Leopard de Oracle10g R2 (Intel x86-64) #2
Leopard de Oracle10g R2 (Intel x86-64) #3 (ちょいと寄り道)
Leopard de Oracle10g R2 (Intel x86-64) #4 (Companion CD installation)
Leopard de Oracle10g R2 (Intel x86-64) #5 (dbstart and dbshut does not work!! But....)
Leopard de Oracle10g R2 (Intel x86-64) #6 (onsがバグっている?件..)
Leopard de Oracle10g R2 (Intel x86-64) #7 (iSQL*Plusのメッセージがものすごく怖い件)
Leopard de Oracle10g R2 (Intel x86-64) #8 - (APEX3.2と遊ぶ #1)
Leopard de Oracle10g R2 (Intel x86-64) #9 - (APEX3.2と遊ぶ #2)
Leopard de Oracle10g R2 (Intel x86-64) #10 (APEX3.2と遊ぶ #3)
Leopard de Oracle10g R2 (Intel x86-64) #11 (APEX3.2と遊ぶ #4)
Leopard de Oracle10g R2 (Intel x86-64) #12 (APEX3.2と遊ぶ #5)
Leopard de Oracle10g R2 (Intel x86-64) #13 (APEX3.2と遊ぶ #6)
Leopard de Oracle10g R2 (Intel x86-64) #14 (APEX3.2と遊ぶ #7)

| | コメント (0) | トラックバック (0)

Leopard de Oracle10g R2 (Intel x86-64) #14 (APEX3.2と遊ぶ #7)

Oracle10g R2 10.2.0.4.0 for MacOSX (Intel x68-64)でAPEX3.2と遊ぶの第七話。

Intel版MacへOracle HTTP ServerとPL/SQL gatewayをORACLE_HOMEごと移動するための環境作りとしてPowerPC上でOracle 10g R1 10.1.0.3.0 + Oracle HTTP Server + HTMLDB 1.5をインストール及び構成する。のづづき。
Oracle 10g R1 10.1.0.3.0のインストール中netcaがコケていた。ログから原因を探ると、デフォルトのJDKをJavaSE6.0 Developer Preview 1にしちゃっているのが原因でインストール時にORACLE_HOME内に作成されるjreのシンボリックリンクが正しく作成されていない。(java2 1.4.2のjreへのシンボリックリンクを作成しようとしているみたい・・・)

というところから...


以下、OUIの指示に従い
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/cfgtoollogs/configToolCommandsを実行してみると、/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jdk/jre//bin/javaがNo such file or directoryとなる。
どうもシンポリックリンク先にjreが存在していない。Tiger Server de Oracle10g を試した頃はJDK1.4.2をデフォルトにしていたのでこの問題は発生しなかったがJavaSE6.0 Developer Preview 1に変更してある影響なんだろう。

G5Server:˜ oracle$ /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/cfgtoollogs/configToolCommands
Oracle Net Configuration Assistant
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/cfgtoollogs/configToolCommands: line 2:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jdk/jre//bin/java: No such file or directory
G5Server:˜ oracle$


ということで、/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jdk/jre//bin/javaの部分をjavaに書き換えて再実行すればOK。

G5Server:/u01/app/oracle/product/10.1.0/tiger oracle$ 
--------------------------------------
次のConfiguration Assistantが正常に完了していません。これらのアシスタントは、製品を完全に構成するため、完了する必要があります。
ファイル/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/cfgtoollogs/configToolCommandsを実行して、
スキップまたは失敗したすべてのConfiguration Assistantを再実行します。
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jdk/jre//bin/java
-Duser.dir=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/jlib
-classpath /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jdk/jre//lib/i18n.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jdk/jre//lib/rt.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/ewt3.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/ewtcompat-3_3_15.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/netcfg.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/jlib/netcam.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/jlib/netca.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/help4.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/jewt4.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/oracle_ice.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/share.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/swingall-1_1_1.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/srvmhas.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/srvm.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/tools
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/ldapjclnt9.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/ldapjclnt10.jar
oracle.net.ca.NetCA /orahome /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger
/orahnam OraDb10g_tiger /instype custom /inscomp client,oraclenet,javavm,server
/insprtcl tcp /cfg local /authadp NO_VALUE /nodeinfo NO_VALUE /responseFile
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/install/netca_typ.rsp
--------------------------------------

G5Server:˜ oracle$
G5Server:˜ oracle$ cat /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/cfgtoollogs/configToolCommands
G5Server:˜ oracle$ java
-Duser.dir=/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/jlib
-classpath /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jdk/jre//lib/i18n.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jdk/jre//lib/rt.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/ewt3.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/ewtcompat-3_3_15.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/netcfg.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/jlib/netcam.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/jlib/netca.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/help4.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/jewt4.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/oracle_ice.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/share.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/swingall-1_1_1.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/srvmhas.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/srvm.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/tools
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/ldapjclnt9.jar
:/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/jlib/ldapjclnt10.jar
oracle.net.ca.NetCA /orahome /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger
/orahnam OraDb10g_tiger /instype custom /inscomp client,oraclenet,javavm,server
/insprtcl tcp /cfg local /authadp NO_VALUE /nodeinfo NO_VALUE /responseFile
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/install/netca_typ.rsp
コマンドライン引数の解析:
パラメータ "orahome" = /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger
パラメータ "orahnam" = OraDb10g_tiger
パラメータ "instype" = custom
パラメータ "inscomp" = client,oraclenet,javavm,server
パラメータ "insprtcl" = tcp
パラメータ "cfg" = local
パラメータ "authadp" = NO_VALUE
パラメータ "nodeinfo" = NO_VALUE
パラメータ "responsefile" = /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/network/install/netca_typ.rsp
コマンドライン引数の解析が終了しました。
Oracle Net Servicesの構成:
デフォルトのローカル・ネーミング構成が完了しました。
次のリスナーを構成中:LISTENER
リスナーの構成が完了しました。
Oracle Net Listenerの起動:
リスナーの制御の実行:
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tiger/bin/lsnrctl start LISTENER
リスナーの制御が完了しました。
リスナーの起動に成功しました。
プロファイルの構成が完了しました。
プロファイルの構成が完了しました。
デフォルトのローカル・ネーミング構成が完了しました。
作成されたネット・サービス名: tiger
Oracle Net Servicesの構成に成功しました。終了コードは次のとおりです。0
G5Server:˜ oracle$
G5Server:˜ oracle$

以下、netcaでlistenerとその構成中のスナップショット。(細かな解説は入れてませんのであしからず。)


Netca_1

Netca_2_2

Netca_3

Netca_4

Netca_5

Netca_6

Netca_7

Netca_8

Netca_9

Netca_10_2

Netca_11

Netca_12

Netca_13_2

Netca_14

Netca_15

Netca_16

Netca_16_2

Netca_17_2

Netca_18

次回はdbcaを利用したデータベース作成。

今回はここまで、To be continued.



バックナンバー
Oracle10g R2 for MacOSX (Intel x86-64) released !!!
Leopard de Oracle10g release 2 (Intel x86-64)
Leopard de Oracle10g R2 (Intel x86-64) #1
Leopard de Oracle10g R2 (Intel x86-64) #2
Leopard de Oracle10g R2 (Intel x86-64) #3 (ちょいと寄り道)
Leopard de Oracle10g R2 (Intel x86-64) #4 (Companion CD installation)
Leopard de Oracle10g R2 (Intel x86-64) #5 (dbstart and dbshut does not work!! But....)
Leopard de Oracle10g R2 (Intel x86-64) #6 (onsがバグっている?件..)
Leopard de Oracle10g R2 (Intel x86-64) #7 (iSQL*Plusのメッセージがものすごく怖い件)
Leopard de Oracle10g R2 (Intel x86-64) #8 - (APEX3.2と遊ぶ #1)
Leopard de Oracle10g R2 (Intel x86-64) #9 - (APEX3.2と遊ぶ #2)
Leopard de Oracle10g R2 (Intel x86-64) #10 (APEX3.2と遊ぶ #3)
Leopard de Oracle10g R2 (Intel x86-64) #11 (APEX3.2と遊ぶ #4)
Leopard de Oracle10g R2 (Intel x86-64) #12 (APEX3.2と遊ぶ #5)
Leopard de Oracle10g R2 (Intel x86-64) #13 (APEX3.2と遊ぶ #6)

| | コメント (0) | トラックバック (0)

2009年5月29日 (金)

Leopard de Oracle10g R2 (Intel x86-64) #13 (APEX3.2と遊ぶ #6)

Oracle10g R2 10.2.0.4.0 for MacOSX (Intel x68-64)でAPEX3.2と遊ぶの第六話。

Intel版MacへOracle HTTP ServerとPL/SQL gatewayをORACLE_HOMEごと移動するための環境作りとしてPowerPCの環境でOracle 10g R1 10.1.0.3.0 + Oracle HTTP Server + HTMLDB 1.5をインストール及び構成するところから。


MacOSX 10.4.11とJavaSE6.0 Developer Preview 1となっている事以外は、Tiger Server De Oracle10g その6と同じである。(ちなみにMacOSXのカーネルパラメータはTiger Server De Oracle10gをやっていた当時のままなので今回の手順ではさらりと書いておくことにした。)

Oracle所有者の環境変数やカーネルパラメータはインストレーションガイド以前のものを参考にしてみてね。

参考資料
Oracle Database 10g Release 1 (10.1) Documentation for Apple Mac OS X

ちなみに、今回の環境変数設定などは以下、あらかじめインストールするディレクトリなどは決めているので事前に設定しておいた。(MySQL関係のは気にしないでね。)


G5Server:˜ oracle$ cat .bash_profile
alias ls='ls -v'
alias ll='ls -vl'
alias startapex='$ORACLE_HOME/../apex/Apache/Apache/bin/apachectl start'
alias stopapex='$ORACLE_HOME/../apex/Apache/Apache/bin/apachectl stop'

umask 022

# oracle environment
TEMP=/tmp
TMPDIR=/tmp
ORACLE_BASE=/Volumes/Discus/4oracle/oracle/u01/app/oracle
ORACLE_HOME=$ORACLE_BASE/product/10.1.0/tiger
ORACLE_SID=tiger
NLS_LANG=Japanese_Japan.AL32UTF8
DYLD_LIBRARY_PATH=$ORACLE_HOME/lib:$ORACLE_HOME/rdbms/lib:$DYLD_LIBRARY_PATH
PATH=$ORACLE_HOME/bin:$PATH
export TEMP TMPDIR ORACLE_BASE ORACLE_HOME ORACLE_SID NLS_LANG DYLD_LIBRARY_PATH PATH

export MYSQL_HOME=/usr/local/mysql
export DATADIR=$MYSQL_HOME/data
export PATH=$MYSQL_HOME/bin:$PATH
G5Server:˜ oracle$

TerminalでunzipしてできるDisk1以下のrunInstallerを起動してOracledatabase 10g R1のインストール開始(Tiger Server de Oracle10gも見てね


Install_db_1

Install_db_2

Install_db_3

Install_db_4_2

Install_db_5

今回はデータベースそのものよりOracle HTTP ServerとAPEXがメインなので必要最低限のオプションだけにしてインストール時間の節約。
Install_db_6_2

Install_db_7

Install_db_8

Install_db_9

インストール時にデータベース作成は行わない。
Install_db_10

Install_db_11

Install_db_12

お約束のroot.shの実行要求が表示されたらTerminalからrootユーザでroot.shを実行する。
Install_db_13

Configuration Assistantの実行でnetcaの実行に失敗するが、JavaSE6.0 Developer Preview 1を利用していることが影響していると考えられる内容であったためエラーを無視してすすめる。(netcaはこの後、手動で実行すれば問題ないので。)
JDK1.4.2又はJavaSE5.0を使っているのならこのエラーには遭遇しないと(思われる)。


Install_db_14

Install_db_15

Install_db_16

Install_db_17_2



OracleDatabase 10g R1のインストールでTiger Server De Oracle10gの頃にはなかったエラーがnetcaの実行中に発生したがこれはJavaSE6.0 Developer Preview 1をデフォルトのJDKに設定している(詳細は次回)ことが影響しているようなのでOUIのインストールではエラーを無視し後でnetcaを手動実行する。

今回はここまで、To be continued.





バックナンバー

Oracle10g R2 for MacOSX (Intel x86-64) released !!!
Leopard de Oracle10g release 2 (Intel x86-64)
Leopard de Oracle10g R2 (Intel x86-64) #1
Leopard de Oracle10g R2 (Intel x86-64) #2
Leopard de Oracle10g R2 (Intel x86-64) #3 (ちょいと寄り道)
Leopard de Oracle10g R2 (Intel x86-64) #4 (Companion CD installation)
Leopard de Oracle10g R2 (Intel x86-64) #5 (dbstart and dbshut does not work!! But....)
Leopard de Oracle10g R2 (Intel x86-64) #6 (onsがバグっている?件..)
Leopard de Oracle10g R2 (Intel x86-64) #7 (iSQL*Plusのメッセージがものすごく怖い件)
Leopard de Oracle10g R2 (Intel x86-64) #8 - (APEX3.2と遊ぶ #1)
Leopard de Oracle10g R2 (Intel x86-64) #9 - (APEX3.2と遊ぶ #2)
Leopard de Oracle10g R2 (Intel x86-64) #10 (APEX3.2と遊ぶ #3)
Leopard de Oracle10g R2 (Intel x86-64) #11 (APEX3.2と遊ぶ #4)
Leopard de Oracle10g R2 (Intel x86-64) #12 (APEX3.2と遊ぶ #5)

| | コメント (0) | トラックバック (0)

2009年5月27日 (水)

Leopard de Oracle10g R2 (Intel x86-64) #12 (APEX3.2と遊ぶ #5)

随分間が空いてしまったが、Oracle10g R2 10.2.0.4.0 for MacOSX (Intel x68-64)でAPEX3.2と遊ぶの第五話。

前回PowerMac G5へインストールしたOracle HTTP ServerとPL/SQL GatewayをそのままIntel Macへ移植移動しただけでOracle HTTP Server+PL/SQL gateway+Oracle Application Express3.2が動作した結果だけをお見せしたが、今回はその手順を。

前提としてIntel Mac以外に、PowerPC版のMacとMacOSX Tiger 10.4.11(ServerでもClient版でも可。)が必要。おそらく、PowerPC版MacはPantherでも可能(だと思う)。


手順の概要

PowerMac G5 (MacOSX Tiger Server 10.4.11)へ、Oracle 10g R1 10.1.0.3.0 for MacOSX (PowerPC版)のDatabase及び、CompanionCDよりOracle HTTP ServerとAPEX(当時はHTMLDBと呼ばれていた)をインストール及び構成(起動するところまで確認)後、Oracle HTTP Server用のORACLE_HOMEディレクトリをまるごとOracle 10g R2 10.2.0.4.0 for MacOSX(Intel x86-64)及びAPEX3.2インストール済みのMacBook Pro - MacOSX Leopard 10.5.6へ移動しコンフィグファイルを書き換えIntel Mac上で未サポート扱いのOracle HTTP Server + PL/SQL gateway + APEX3.2を使えるようにする。

まず、PowerMacの情報

gccは3.3を使うのでそれ以外の場合はgcc_selectで変更する。また、javaに関してはOracle10g R1のリリース当時はJDK1.4.2だったが、以前デフォルトをJavaSE6.0 Developer Preview 1へ切り替えたままで行うことにした。PowerPC版Macの場合JavaSE6.0は正式にリリースされていないのでJavaSE5.0までのほうが問題は少ない。。はずだが。

G5Server:˜ oracle$ sw_vers
ProductName: Mac OS X Server
ProductVersion: 10.4.11
BuildVersion: 8S169
G5Server:˜ oracle$
G5Server:˜ oracle$ uname -a
Darwin G5Server 8.11.0 Darwin Kernel Version 8.11.0: Wed Oct 10 18:26:00 PDT 2007;
root:xnu-792.24.17˜1/RELEASE_PPC Power Macintosh powerpc
G5Server:˜ oracle$
G5Server:˜ oracle$
G5Server:˜ oracle$ /usr/sbin/system_profiler SPHardwareDataType | grep CPU
CPU Type: PowerPC G5 (3.1)
Number Of CPUs: 2
CPU Speed: 2.7 GHz
L2 Cache (per CPU): 512 KB
G5Server:˜ oracle$
G5Server:˜ oracle$
G5Server:˜ oracle$ /usr/sbin/system_profiler SPApplicationsDataType | grep Xcode
Xcode:
Get Info String: Xcode version 2.4.1
Location: /Developer/Applications/Xcode.app

G5Server:˜ oracle$
G5Server:˜ oracle$ gcc --version
powerpc-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build 5367)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

G5Server:˜ oracle$
G5Server:˜ oracle$ gcc_select -l
Available compiler versions:
3.3 3.3-fast 4.0

G5Server:˜ oracle$
G5Server:˜ oracle$ sudo gcc_select 3.3
Password:
Default compiler has been set to:
gcc version 3.3 20030304 (Apple Computer, Inc. build 1819)
G5Server:˜ oracle$
G5Server:˜ oracle$ gcc -v
Reading specs from /usr/libexec/gcc/darwin/ppc/3.3/specs
Thread model: posix
gcc version 3.3 20030304 (Apple Computer, Inc. build 1819)
G5Server:˜ oracle$

G5Server:˜ oracle$
G5Server:˜ oracle$ java -version
java version "1.6.0-dp"
Java(TM) SE Runtime Environment (build 1.6.0-dp-b88-34)
Java HotSpot(TM) Core VM (build 1.6.0-b88-17-release, interpreted mode)
G5Server:˜ oracle$

次に、Intel Macの情報

Oracle 10g R2 10.2.0.4.0 for MacOSX(intel x86-64)インストール時のまま。

Macintosh:˜ discus$ /usr/sbin/system_profiler SPHardwareDataType | grep -E '(Processor|Cores|Memory)'
Processor Name: Intel Core 2 Duo
Processor Speed: 2.2 GHz
Number Of Processors: 1
Total Number Of Cores: 2
Memory: 2 GB
Macintosh:˜ discus$
Macintosh:˜ discus$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.5.6
BuildVersion: 9G55
Macintosh:˜ discus$
Macintosh:˜ discus$ uname -a
Darwin Macintosh.local 9.6.0 Darwin Kernel Version 9.6.0: Mon Nov 24 17:37:00
PST 2008; root:xnu-1228.9.59˜1/RELEASE_I386 i386
Macintosh:˜ discus$
Macintosh:˜ discus$ gcc --version
i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5488)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Macintosh:˜ discus$
Macintosh:˜ discus$ java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06-153)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0_07-b06-57, mixed mode)
Macintosh:˜ discus$
Macintosh:˜ discus$ system_profiler SPApplicationsDataType | grep Xcode
Xcode:
Get Info String: Xcode version 3.1.1
Location: /Developer/Applications/Xcode.app
Macintosh:˜ discus$

長くなるので(というより息子が風邪(フツーの)で保育園に行けない。しかも熱が37度台になってきたので走り回ってたり私が集中できないという理由もあり)今日はここまで、次回へつづく。:)

もう、そろそろ昼寝していた息子が起きそうだ...相手してやらないと・・・





バックナンバー

Oracle10g R2 for MacOSX (Intel x86-64) released !!!
Leopard de Oracle10g release 2 (Intel x86-64)
Leopard de Oracle10g R2 (Intel x86-64) #1
Leopard de Oracle10g R2 (Intel x86-64) #2
Leopard de Oracle10g R2 (Intel x86-64) #3 (ちょいと寄り道)
Leopard de Oracle10g R2 (Intel x86-64) #4 (Companion CD installation)
Leopard de Oracle10g R2 (Intel x86-64) #5 (dbstart and dbshut does not work!! But....)
Leopard de Oracle10g R2 (Intel x86-64) #6 (onsがバグっている?件..)
Leopard de Oracle10g R2 (Intel x86-64) #7 (iSQL*Plusのメッセージがものすごく怖い件)
Leopard de Oracle10g R2 (Intel x86-64) #8 - (APEX3.2と遊ぶ #1)
Leopard de Oracle10g R2 (Intel x86-64) #9 - (APEX3.2と遊ぶ #2)
Leopard de Oracle10g R2 (Intel x86-64) #10 (APEX3.2と遊ぶ #3)
Leopard de Oracle10g R2 (Intel x86-64) #11 (APEX3.2と遊ぶ #4)

| | コメント (0) | トラックバック (0)

2009年5月22日 (金)

DB2 で PL/SQL

DB2新版はPL/SQL対応、Oracleユーザーの移行狙う@ ITmedia

へぇ〜、それじゃ、昨日作ったケンブリッジ関数もDB2 9.7で動作するようになるのか〜〜。へぇ〜。mod_plsqlというかPL/SQL gatewayはどうなんだろうか?、Oracleが提供しているPL/SQLパッケージも対応しているのだろうか? 機会があったら質問しておこうっと。

できれば他のRDBMSでもやってくれるとありがたいかも...

PL/SQL : Write Once Run Any RDBMS なんてね。

| | コメント (0) | トラックバック (0)

2009年5月21日 (木)

PL/SQL de ケンブリッジ関数

先日、ケンブリッジ関数ネタを取り上げたついでなのでPL/SQLで作ってみた。
こんな感じかな。他の言語に比べるとアウェイ感が強いけど。時間があったらほかのでもやるかも..w

ちなみに、OracleはOracle10g R2 10.2.0.4.0で、キャラクタセットはAL32UTF8

関連記事:
ケブンッリジ関数@ どう書く?org
確かに“読めてしまう”コピペに2ch住人が「人間すげー」と驚く@ITmedia
流行りのケブンリッジ関数 - JavaScript 編@IT戦記

ストアドファンクションにしてあります。

CREATE OR REPLACE FUNCTION Cambridge( iWords IN CLOB )
RETURN CLOB
IS
words CLOB := EMPTY_CLOB();
word CLOB := EMPTY_CLOB();
nonwords CLOB := EMPTY_CLOB();
TYPE t_char_table_type IS TABLE OF CHAR(1 CHAR);
chars t_char_table_type := t_char_table_type();
charsInit t_char_table_type := t_char_table_type();
startpos PLS_INTEGER := 1;
endpos PLS_INTEGER;
l PLS_INTEGER;
endpos_nonwords PLS_INTEGER;
tempwords CLOB := EMPTY_CLOB();
done BOOLEAN;
--
FUNCTION getShuffledWord RETURN CLOB
IS
workCLOB CLOB := EMPTY_CLOB();
BEGIN
IF chars.COUNT > 0 THEN
FOR j IN chars.FIRST..chars.LAST LOOP
workCLOB := workCLOB || chars(j);
END LOOP;
END IF;
RETURN workCLOB;
END;
--
BEGIN
words := iWords;
LOOP
endpos := REGEXP_INSTR(words, '(\s+|[[:punct:]]+|$)', startpos);
EXIT WHEN endpos = 0;
--
word := DBMS_LOB.SUBSTR(words, endpos - startpos, startpos);
chars := charsInit;
--
IF DBMS_LOB.getLength(word) > 3 THEN
FOR i IN 1..DBMS_LOB.getLength(word) LOOP
chars.EXTEND();
END LOOP;
chars(chars.FIRST) := DBMS_LOB.SUBSTR(word, 1, 1);
chars(chars.LAST) := DBMS_LOB.SUBSTR(word, 1, DBMS_LOB.getLength(word));
--
FOR k IN 2..DBMS_LOB.getLength(word) - 1 LOOP
done := FALSE;
WHILE NOT done LOOP
l := ROUND(DBMS_RANDOM.VALUE(2, DBMS_LOB.getLength(word) - 1));
IF chars(l) IS NULL THEN
chars(l) := DBMS_LOB.SUBSTR(word, 1, k);
done := TRUE;
END IF;
END LOOP;
END LOOP;
word := getShuffledWord();
END IF;
--
endpos_nonwords := REGEXP_INSTR(words, '(\s+|[[:punct:]]+|$)', startpos, 1, 1);
nonwords := DBMS_LOB.SUBSTR(words, endpos_nonwords - endpos, endpos);
startpos := endpos + 1;
tempwords := tempwords || word || nonwords;
END LOOP;
RETURN tempwords;
END;
/

あたえる文字列はテーブルに格納してあります。

SCOTT> 
SCOTT> set linesize 80
SCOTT> desc wordstable
名前 NULL? 型
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER
WORDS CLOB

SCOTT> set long 4000
SCOTT> set longchunk 400
SCOTT> select words from wordstable where id = 1;

WORDS
---------------------------------------------------------------------------
こんにちは みなさん おげんき ですか? わたしは げんき です。
この ぶんしょう は いぎりす の ケンブリッジ だいがく の けんきゅう の けっか
にんげん は もじ を にんしき する とき その さしいょ と さいご の もじさえ あっていれば
じゅんばん は めちゃくちゃ でも ちゃんと よめる という けんきゅう に もとづいて
わざと もじの じゅんばん を いれかえて あります。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よめたら はんのう よろしく


じこっう けっか。 フツー に よまめす よね?
PL/SQLをNative compileすればもっと早くなるだろうけど...

SCOTT> select cambridge(words) from wordstable where id = 1;

CAMBRIDGE(WORDS)
---------------------------------------------------------------------------
こちにんは みさなん おんげき ですか? わたしは げんき です。
この ぶょんしう は いりぎす の ケブンリッジ だいがく の けゅんきう の けっか
にげんん は もじ を にしんき する とき その さしいょ と さいご の もさじえ あてっいれば
じゅんばん は めゃくちちゃ でも ちんゃと よめる という けゅんきう に もとづいて
わざと もじの じばんゅん を いかれえて あまりす。
どうです? ちゃんと よめちゃう でしょ?
ちゃんと よためら はのんう よろしく

経過: 00:00:00.07
SCOTT>


では、次回はLeoparde de Oracle10g R2ネタに戻るとしましょうか・・・

それにしても他の言語で書かれているの見ると随分短いよね。そういえば、Python ChallengeでもPythonなら数行なのにPL/SQL無理矢理で書いていたっけ。。そうだ誰か、PostgreSQLのPL/pgSQLとかMySQLのストアドで書くような人はいないか?なぁ〜。と呟いてみる。w (2009/5/22追記)

| | コメント (0) | トラックバック (1)

2009年5月18日 (月)

Leopard de Oracle10g R2 (Intel x86-64) #11 (APEX3.2と遊ぶ #4)

Oracle10g R2 10.2.0.4.0 for MacOSX (Intel x68-64)でAPEX3.2と遊ぶの第四話。

前回、Rosettaの力を借りて、PowerPC版のMacへインストールしたOracle HTTP Server + PL/SQL gatewayをIntel x86版のMacへHomeディレクトリごと移動してしまえば動作するだろう。(但し、構成ファイル等は手動で手直しする必要あり)と書いたが、試してみたところ上手く動作した。Rosetta やっぱり、すげー!(Rosettaを作ったTransitive社はIBMに買収された。

手順は長くなるので次回にするが、環境と動作したスナップショットを。。。。


クリックで拡大表示します。


Ohs_apex_version1

Ohs_apex_version2


環境

Oracle HTTP ServerとPL/SQL gatewayをインストールしたMac (PowerPC)
 ---- PowerMac G5 (PowerPC G5 Dual 2.7Ghz / MacOSX Tiger Server 10.4.11)

PowerPCへインストールしたOracle HTTP ServerとPL/SQL gatewayの移動先のMac (Intel x86)
 ---- MacBook Pro (Intel Core 2 Duo 2.2Ghz / MacOSX Leopard 10.5.6)


今日はここまで、次回へつづく。:)




バックナンバー

Oracle10g R2 for MacOSX (Intel x86-64) released !!!
Leopard de Oracle10g release 2 (Intel x86-64)
Leopard de Oracle10g R2 (Intel x86-64) #1
Leopard de Oracle10g R2 (Intel x86-64) #2
Leopard de Oracle10g R2 (Intel x86-64) #3 (ちょいと寄り道)
Leopard de Oracle10g R2 (Intel x86-64) #4 (Companion CD installation)
Leopard de Oracle10g R2 (Intel x86-64) #5 (dbstart and dbshut does not work!! But....)
Leopard de Oracle10g R2 (Intel x86-64) #6 (onsがバグっている?件..)
Leopard de Oracle10g R2 (Intel x86-64) #7 (iSQL*Plusのメッセージがものすごく怖い件)
Leopard de Oracle10g R2 (Intel x86-64) #8 - (APEX3.2と遊ぶ #1)
Leopard de Oracle10g R2 (Intel x86-64) #9 - (APEX3.2と遊ぶ #2)
Leopard de Oracle10g R2 (Intel x86-64) #10 (APEX3.2と遊ぶ #3)

| | コメント (0) | トラックバック (0)

Leopard de Oracle10g R2 (Intel x86-64) #10 (APEX3.2と遊ぶ #3)

Oracle10g R2 10.2.0.4.0 for MacOSX (Intel x68-64)でAPEX3.2と遊ぶの第三話。
前回まででOracle 10g R2 10.2.0.4.0 for MacOSX (Intel x86-64)へAPEX3.2日本語リソースまでインストールすることができた。今回はOracle 10g R2 10.2.0.4.0 for MacOSX (Intel x86-64)ではCompanion CDにも含まれておらずインストールすらできないOracle HTTP ServerとPL/SQL gatewayなんとかしてみる。(それさえなんとかできればAPEX3.2が使えるはず。。)
方法は幾つ考えられるが、まずは、”なんとかできるはず”と思っている根拠について書いておこうかと・・・・。


”なんとかできるはず”だと考えているのにはそれなりの理由がある。それは、Rosettaの存在。
以前、Oracle Instant Client 10g R1 for MacOSX(PPC) is running under Rosetta on MacOSX LeopardでもRosettaの力でPowerPC版のOracle Instant Client 10g R1がMacOSX Leopard (intel x86)上で動作したという記事を書いたことがあるが、今回もRosettaのお世話になれば実現できるはず!。

いくつか考えられる方法のうち、Oracle10g R1 10.1.0.3.0 for MacOSX (PowerPC)版のCompanion CDを使いMacOSX Leopard (intel x86)上でインストールするという方法は、随分前にも試したことがあるOracl10g Databaseのインストールと同様に上手く行かない。(以下、NGシーンの再現)
Oracle10gr1_companinon_cd_4_powerpc


上記以外で確実な方法として、PowerPC版Mac上でインストール、構成までしたバイナリを、そのままIntel x86版Macへ移動して再構成(もちろん手動でね)すれば使えるようになるはず・・・・・・・。

ということで、次回へつづく。




バックナンバー

Oracle10g R2 for MacOSX (Intel x86-64) released !!!
Leopard de Oracle10g release 2 (Intel x86-64)
Leopard de Oracle10g R2 (Intel x86-64) #1
Leopard de Oracle10g R2 (Intel x86-64) #2
Leopard de Oracle10g R2 (Intel x86-64) #3 (ちょいと寄り道)
Leopard de Oracle10g R2 (Intel x86-64) #4 (Companion CD installation)
Leopard de Oracle10g R2 (Intel x86-64) #5 (dbstart and dbshut does not work!! But....)
Leopard de Oracle10g R2 (Intel x86-64) #6 (onsがバグっている?件..)
Leopard de Oracle10g R2 (Intel x86-64) #7 (iSQL*Plusのメッセージがものすごく怖い件)
Leopard de Oracle10g R2 (Intel x86-64) #8 - (APEX3.2と遊ぶ #1)
Leopard de Oracle10g R2 (Intel x86-64) #9 - (APEX3.2と遊ぶ #2)

| | コメント (0) | トラックバック (0)

2009年4月 2日 (木)

ちょいと迷惑だったストアドファンクション(おまけ)

〜〜〜〜し〜〜し〜〜でぃ〜〜っ。む、ぶん!
やけに耳の残っちゃうんだよな〜。あの声とアクセント

なんて関係ない話はおいといて。。と



以前、
ちょいと迷惑だったストアドファンクション
ちょいと迷惑だったストアドファンクション(つづき)

ということを書いていたが、ちょいと迷惑だったストアドファンクションの例外ハンドラーで問題解決の手がかりとするためログ出力が実装されていたらどうするの? っていうこともあるのでおまけのおまけということで書いておきます。

以前の例では例外ハンドラーをバッサリ切り捨ててしまったのですが、例外ハンドラーで問題解決の手がかりとするためのログ出力が実装されていて例外ハンドラーを取り除くことが出来ない場合、例外名無しのRAISE文を使えば解決できますよ。:)

ちょいと迷惑だったストアドファンクションの例外ハンドラーで問題解決の手がかりとするためのログ出力を実装していたらという例・・・・(赤太字部分)

尚、この例ではオープンソースのPL/SQL向けロギングフレームワークLog4PLSQLを利用している。

CREATE OR REPLACE
PACKAGE inconvenient_package
AS
TYPE employeesType IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;
TYPE membersType IS RECORD (
deptNo dept.deptNo%TYPE
,deptName dept.dName%TYPE
,employees employeesType
);
FUNCTION inconvenient_function(iDeptNo IN dept.deptNo%TYPE)
RETURN membersType;
END inconvenient_package;
/
show errors


CREATE OR REPLACE
PACKAGE BODY inconvenient_package
AS
FUNCTION inconvenient_function(iDeptNo IN dept.deptNo%TYPE)
RETURN membersType
AS
members membersType;
Log4PlsqlCtx plogparam.log_ctx := plog.init(pDBMS_OUTPUT => TRUE); -- Log4PLSQL setting
BEGIN
SELECT
deptNo
,dName
INTO
members.deptNo
,members.deptName
FROM
dept
WHERE
deptNo = iDeptNo
;
--
SELECT *
BULK COLLECT INTO
members.employees
FROM
emp
WHERE
deptno = iDeptNo
;
RETURN members;
EXCEPTION
WHEN NO_DATA_FOUND THEN
plog.warn(Log4PlsqlCtx, sqlerrm()); -- Log4PLSQL warnning
RETURN NULL;
END inconvenient_function;
END inconvenient_package;
/
show errors


変更前ファンクションの例外ハンドラー部分にある"RETURN NULL;"を"RAISE;"(例外名無しのRAISE文)に変更するだけ。

CREATE OR REPLACE
PACKAGE BODY inconvenient_package
AS
FUNCTION inconvenient_function(iDeptNo IN dept.deptNo%TYPE)
RETURN membersType
AS
members membersType;
Log4PlsqlCtx plogparam.log_ctx := plog.init(pDBMS_OUTPUT => TRUE); -- Log4PLSQL setting
BEGIN
SELECT
deptNo
,dName
INTO
members.deptNo
,members.deptName
FROM
dept
WHERE
deptNo = iDeptNo
;
--
SELECT *
BULK COLLECT INTO
members.employees
FROM
emp
WHERE
deptno = iDeptNo
;
RETURN members;
EXCEPTION
WHEN NO_DATA_FOUND THEN
plog.warn(Log4PlsqlCtx, sqlerrm()); -- Log4PLSQL warnning
RAISE;
END inconvenient_function;
END inconvenient_package;
/


例外ハンドラー内で例外名を省略すると該当する例外がさらに外側のブロックへスローされます。詳細はマニュアル(Oracle Database PL/SQL Language Reference 11g Release 1 : RIASE statement)及び、Oracle Database PL/SQL Language Reference 11g Release 1 : How PL/SQL Exceptions Propagate参照のこと。

SCOTT> set linesize 132
SCOTT> set serveroutput on
SCOTT> l
1 DECLARE
2 members inconvenient_package.membersType;
3 Log4PlsqlCtx plogparam.log_ctx := plog.init(pDBMS_OUTPUT => TRUE);
4 BEGIN
5 BEGIN
6 members := inconvenient_package.inconvenient_function(99);
7 DBMS_OUTPUT.PUT_LINE(
8 'Dept name/id:'
9 ||members.deptname
10 ||'/'||TO_CHAR(members.deptno)
11 );
12 FOR i IN members.employees.FIRST..members.employees.LAST LOOP
13 DBMS_OUTPUT.PUT_LINE(' -- '||members.employees(i).ename);
14 END LOOP;
15 EXCEPTION
16 WHEN NO_DATA_FOUND THEN
17 plog.warn(Log4PlsqlCtx, sqlerrm());
18 END;
19* END;
SCOTT> /
12:35:27:02-WARN-block-->SCOTT.INCONVENIENT_PACKAGE ORA-01403: データが見つかりません。
12:35:27:03-WARN-block ORA-01403: データが見つかりません。

PL/SQLプロシージャが正常に完了しました。

SCOTT> l
1 DECLARE
2 members inconvenient_package.membersType;
3 Log4PlsqlCtx plogparam.log_ctx := plog.init(pDBMS_OUTPUT => TRUE);
4 BEGIN
5 BEGIN
6 members := inconvenient_package.inconvenient_function(10);
7 DBMS_OUTPUT.PUT_LINE(
8 'Dept name/id:'
9 ||members.deptname
10 ||'/'||TO_CHAR(members.deptno)
11 );
12 FOR i IN members.employees.FIRST..members.employees.LAST LOOP
13 DBMS_OUTPUT.PUT_LINE(' -- '||members.employees(i).ename);
14 END LOOP;
15 EXCEPTION
16 WHEN NO_DATA_FOUND THEN
17 plog.warn(Log4PlsqlCtx, sqlerrm());
18 END;
19* END;
SCOTT> /
Dept name/id:ACCOUNTING/10
-- CLARK
-- KING
-- MILLER

PL/SQLプロシージャが正常に完了しました。

SCOTT>

| | コメント (0) | トラックバック (0)

2009年2月 6日 (金)

In Oracle Database 11g, native dynamic SQL now supports statements bigger than 32K characters

久々にOracleネタ。

Oracle11gのPL/SQLのDynamic SQLでCLOBが使えるようになったようなので試してみた。
10gまではexecute immediate文で使えるのは最大でVARCHAR2(32767)までだったワケで、ど〜〜〜〜〜〜しても(書きたくないけど・・)巨大なSQL文をダイナミックに実行しなきゃいけない人には朗報?なんでしょうね。(DWH系ではCLOBが必要なくらい巨大なクエリをダイナミックに生成するなんてこともあるんでしょうね。私は今のところ32Kを超えるクエリは書いたことないけどそれに近いのは過去1度あったかな?! という程度。)

ということで10gと11g for linux(x86)を使って確認!(ClientはMacOSX(PPC)版Instant Clientですよん

まず最初はOracle10g
execute immediate文に利用できるのはVARCHAR2(32767)が最大サイズなのでダイナミックに生成するSQL文もそのサイズに制限されちゃう。VARCHAR2(32767)を超えるとORA-06502が発生する。(尚、10gの場合でもDBMS_SQLを使えばもっと大きいサイズの動的SQLも使用できる。)

G5Server:˜ discus$ sqlplus /nolog

SQL*Plus: Release 10.1.0.3.0 - Production on 金 2月 6 1:19:22 2009

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

> conn scott@catfish
パスワードを入力してください:
接続されました。
SCOTT> set serveroutput on
SCOTT> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Prod
PL/SQL Release 10.1.0.3.0 - Production
CORE 10.1.0.3.0 Production
TNS for Linux Server: Version 10.1.0.3.0 - Production
NLSRTL Version 10.1.0.3.0 - Production

SCOTT> l
1 CREATE OR REPLACE PROCEDURE dynamic_sql_test10g(iLength IN NUMBER)
2 IS
3 vSQL VARCHAR2(32767);
4 vResult NUMBER;
5 BEGIN
6 vSQL := 'SELECT 1';
7 FOR i IN 1.. iLength LOOP
8 vSQL := vSQL || '+1';
9 END LOOP;
10 vSQL := vSQL || ' FROM DUAL';
11 EXECUTE IMMEDIATE vSQL INTO vresult;
12 DBMS_OUTPUT.PUT_LINE('Result:'||TO_CHAR(vresult));
13* END;
SCOTT> /

プロシージャが作成されました。

SCOTT> exec dynamic_sql_test10g(16374);
Result:16375

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec dynamic_sql_test10g(16375);
BEGIN dynamic_sql_test10g(16375); END;

*
行1でエラーが発生しました。:
ORA-06502: PL/SQL: 数値または値のエラー:
文字列バッファが小さすぎます。が発生しました ORA-06512:
"SCOTT.DYNAMIC_SQL_TEST10G", 行10
ORA-06512: 行1

SCOTT>

11gの場合
execute immediate文にCLOBが使えるようになったことで以下のように32K超えの動的SQLも実行できちゃうのだ。

注)
以下のコードで遊ぶときは個人で遊べるデータベースでやってくださいね。(本番データベースや多数の開発者で共有しているテスト/開発データベースでとんでもなく巨大なクエリを実行すると他の方の迷惑になるので・・・・・)

SCOTT> 
SCOTT> conn scott@lampeye
パスワードを入力してください:
接続されました。
SCOTT>
SCOTT> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
PL/SQL Release 11.1.0.6.0 - Production
CORE 11.1.0.6.0 Production
TNS for Linux: Version 11.1.0.6.0 - Production
NLSRTL Version 11.1.0.6.0 - Production

SCOTT>
SCOTT> l
1 CREATE OR REPLACE PROCEDURE dynamic_sql_test11g(iLength IN NUMBER)
2 IS
3 vSQL CLOB;
4 vResult NUMBER;
5 BEGIN
6 vSQL := 'SELECT 1';
7 FOR i IN 1.. iLength LOOP
8 vSQL := vSQL || '+1';
9 END LOOP;
10 vSQL := vSQL || ' FROM DUAL';
11 EXECUTE IMMEDIATE vSQL INTO vresult;
12 DBMS_OUTPUT.PUT_LINE('Result:'||TO_CHAR(vresult));
13* END;
SCOTT> /

プロシージャが作成されました。

SCOTT> set serveroutput on
SCOTT> exec dynamic_sql_test11g(32767);
Result:32768

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> set timi on
SCOTT> exec dynamic_sql_test11g(1000000);
Result:1000001

PL/SQLプロシージャが正常に完了しました。

経過: 00:06:25.93
SCOTT>

| | コメント (0) | トラックバック (0)

2008年9月13日 (土)

ちょいと迷惑だったストアドファンクション(つづき)

前回の続きです。

ところで何がちょっと迷惑だったのか?

まずは、マニュアルをご覧ください。

もうお分かりですよね!

例の関数、戻り値としてレコード型を返してくれるのはよいのですが、該当データが存在しなかった場合にNULLを返す作りになっています。そのレコード型はどのように比較すれば該当データが存在しないのか外部の仕様からは全く見えません。(当然、レコードがNULLであるか判定する関数も用意されていません。)

レコード型がNULLかテストできないので以下のようなコードは書けないのですよ!

SCOTT> set serveroutput on size 100000
SCOTT> l
1 DECLARE
2 members inconvenient_package.membersType;
3 BEGIN
4 members := inconvenient_package.inconvenient_function(99);
5 IF members IS NULL THEN
6 RAISE NO_DATA_FOUND;
7 ELSE
8 DBMS_OUTPUT.PUT_LINE('Dept name/id:'||members.deptname||'/'||TO_CHAR(members.deptno));
9 FOR i IN members.employees.FIRST..members.employees.LAST LOOP
10 DBMS_OUTPUT.PUT_LINE(' -- '||members.employees(i).ename);
11 END LOOP;
12 END IF;
13* END;
SCOTT> /
IF members IS NULL THEN
*
行5でエラーが発生しました。:
ORA-06550: 行5、列6:
PLS-00306: 'IS NULL'の呼出しで、引数の数または型が正しくありません。
ORA-06550: 行5、列3:PL/SQL: Statement ignored

利用する側からすると、該当データが存在しない場合のコードをどうかいて良いのかAPIからは判断がつかない(該当関数のソースコードを読まない限り判断できない)。
この点がちょいと迷惑だったわけ。

例の関数をそのまま利用した場合以下のようなコードを書かないと該当データが存在しないことを判定できない。
(赤太字部分は利用する関数のコード及びこの関数がアクセスしている表定義を見て判断する必要がある。面倒くさい! なんでAPI見ただけでコード書く事できないような共通関数があるの〜〜〜。)

SCOTT> l
1 DECLARE
2 members inconvenient_package.membersType;
3 BEGIN
4 members := inconvenient_package.inconvenient_function(99);
5 IF members.employees.COUNT = 0
6 OR members.deptno IS NULL
7 THEN
8 DBMS_OUTPUT.PUT_LINE('該当データが存在しません.');
9 ELSE
10 DBMS_OUTPUT.PUT_LINE(
11 'Dept name/id:'
12 ||members.deptname
13 ||'/'||TO_CHAR(members.deptno)
14 );
15 FOR i IN members.employees.FIRST..members.employees.LAST LOOP
16 DBMS_OUTPUT.PUT_LINE(' -- '||members.employees(i).ename);
17 END LOOP;
18 END IF;
19* END;
SCOTT> /
該当データが存在しません.

PL/SQLプロシージャが正常に完了しました。


SCOTT> l
1 DECLARE
2 members inconvenient_package.membersType;
3 BEGIN
4 members := inconvenient_package.inconvenient_function(10);
5 IF members.employees.COUNT = 0
6 OR members.deptno IS NULL
7 THEN
8 DBMS_OUTPUT.PUT_LINE('該当データが存在しません.');
9 ELSE
10 DBMS_OUTPUT.PUT_LINE(
11 'Dept name/id:'
12 ||members.deptname
13 ||'/'||TO_CHAR(members.deptno)
14 );
15 FOR i IN members.employees.FIRST..members.employees.LAST LOOP
16 DBMS_OUTPUT.PUT_LINE(' -- '||members.employees(i).ename);
17 END LOOP;
18 END IF;
19* END;
SCOTT> /
Dept name/id:ACCOUNTING/10
-- CLARK
-- KING
-- MILLER

PL/SQLプロシージャが正常に完了しました。

SCOTT>

例の関数を修正するとしたら、私個人の趣味だとNO_DATA_FOUND例外はそのままスローするように例外ハンドラー部分を削除しますね。
(ファンクションである必要も無さそうなのでプロシージャにして該当データ無しなどを表すステータスを返す方法を好む方も多いのですが。)

例の関数を修正しNO_DATA_FOUND例外をそのままスローする仕様に変更すれば共通関数のソースコードや関連する表定義まで追っかける必要は無くなりますよ!。w
以下、NO_DATA_FOUNDの例外ハンドラーを削除した例

CREATE OR REPLACE PACKAGE BODY inconvenient_package
AS
FUNCTION inconvenient_function(iDeptNo IN dept.deptNo%TYPE)
RETURN membersType
AS
members membersType;
BEGIN
SELECT
deptNo
,dName
INTO
members.deptNo
,members.deptName
FROM
dept
WHERE
deptNo = iDeptNo
;
--
SELECT *
BULK COLLECT INTO
members.employees
FROM
emp
WHERE
deptno = iDeptNo
;
RETURN members;
-- NO_DATA_FOUND例外ハンドラーを削除して利用する側でハンドリングさせる
END inconvenient_function;
END inconvenient_package;
/

前述のように修正すれば以下のようなコードを書くだけでよく余計なことに気を使う事もなくなる。(関数のコードやアクセスしている表定義なんて覗かなくても該当データが存在しない場合、NO_DATA_FOUND例外をキャッチするだけで済む)

SCOTT> l
1 DECLARE
2 members inconvenient_package.membersType;
3 BEGIN
4 BEGIN
5 members := inconvenient_package.inconvenient_function(10);
6 DBMS_OUTPUT.PUT_LINE(
7 'Dept name/id:'
8 ||members.deptname
9 ||'/'||TO_CHAR(members.deptno)
10 );
11 FOR i IN members.employees.FIRST..members.employees.LAST LOOP
12 DBMS_OUTPUT.PUT_LINE(' -- '||members.employees(i).ename);
13 END LOOP;
14 --
15 EXCEPTION
16 WHEN NO_DATA_FOUND THEN
17 DBMS_OUTPUT.PUT_LINE('該当データが存在しません。');
18 END;
19* END;
SCOTT> /
Dept name/id:ACCOUNTING/10
-- CLARK
-- KING
-- MILLER

PL/SQLプロシージャが正常に完了しました。

SCOTT> l
1 DECLARE
2 members inconvenient_package.membersType;
3 BEGIN
4 BEGIN
5 members := inconvenient_package.inconvenient_function(99);
6 DBMS_OUTPUT.PUT_LINE(
7 'Dept name/id:'
8 ||members.deptname
9 ||'/'||TO_CHAR(members.deptno)
10 );
11 FOR i IN members.employees.FIRST..members.employees.LAST LOOP
12 DBMS_OUTPUT.PUT_LINE(' -- '||members.employees(i).ename);
13 END LOOP;
14 --
15 EXCEPTION
16 WHEN NO_DATA_FOUND THEN
17 DBMS_OUTPUT.PUT_LINE('該当データが存在しません。');
18 END;
19* END;
SCOTT> /
該当データが存在しません。

PL/SQLプロシージャが正常に完了しました。

SCOTT>

2009/3/25追記:
この例では該当関数の例外ハンドラーを削除しただけですが、もし該当関数やプロシージャの例外ハンドラーでエラーログ(例えばLog4PLSQLとか)などでエラーなどを追跡しやすくするようなロジックを実装していたら・・・・例外ハンドラーを削除することは避けてくださいね。そのような場合は例外ハンドラー内で同じ例外をスローするように変更すべきです(プロジェクトの規約でユーザー定義例外をスローするようにしているところもあります。)
そのようにすることで該当関数から呼び出しもとへ同じ例外がスローされるようになります。具体的な例は別エントリで書く予定。

ついでなのでOTNオンラインマニュアルのURLを変更。(OTNのオンラインマニュアルは訂正が入るとリビジョンが上がりURLまで変っちゃうのが面倒なのよ。ほんと。。URL変らないように工夫してくれないかな。。

| | コメント (0) | トラックバック (0)

2008年9月12日 (金)

ちょいと迷惑だったストアドファンクション

以下のような既存パッケージがあり、共通ファンクションがあるのでこれを利用してくださいとのこと。

仕様書には、該当データが存在する場合はユーザ定義レコード型として定義されているmembersType、該当データが存在しない場合この関数はNULLを返すとある。フムフム。・・・・・でもなんとなく怪しい匂いが。。
で、ソースを除いてみたら以下の”ような”コードだった。どこがちょいと迷惑なのか分かりますか?
(私だったらコードレビュー時に指摘して変更させちゃうんだけどね。そのプロジェクトでは此の手のちょいと迷惑なのがかなりあったのよ。w)
2008/9/12 仕様書には、以下に少々追記

以下の例で利用している表は、Scottスキーマのemp表とdept表です。

CREATE OR REPLACE PACKAGE inconvenient_package 
AS
TYPE employeesType IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;
TYPE membersType IS RECORD (
deptNo dept.deptNo%TYPE
,deptName dept.dName%TYPE
,employees employeesType
);
FUNCTION inconvenient_function(iDeptNo IN dept.deptNo%TYPE)
RETURN membersType;
END inconvenient_package;
/
show errors

CREATE OR REPLACE PACKAGE PACKAGE BODY inconvenient_package
AS
FUNCTION inconvenient_function(iDeptNo IN dept.deptNo%TYPE)
RETURN membersType
IS
members membersType;
BEGIN
SELECT
deptNo
,dName
INTO
members.deptNo
,members.deptName
FROM
dept
WHERE
deptNo = iDeptNo
;
--
SELECT *
BULK COLLECT INTO
members.employees
FROM
emp
WHERE
deptno = iDeptNo
;
RETURN members;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN NULL;
END inconvenient_function;
END inconvenient_package;
/
show errors

次回へつづく。

| | コメント (0) | トラックバック (0)

2008年4月26日 (土)

PL/SQL で Python Challenge Level 18 わかちゃったかも・・

Level18は以外と簡単かも〜〜、Pythonならば。と。
当然だよね。Python ChallengeなんだからPythonを使って解くことを前提に作られてるのは。。。。

しかし、今回はもしかするとPL/SQLだけで全部解けちゃうかもしれない・・・久々だ〜。一部はかなり苦労してガリガリ作り込まなければならないと思われるのだが・・・その方法で上手く解けるという自信は70%。チャレンジしてみますよ〜〜。連休中にロジックを考えとく。。。

次回へつづく。;)

| | コメント (0) | トラックバック (0)

2008年4月17日 (木)

埋込みPL/SQL Gatewayで外部URLアクセス

Oracle11g R1 11.1.0.6.0 for Linux x86 and Oracle Application Expressという記事で埋込みPL/SQL GatewayをでPython Challengeを試してみたのだが・・・埋込みPL/SQL Gatewayを利用した場合、UTL_HTTPパッケージで外部のURLへアクセスすることはできないみたいなので、あきらめて通常のmod_plsqlでやってみるか・・・。Oracle11gからならACLで許可してやればアクセスできるのに、Oracle11gに内蔵されているXDB HTTP Serverではそれは効かないのね。。遊べると思ったのに。。orz.(Oracle11gの埋込みPL/SQL Gatewayの備忘録として残しておくか。。)

エラーメッセージは以下の通り。(Apexを3.1にするとできるようになったりして。。。2008/4/19追記)

ORA-31020:操作できません。 理由:For security reasons, ftp and http access over XDB repository is not allowed on server side

以下、埋込みPL/SQL Gatewayを利用したOracle Application Expressのスクリーンショット
9


4/18追記
どうもこれは埋込みPL/SQL GatewayというよりOracle Application Express側の影響のように思えてきた。10gのmod_plsql経由でもApexでは同じエラーだった。
ちなみに、mod_plsql経由で呼び出すだけならACL定義でアクセスするホストを許可してやるだけでOK。

以下にその時のスクリーンショットを載せておく。
答えにLevel17の答えに結びつく部分はぼかしてますよ〜〜。

19


でも何故、ApexからUTL_HTTPを利用するとXDB絡みのエラーになるんだ? 不思議すぎる。。。これは追々調べておくか。。何か手順から漏れていることがあったりして。。。。つづく。

さらに追記、やはり出来ない(11gからはできなくなったと言ったほうがいいだろう)というのが正しいようだ。10gではApexから直接UTL_HTTPパッケージからHTTPリクエスト出してfeedやらHTMLやらアクセスし放題だったのに〜〜〜、プンプンのプン。 ふ〜普通のmod_plsqlでやりますよ〜〜〜〜だ。

| | コメント (0) | トラックバック (0)

2008年4月16日 (水)

Oracle11g R1 11.1.0.6.0 for Linux x86 and Oracle Application Express

Python Challenge Level17の記事を書く前に、やっておきたい事があったのでそちらを先に。

何をやりたかったのか? それは、APEX(Oracle Application Express)環境を作っておく事。

Python ChallengeではWeb Applicationとして処理して欲しそうな問題も多数存在する。Level17はそうしたほうが自然な感じをだと思ったので。。。(実際にはそこまでしなくても解けたのですが)
Oracle11gからApexがバンドルされたのと同時に、組み込みPL/SQL gateway機能も追加されたのでその辺りも含めて確認しておきたかった。

この組込PL/SQL Gatewayってなによ? って方もいると思うのだが、簡単に言うと、”Oracle11gのデータベース内部にHTTP Server+mod_plsqが内蔵されちゃっている”と思えばイメージしやすいんじゃないかと。

概要はこのあたりのマニュアルを読めば掴めると思います。はい。

マニュアル(英語)Understanding Oracle Application Express Architecture

データベースサーバがHTTPサーバを内蔵なんて言うといや〜な顔する人もいるだろうなぁ。なんて思ったりもします。(笑)
実際の所組込みPL/SQLゲートウェイは、外部に公開するというより開発目的など内部の閉じられた環境で利用されることがほとんどじゃないかなぁと個人的には思います。

Oracle11gをインストールした場合、OUIによるインストールでは明示的に除外しなければOracle Application Expressも同時にインストールされる。尚、埋込みPL/SQLゲートウェイを利用するためには、Oracle XML DBも必要。詳細はマニュアルに記載されているので、よ〜〜〜く読めば簡単に構成できます。
4.5 Postinstallation Tasks for Oracle Application Express

ちなみに、Oracle11g R1 1011.1.0.6.0に含まれるOracle Application Expressは、3.0.1.00.08とのこと、3.1が既にリリースされているのでアップグレードするのもいいが、今回は面倒なのでそのまま使うことにした。

では”素直に”マニュアルに従い作業を進める。。。(笑)

sysdbaで接続後、 $ORACLE_HOME/apex/apexconfを実行しadminユーザのパスワードとapexのport番号を設定してから、anonymousユーザをアンロックします。

G5Server:˜ discus$ ssh oracle@corydoras
oracle@corydoras's password:
Last login: Tue Apr 15 22:09:38 2008 from 192.168.1.19
[oracle@corydoras ˜]$
[oracle@corydoras ˜]$
[oracle@corydoras ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 火 4月 15 22:46:50 2008

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

> conn / as sysdba
接続されました。
SYS> spo apexconfig.log
SYS> @?/apex/apxconf

PORT
----------
8080

Enter values below for the XDB HTTP listener port and the password for the Application Express ADMIN user.
Default values are in brackets [ ].
Press Enter to accept the default value.


Enter a password for the ADMIN user [] apex
Enter a port for the XDB HTTP listener [ 8080]
...changing HTTP Port

PL/SQLプロシージャが正常に完了しました。


PL/SQLプロシージャが正常に完了しました。


セッションが変更されました。

...changing password for ADMIN

PL/SQLプロシージャが正常に完了しました。


コミットが完了しました。

SYS> alter user anonymous account unlock;

ユーザーが変更されました。

SYS>

さて、お継ぎはマニュアルに記載されている通り(コピペでOKです。)外部のネットワークにアクセスする為にACLを変更しました。
(この例ではマニュアルと同様、どこでもアクセスできるようにしておきます。今回の場合は、python challengeのサイトだけアクセス許可しておけば問題ないのですが、いろいろと試したいことがあるので今回マニュアルの例をそのまま利用させてもらいました。)

SYS> l
1 DECLARE
2 ACL_PATH VARCHAR2(4000);
3 ACL_ID RAW(16);
4 BEGIN
5 -- Look for the ACL currently assigned to '*' and give FLOWS_030000
6 -- the "connect" privilege if FLOWS_030000 does not have the privilege yet.
7 SELECT ACL INTO ACL_PATH FROM DBA_NETWORK_ACLS
8 WHERE HOST = '*' AND LOWER_PORT IS NULL AND UPPER_PORT IS NULL;
9
10 -- Before checking the privilege, make sure that the ACL is valid
11 -- (for example, does not contain stale references to dropped users).
12 -- If it does, the following exception will be raised:
13 --
14 -- ORA-44416: Invalid ACL: Unresolved principal 'FLOWS_030000'
15 -- ORA-06512: at "XDB.DBMS_XDBZ", line ...
16 --
17 SELECT SYS_OP_R2O(extractValue(P.RES, '/Resource/XMLRef')) INTO ACL_ID
18 FROM XDB.XDB$ACL A, PATH_VIEW P
19 WHERE extractValue(P.RES, '/Resource/XMLRef') = REF(A) AND
20 EQUALS_PATH(P.RES, ACL_PATH) = 1;
21
22 DBMS_XDBZ.ValidateACL(ACL_ID);
23
24 IF DBMS_NETWORK_ACL_ADMIN.CHECK_PRIVILEGE(ACL_PATH, 'FLOWS_030000', 'connect')
25 IS NULL THEN
26 DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(ACL_PATH,
27 'FLOWS_030000', TRUE, 'connect');
28 END IF;
29
30 EXCEPTION
31 -- When no ACL has been assigned to '*'.
32 WHEN NO_DATA_FOUND THEN
33 DBMS_NETWORK_ACL_ADMIN.CREATE_ACL('power_users.xml',
34 'ACL that lets power users to connect to everywhere',
35 'FLOWS_030000', TRUE, 'connect');
36 DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL('power_users.xml','*');
37* END;
SYS> /

PL/SQLプロシージャが正常に完了しました。

SYS>
SYS> commit;

コミットが完了しました。

SYS>


apexの管理画面にログインするには...以下のような形式のURLでブラウザからアクセスする。もちろん、ホストはOracle11g Databaseインスタンスがあるサーバですよ。

http://host:port/apex/apex_admin

Apex_admin_1

Apex_admin_2

Apex_admin_3

Apex_admin_4

ここまでで、application expressは利用可能な状態なのだが1つ問題がある、それは英語版のままだということ。(これは以前のOracle Application Expressでも同じですね。)
ということで、日本語リソースをロードします。尚、環境変数NLS_LANGは、AL32UTF8である必要があります。(これも以前と同じなので利用したことがあれば間違うことは無いと思いますが、注意しなければならない点ですよ。うっかりミスというのもありますから。)

[oracle@corydoras ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 火 4月 15 23:06:03 2008

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

> conn / as sysdba
接続されました。
SYS> !echo $NLS_LANG
japanese_japan.AL32UTF8

SYS> alter session set current_schema=FLOWS_030000;

セッションが変更されました。

SYS> @?/apex/builder/ja/load_ja
. ____ ____ ____ ____
. / \ | \ /\ / | /
.| || / / \ | | |
.| ||--- ---- | | |--
.| || \ / \ | | |
. \____/ | \/ \ \____ |____ \____
.
. Application Express Hosted Development Service Installation.
.........................................................

PL/SQLプロシージャが正常に完了しました。

Install Application Express applications

PL/SQLプロシージャが正常に完了しました。

APPLICATION 4420 - APEX - System Messages
Set Credentials...
Check Compatibility...
API Last Extended:20070525
Your Current Version:20070525
This import is compatible with version: 20070108
COMPATIBLE (You should be able to run this import without issues.)
Set Application ID...
...authorization schemes
...navigation bar entries
...application processes
...application items
...application level computations
...Application Tabs
...Application Parent Tabs
...Shared Lists of values
...Application Trees
...page groups
...PAGE 1.442: メッセージ
...lists
...breadcrumbs

中略

...PAGE 91.4009: 検証の作成 - 検証タイプ
...PAGE 92.4009: 標準タブの作成の確認
...PAGE 93.4009: 既存のタブ・セットの選択
...PAGE 94.4009: タブ情報の指定
...PAGE 95.4009: 親タブ・セット
...PAGE 96.4009: 新しいタブ名
...PAGE 97.4009: 表形式フォーム
...PAGE 98.4009: 検証の作成 - SQL検証
...PAGE 99.4009: SQLレポートの作成
...PAGE 100.4009: カレンダ・ページの作成
...PAGE 101.4009: ボタンのコピー
...PAGE 102.4009: リージョンの削除の確認
...PAGE 103.4009: ビルド・ステータス
...PAGE 104.4009: ビルド・チャート問合せ
...PAGE 105.4009: スクリプト・ファイルのエクスポート
...PAGE 106.4009: ビルド・チャート問合せ
...PAGE 107.4009: 作成ウィザード
...PAGE 108.4009: 作成ウィザード
...PAGE 109.4009: 作成ウィザード
...PAGE 110.4009: 作成ウィザード
...PAGE 111.4009: 作成ウィザード
...PAGE 112.4009: ツリー・ウィザード
...PAGE 113.4009: ツリー・ウィザード
...PAGE 114.4009: ツリー・ウィザード

中略

......scheme 108165525079033088.4709
...done
Adjust instance settings

PL/SQLプロシージャが正常に完了しました。


最後に、job_queue_process初期化パラメータが1以上になっているか確認します。
私も初めて気付いたがデフォルトで1000になっているんですね。びっくり。以前は1桁か2桁だったようなきがするが。

SYS> 
SYS> show parameter job_queue_processes

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
job_queue_processes integer 1000
SYS>

尚、今回はSSLの設定は行わないので早速Apexの管理ユーザログインし直し開発用作業領域と開発ユーザを作っておく。

Apex_ja_1

Apex_ja_2

Apex_ja_3

Apex_ja_4

Apex_ja_7

Apex_ja_8

Apex_ja_10

Apex_ja_9

さて、準備もできたので次へ行くか!

| | コメント (0) | トラックバック (0)

2008年4月13日 (日)

PL/SQL で Python Challenge Level 17 #2 - 解けた!

さて、前回、解き方は見えたような気がすると書いたがいろいろな罠?に見事に引っかかったが解けました。はい。
今、Level18の問題が見えたのだが、また画像問題なのかな?

Level17は、Web Applicationを作った経験のある方ならLevel17の質問の画像自体がヒント。
なんですが、2重、3重の仕掛けがあるのでイライラするよ。ですが、基本的にはいままでの問題を解いてきたテクニックやコードを再利用すれば十分なので特に新しいことが必要でもない。。。

ということで、次回のPL/SQL で Python ChallengeはLevel17のヒントにならないヒント。でLevel17を締めくくろう。


以下のスクリーンショットは、最後の仕掛けを通り抜ける為のヒントを取り出す事に成功した場面。Level18のURLを導きだした時のスクリーンショットではありません。:)
Level17_no2

| | コメント (0) | トラックバック (0)

2008年3月26日 (水)

PL/SQL で Python Challenge Level 17

さて、ココログのデータベースのデフラグ?作業でログインできなかったので今書いてますが。
Level 17、少々ハマったが解き方は見えた(ような気がする)ので次回はその経過でも。

Level 17は、Web Applicationを作った経験のあるかたなら案外すんなり解けるかもしれない。
問題の画像にそのすべてのヒントが!


Enjoy! Python Challenge!
(Python じゃなくても楽しめるのだ!)

| | コメント (0) | トラックバック (0)

2008年3月24日 (月)

PL/SQL で Python Challenge Level 16完

前回の続きです

さて、Level 16のページには、"let me get this straight" というタイトルが付けられている。これ自体が大きなヒント。なのでこれ以上は何も言うまい。

問題の解くjavaアプリケーションの内容は、以前、Level 11の処理の流れを書いていたが、その3、4以外の部分は同じ。
但し、Level7で利用した Level7.getBfile()とLevel9で作成したLevel9.writeImageFile()というファンクションとプロシージャを以下のPL/SQLパッケージに纏めた。

CREATE OR REPLACE PACKAGE PYTHONCHALLENGE_UTL AS

FUNCTION getBfile
(
i_dir_name IN VARCHAR2,
i_file_name IN vARCHAR2
) RETURN BFILE;

PROCEDURE writeImageFile(
directoryName IN VARCHAR2,
fileName IN VARCHAR2,
srcImage IN OUT NOCOPY BLOB
);

END PYTHONCHALLENGE_UTL;

CREATE OR REPLACE PACKAGE BODY PYTHONCHALLENGE_UTL AS

FUNCTION getBfile
(
i_dir_name IN VARCHAR2,
i_file_name IN VARCHAR2
) RETURN bfile AS
v_file BFILE;
BEGIN
v_file := BFILENAME(UPPER(i_dir_name),i_file_name);
RETURN v_file;
END getBfile;

PROCEDURE writeImageFile(
directoryName IN VARCHAR2,
fileName IN VARCHAR2,
srcImage IN OUT NOCOPY BLOB
) IS
file utl_file.file_type;
BEGIN
file := UTL_FILE.FOPEN(UPPER(directoryName), fileName, 'w', 32767);
DBMS_LOB.OPEN(srcImage, DBMS_LOB.LOB_READONLY);

DECLARE
v_raw RAW(32767);
amount INTEGER;
offset INTEGER;
BEGIN
offset := 1;
LOOP
amount := 32767;
DBMS_LOB.READ(srcImage, amount, offset, v_raw);
UTL_FILE.PUT_RAW(file, v_raw, true);
offset := offset + amount;
END LOOP;
EXCEPTION
WHEN no_data_found THEN
NULL;
WHEN OTHERS THEN
UTL_FILE.FCLOSE(file);
DBMS_LOB.CLOSE(srcImage);
RAISE_APPLICATION_ERROR(-20001, sqlerrm());
END;

UTL_FILE.FCLOSE(file);
DBMS_LOB.CLOSE(srcImage);
END writeImageFile;

END PYTHONCHALLENGE_UTL;
/

上記のパッケージをJava Stored Procedureから利用するわけです。javaのソースコードは載せませんよ。ネタバレになっちゃいますから。

次に、デプロイしたjava classは以下のようにしてJava Stored Procedureとして定義します。

CREATE OR REPLACE PACKAGE LEVEL16 AS
FUNCTION getResult RETURN NUMBER AS
LANGUAGE JAVA NAME 'jp.macdeoracle.Level16.getResult() return java.lang.boolean';
END LEVEL16;

では、SQL*Plusから実行してみましょう!

Last login: Sun Mar 23 20:29:41 on ttyp2
Welcome to Darwin!
G5Server:˜ discus$ ssh oracle@corydoras
oracle@corydoras's password:
Last login: Sun Mar 23 20:31:49 2008 from 192.168.1.19
[oracle@corydoras ˜]$ cd python_challenge
[oracle@corydoras python_challenge]$ ll
合計 264
-rw-r--r-- 1 oracle oinstall 254006 3月 23 16:26 level16.gif

[oracle@corydoras python_challenge]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 日 3月 23 20:58:34 2008

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

> conn scott/tiger
接続されました。
SCOTT> l
1 select
2 case
3 when level16.getResult() = 1 then '成功!'
4 else '失敗!'
5 end as "Level16"
6* from dual
SCOTT> /

Level16
---------
成功!

SCOTT> !ls -l
合計 504
-rw-r--r-- 1 oracle oinstall 254006 3月 23 16:26 level16.gif
-rw-r--r-- 1 oracle oinstall 239515 3月 23 21:02 level16_result.png

SCOTT>

これだけでもかなりのヒントになっているような気もしますが。。。
MacOSXのChicken of the VNC(MacOSX向けのVNC Client)経由でLinux(CentOS5)にある結果を確認!


Level16_res1

Level16_res2


ということで、Python Challenge Level 16完。 Level 17は気が向いたら載せると思います。 
Enjoy Python Challenge!

| | コメント (0) | トラックバック (0)

2008年3月 7日 (金)

Oracle de XMLDB #26 - XMLTYPEの更新

OTN-Jで、PL/SQLでXMLTYPEのあるの要素の値を変更したり、ある要素の値を参照したいというスレッドがあったのでレスしておいた。

そういえば、XQueryやXPathを使ったOracle XMLDBネタもやっているが更新系のはやってないな(というかまだ、XMLの更新、追加、削除に関する標準が定まっていないわけだから仕方ない。)

ということで、前述したOTN-Jのネタをもう少しフラッシュアップして?!(for updateなどが抜けていたので。。)残しておく事にした。

まず、hogehoge表に以下のようなXMLを登録する。

SCOTT> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SCOTT>
SCOTT> desc hogehoge
名前 NULL? 型
----------------------------------------- -------- ----------------------------
SEQNO NOT NULL NUMBER
XMLINFO XMLTYPE

SCOTT>
SCOTT> insert into hogehoge values(1,xmltype('<?xml version="1.0"?><addressbook>
<person id="1"><name>岡田</name><age>30</age>
<address zipcode="123456">東京都ホゲ市ホゲ町1−1</address></person><person id="2">
<name>安倍</name><age>50</age>
<address zipcode="1050011">東京都ホゲ区ホゲ田町1−1−1</address>
</person></addressbook>'));

1行が作成されました。

SCOTT> commit;

コミットが完了しました。

SCOTT>
SCOTT>
SCOTT> set timi on
SCOTT> set long 4000
SCOTT> col xmlinfo for a80
SCOTT> set linesize 132
SCOTT> set pagesize 1000
SCOTT> select * from hogehoge where seqno=1;

SEQNO XMLINFO
---------- ------------------------------------------------------------
1 <?xml version="1.0"?><addressbook><person id="1"><name>岡田<
/name><age>30</age><address zipcode="123456">東京都ホゲ市ホ
ゲ町1−1</address></person><person id="2"><name>安倍</name>
<age>50</age><address zipcode="1050011">東京都ホゲ区ホゲ田
町1−1−1</address></person></addressbook>


経過: 00:00:00.01
SCOTT>

上記のようなXML文書を対象に特定のid属性値を持つperson要素に含まれるname要素の値を変更するストアドファンクション。
(もうすこし平たく言うと、指定した名前を変更するストアドファンクション。略し過ぎか・・・)

XML文書の変更方法は他にもあるが、PL/SQLパッケージで行うにはDOM APIであるDBMS_XMLDOMパッケージを利用して行う。
尚、XMLTYPEをDBMS_XMLDOMパッケージで更新する際のポイントは、XMLTYPEインスタンスからDOMインスタンスを生成し、DOMインスタンに対して必要な更新操作行った上で、XMLTYPEインスタンスを表へ書き戻すという所。(該当部分は赤太字にしてあります。)

SCOTT> l
1 create or replace
2 function changePersonName
3 (
4 iKey in number,
5 iPersonId in varchar2,
6 iNewName in varchar2
7 ) return xmltype
8 is
9 xml xmlType;
10 personNodeList dbms_xmldom.DomNodeList;
11 personNode dbms_xmldom.DomNode;
12 nameNodeList dbms_xmldom.DomNodeList;
13 personAttrNodeMap dbms_xmldom.DomNamedNodeMap;
14 idAttrNode dbms_xmldom.DomNode;
15 wKey number;
16 wPersonId varchar2(38);
17 wNewName varchar2(60);
18 begin
19 wKey := iKey;
20 wPersonId := iPersonId;
21 wNewName := iNewName;
22
23 select xmlinfo into xml from hogehoge where seqno = wKey for update;
24
25 personNodeList := dbms_xmldom.getElementsByTagName(
26 dbms_xmldom.newDomDocument(xml)
27 ,'person'
28 );
29
30 if not dbms_xmldom.isNull(personNodeList) then
31 for i in 0..dbms_xmldom.getLength(personNodeList) loop
32 personNode := dbms_xmldom.item(personNodeList, i);
33 personAttrNodeMap := dbms_xmldom.getAttributes(personNode);
34 idAttrNode := dbms_xmldom.getNamedItem(personAttrNodeMap, 'id');
35 if dbms_xmldom.getNodeValue(idAttrNode) = wPersonId then
36 nameNodeList := dbms_xmldom.getChildrenByTagName(
37 dbms_xmldom.makeElement(personNode)
38 ,'name'
39 );
40 dbms_xmldom.setNodeValue(
41 dbms_xmldom.getFirstChild(dbms_xmldom.item(nameNodeList, 0))
42 ,wNewName
43 );
44 update hogehoge set xmlinfo = xml where seqno = wKey;
45 exit;
46 end if;
47 end loop;
48 end if;
49 return xml;
50* end;
SCOTT> /

ファンクションが作成されました。

経過: 00:00:00.04
SCOTT>
SCOTT>
SCOTT>
SCOTT> l
1 declare
2 xml xmlType;
3 begin
4 xml := changePersonName(1, '1', '福田ほげ蔵');
6 commit;
7* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.03
SCOTT>
SCOTT>
SCOTT> select * from hogehoge where seqno=1;
SEQNO XMLINFO
---------- --------------------------------------------------------------------------------
1 <?xml version="1.0"?>
<addressbook>
<person id="1">
<name>福田ほげ蔵</name>
<age>30</age>
<address zipcode="123456">東京都ホゲ市ホゲ町1−1</address>
</person>
<person id="2">
<name>安倍</name>
<age>50</age>
<address zipcode="1050011">東京都ホゲ区ホゲ田町1−1−1</address>
</person>
</addressbook>


経過: 00:00:00.00
SCOTT>

もうお気づきだと思うが、Oracle11gでも発生しているこちらからは操作できないところでwhitespaceが追加されたり、されなかったりする。まあこれ自体は大抵の場合問題にはならないのだが。。

あともうひとつの話題は特定の要素の値を取り出したいということ。これだけならDBMS_XMLDOMパッケージを使わなくても、SQL/XMLを使えば簡単ですよね。
XMLQuery()関数を使って、id属性値が "1"であるperson要素以下にあるage要素の値を参照する例です。

SCOTT> set linesize 80
SCOTT> l
1 select
2 xmlquery(
3 'let $n := $xmldoc//person[@id="1"]/age/text()
4 return $n'
5 passing by value xmlinfo as "xmldoc"
6 returning content
7 ) as "age"
8* from hogehoge where seqno=1
SCOTT> /

age
--------------------------------------------------------------------------------
30

経過: 00:00:00.04
SCOTT>

ちなみに、Oracleのマニュアルは以下の辺りを参照するとよいと思いますが、DOM、XQueryやXPathに関してはXML関連のサイトもググって調べたほうがよいと思います。XMLの操作の基本を理解していれば、あとはどんなツールを使ってそれを行うかということだけですから。

マニュアル
Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス 10g R2 - DBMS_XMLDOM
Oracle Database SQLリファレンス 10g R2 - XMLQUERY

Enjoy!

| | コメント (0) | トラックバック (0)

2007年12月21日 (金)

太った空白

書こうか迷っていたのだが、意外とハマっている方が多いらしいので書いておく事にした。
まあ、エラーメッセージがわかりずらいのでしょうがないとは思うが。

PL/SQLで開発する際に出くわす事がある。
(私もたまにやっちゃいますけどハマることはないです。こればかりは慣れるしかないですね。)

ということで太った空白のお話。

PL/SQLではマルチバイト文字の空白(全角の空白と言ったほうがわかりやすいでしょうか?)が原因で意味不明のコンパイルエラーを引き起こす。
そう、”太った空白”と書いたのはマルチバイト文字の空白。半角の空白が2つあるように見えるが全角の空白が1文字。

まずは、以下の例を見てください。

Last login: Fri Dec 21 08:25:31 on console
Welcome to Darwin!
G5Server:˜ discus$ su - oracle
Password:
G5Server:˜ oracle$ ssh oracle@corydoras
oracle@corydoras's password:
Last login: Sun Dec 16 18:02:52 2007 from 192.168.1.19
[oracle@corydoras ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 金 12月 21 19:50:10 2007

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

> conn scott/tiger
接続されました。
SCOTT> create or replace function now
2 return timestamp
3 is
4 begin
5  return systimestamp;
6 end;
7 /

警告: ファンクションが作成されましたが、コンパイル・エラーがあります。

SCOTT> show errors
FUNCTION NOWのエラーです。

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/3 PLS-00103: 記号""が見つかりました。 次のうちの1つが入るとき:
( begin case declare exit for goto if loop mod null pragma
raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> <<
continue close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe purge
記号"" は無視されました。

上記では、now()というストアドファンクションを作成しようとして5行目の3カラム目でコンパイルエラーが発生している。
(ストアドファンクション自体は意味の無いものなので気にしないでね。コンパイルエラーに注目してください。)

5行目の3カラム目は、"r"だなと思ったあなたは、もうすでにハマっていますよ。

実は、5行目の先頭の空白は半角の空白2文字ではなく”全角の空白1文字”なんです。

もうお分かりですよね。では、全角空白1文字を半角空白2文字に置換して再実行してみましょう。

SCOTT> list 5
5*  return systimestamp;
SCOTT> c / return/ return
5* return systimestamp;
SCOTT> l
1 create or replace function now
2 return timestamp
3 is
4 begin
5 return systimestamp;
6* end;
SCOTT> /

ファンクションが作成されました。

SCOTT> select now() from dual;

NOW()
---------------------------------------------------------------------------
07-12-21 19:56:19.046993000

SCOTT> /

| | コメント (0) | トラックバック (0)

2007年11月22日 (木)

Oracle de XMLDB #8 - またまた少々脱線

久々にOracle11gのXML DBネタなのだが、XQueryなどのXMLマスタープロフェッショナル(データベース)絡みのネタからはまた脱線。SQL/XMLネタを一つ。

以前、Oracle10g R1/R2上でRSS FEEDをPL/SQLで取得してOracle Application Expressで表示なんてことをやっていた。
(33回も連載してたっけ。。。。)

Mac De PL/SQL RSS Reader #1
Mac De PL/SQL RSS Reader #2

それらのエントリで、参照するXML文書の文字エンコーディングとデータベースキャラクタセットが異なると文字化けを起こしてしまうHttpUriType型の仕様?のことを書いていたのだが、先日リリースされたOracle11g R1ではどうなったのか?


確かめてみた! 

まずは、SQL/XMLを利用した例。(以下は、Oracle11g R1 for Linux x86を利用。)

XML文書の文字エンコーディングはUTF-8、Oracleデータベースのキャラクタセットは、JA16SJISTILDE。

SCOTT> r
1 select *
2 from
3 xmltable(
4 'for $i in //*
5 return $i'
6 passing httpuritype('http://discus-hamburg.cocolog-nifty.com/test/atom.xml').getXML()
7* )
passing httpuritype('http://discus-hamburg.cocolog-nifty.com/test/atom.xml').getXML()
*
行6でエラーが発生しました。:
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00244: 小なり不等号 ('<')文字の使用が無効です。 (&lt;を使用します)
Error at line 30
中にエラーが発生しました
ORA-06512: "SYS.XMLTYPE", 行5
ORA-06512: "SYS.HTTPURITYPE", 行97


SCOTT>


あ〜〜〜〜やっぱり、ダメね〜。上記はXML文書のパースエラーとして現れているのだが、その原因は文字化けなのである。


XML文書とOracleデータベースのキャラクタセットが異なる場合(前述の例では、UTF-8とSJIS)にはHttpUriType型を利用せず、UTL_HTTPパッケージを利用し、

UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');

のようにすることで文字化けせずにXML文書を取込むことができる。
尚、XML文書、データベースキャラクタセットが同一である場合(XML文書がUTF-8でデータベースキャラクタセットがAL32UTF8のような場合)には文字化けは発生しない。これは私個人の想像なのだが、HttpUriType型が裏でHTTP通信する際に利用する文字エンコーディングはデータベースキャラクタセットから導出しているのだと思われる。今のところHttpUriType型には文字エンコーディングは指定できないのでオラクルさんが方針を変えない限り文字化けの回避策は前述の2つしかないだろう。

2007/11/28追記
もしどうしてもXML文書の文字エンコーディングとデータベースキャラクタセットが異なる環境でHTTPURITYPE型を使いたいということであれば、代替策としてUTL_HTTPパッケージを利用したユーザ定義型を作成すれば可能かもしれない。
(あくまで推測。。あとで試してみるか=>TODO)

以前、DBMS_XMLPARSER.PARSE(parser, uri)を使ってFEEDを直接参照した場合も同様のエラーだったが、UTL_HTTPパッケージを利用して文字化けを回避した。
以下URL参照のこと。(下記のエントリの内容はOracle10g R1/R2で試したものです。)

Mac De PL/SQL RSS Reader #3

SQL/XML機能が充実してきたので今後はあまり使わなくなるかもしれないが、次いでなのでDBMS_XMLPARSER.PARSER(parser,uri)でも試してみた。
DBMS_XMLPARSER.PARSER(parser, uri)でもHttpUriType型を利用しているだろうから結果は同じはずだ。
(また、XMLマスタープロフェッショナル(データベース)ネタからは離れてく〜〜。w)

以前作成したコードを少々手直してOracle11gで実行!(Oracle SQL Developer for MacOSXを利用した)
Xmldb8_jdev


● ソース

CREATE OR REPLACE PROCEDURE GET_FEED(i_url IN VARCHAR2)
AS
v_url VARCHAR2(32767);
v_myParser DBMS_XMLPARSER.Parser;
v_rssDoc DBMS_XMLDOM.DomDocument;
v_xml XMLTYPE;

PROCEDURE println(str IN VARCHAR2)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE(str);
END;

PROCEDURE println
(
i_text IN CLOB
)
IS
v_tempStr VARCHAR(32767);
v_numOfPieces PLS_INTEGER;
BEGIN
v_numOfPieces := CEIL(LENGTH(i_text)/1000);
FOR i IN 1..v_numOfPieces LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(i_text, ((i-1)*1000), 1000));
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'println(CLOB) internal procedure:'
|| sqlerrm()
);
RAISE;
END println;

--****************************************************************************
--* Main
--****************************************************************************
BEGIN
DBMS_OUTPUT.ENABLE(200000);
println('begin...');


v_url := i_url;
IF v_url IS NULL THEN
RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。');
END IF;

v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSE(v_myParser, v_url);
v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
println('DBMS_XMLPARSERバージョン:'||DBMS_XMLPARSER.GETRELEASEVERSION());
println('DBMS_XMLDOMバージョン :'||DBMS_XMLDOM.GETVERSION(v_rssDoc));
println(' ');
println('=== パース済みDOMから取得したRSSソース ===');
println(XmlType.GETCLOBVAL(v_xml));
println('====================');
println(' ');
DBMS_XMLPARSER.FREEPARSER(v_myParser);

println('...End');

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'Main Procedure:'
|| sqlerrm()
);
RAISE;

END GET_FEED;


● 結果

RSS FEED(UTF-8)をデータベースキャラクタセット(JA16SJISTILDE)から取込んだ場合。
Connecting to the database Oracle11g R1 Scott(leaffish) - JA16SJISTILDE.
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00244: 小なり不等号 ('<')文字の使用が無効です。 (&lt;を使用します)
Error at line 30
中にエラーが発生しました
ORA-06512: "SCOTT. GET_FEED", 行161
ORA-06512: 行6
begin...
Main Procedure:ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00244: 小なり不等号 ('<')文字の使用が無効です。 (&lt;を使用します)
Error at line 30
中にエラーが発生しました
Process exited.
Disconnecting from the database Oracle11g R1 Scott(leaffish) - JA16SJISTILDE.


RSS FEED(UTF-8)をデータベースキャラクタセット(AL32UTF8)から取込んだ場合。文字エンコーディングが同じ場合は問題なし!
ところで、Oracle11g R1でも、DBMS_XMLPARSERのパージョンは10.1.0.2.0なのね〜。(^^;;;

Connecting to the database Oracle11g R1 Scott(guppy) - AL32UTF8.
begin...
DBMS_XMLPARSERバージョン:10.1.0.2.0
DBMS_XMLDOMバージョン :1.0

=== パース済みDOMから取得したRSSソース ===
<?xml version="1.0" encoding="utf-8"?>

<feed xmlns="http://www.w3.org/2005/Atom">
<title>Mac De Oracle</title>
<link rel="alternate" type="text/html" href="http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/" />
<link rel="service.post" type="application/x.atom+xml" href="http://app.cocolog-nifty.com/t/atom/weblog/blog_id=121907" title="Mac De Oracle" />
<id>tag:app.cocolog-nifty.com,2003:weblog-121907</id>
<updated>2007-11-19T09:16:39Z</updated>


・・・・中略・・・・


<summary>前回、何かが違うと感じたと書いたがそれはなにか? 実はwhitespaceに関す...</summary>
<author>
<name>discus</name>
</author>
<category term="Linux" />
<category term="Oracle" />
<category term="Oracle Database 11g" />
<category term="XML" />




</entry>

</feed>
====================

...End
Process exited.
Disconnecting from the database Oracle11g R1 Scott(guppy) - AL32UTF8.


尚、Oracle11g R1ではセキュリティが強化されている。(Oracle10g R2以前のセキュリティレベルにもできるようだが。。)上記のコードをそのまま実行しようとするとエラーになる。

ということで、セキュリティ関連も含めて続きは次回ということで。


おまけ

以下の資料はSQL/XMLって何? ってとこからスタートする方にはよいかも..。
オープンソースカンファレンス2007 .DBの資料「XQuery、XPath 及び SQL / XML に関する標準化動向と今後の取組み状況」 (PDF)

以下のサイトにはSQL/XML関連の情報がいろいろ(英語です。)
SQLX.org

その他、OTN-Jなどにもあったかも。。。(未確認)

| | コメント (0) | トラックバック (0)

2007年10月17日 (水)

DBMS_OUTPUT.PUT_LINE()/PUT()の出力制限

Oracle10g R2からDBMS_OUTPUT.PUT_LINE()/PUT()関数で出力できる1行最大サイズが、255バイトから32767バイトへ拡張されたことはご存知だろうか?
PL/SQLでプログラミングしている方ならほとんどの方がお世話になったことがあると思うDBMS_OUTPUT.PUT_LINE()/PUT()関数。これらの関数は、Oracle7のころから、ず〜〜〜〜〜っと255バイトが最大サイズだった。
それが、Oracle10g R2になって、いきなり32767バイト(このサイズは、VARCHAR2型のPL/SQL内での最大サイズに等しい)まで拡張された。(うれしいというか、便利にというか、楽にはなったかもしれない。)
だが、いままで工夫して利用してきているだけに、意外とそのまんまになっていたり、32767バイトまで拡張されたということを知らない方も多いようなので、ネタとしてはあまり新しいとは思えないのだが取り上げておく事にした。

ということで、Oracle10g R1 10.1.0.4.0とOracle10g R2 10.2.0.1.0を利用して実際に違いを確認。

以下の無名PL/SQLブロックでは、 255バイト/256バイト/32767バイト/32768バイトの各文字列をDBMS_OUTPUT.PUT_LINE()関数で出力するコードである。
DBMS_OUTPUT.PUT_LINE()/PUT()関数の制限により、Oracle10g R2より前のリリースでは、256バイト以上の文字列を出力しようと場合/Oracle10g R2以降では32768バイト以上の文字列を出力しようとするとエラーになる。

● Oracle10g R2 10.2.0.1.0の例

32768バイトの文字列を出力しようとした場合だけがエラーになっていることが確認できる。
SCOTT> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SCOTT> set serveroutput on size 100000
SCOTT> l
1 declare
2 str255 varchar2(255) := rpad('255',255,'*');
3 str256 varchar2(256) := rpad('256',256,'*');
4 str32767 varchar2(32767) := rpad('32767',32767,'*');
5 begin
6 dbms_output.put_line(str255);
7 begin
8 dbms_output.put_line(str256);
9 exception
10 when others then
11 dbms_output.put_line(sqlerrm());
12 end;
13 dbms_output.put_line(str32767);
14 begin
15 dbms_output.put_line(str32767||'*');
16 exception
17 when others then
18 dbms_output.put_line(sqlerrm());
19 end;
20* end;
SCOTT> /
255*****************************************************************************
********************************************************************************
********************************************************************************
***************
256*****************************************************************************
********************************************************************************
********************************************************************************
****************
32767***************************************************************************
********************************************************************************
・・・・・中略・・・・・
********************************************************************************
********************************************************************************
********************************************************************************
***********************************************
ORA-20000: ORU-10028: line length overflow, limit of 32767 bytes per line

PL/SQLプロシージャが正常に完了しました。

SCOTT>

● Oracle10g R1 10.1.0.4.0の例

256バイト以上の文字列を出力しようとした場合、全てがエラー。当然!
SCOTT> conn scott@fishtank
パスワードを入力してください:
接続されました。
SCOTT> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0 - Prod
PL/SQL Release 10.1.0.4.0 - Production
CORE 10.1.0.4.0 Production
TNS for Linux: Version 10.1.0.4.0 - Production
NLSRTL Version 10.1.0.4.0 - Production

SCOTT> set serveroutput on size 100000
SCOTT> l
1 declare
2 str255 varchar2(255) := rpad('255',255,'*');
3 str256 varchar2(256) := rpad('256',256,'*');
4 str32767 varchar2(32767) := rpad('32767',32767,'*');
5 begin
6 dbms_output.put_line(str255);
7 begin
8 dbms_output.put_line(str256);
9 exception
10 when others then
11 dbms_output.put_line(sqlerrm());
12 end;
13 begin
14 dbms_output.put_line(str32767);
15 exception
16 when others then
17 dbms_output.put_line(sqlerrm());
18 end;
19 begin
20 dbms_output.put_line(str32767||'*');
21 exception
22 when others then
23 dbms_output.put_line(sqlerrm());
24 end;
25* end;
SCOTT> /
255*****************************************************************************
********************************************************************************
********************************************************************************
***************
ORA-20000: ORU-10028: line length overflow, limit of 255 chars per line
ORA-20000: ORU-10028: line length overflow, limit of 255 chars per line
ORA-20000: ORU-10028: line length overflow, limit of 255 chars per line

PL/SQLプロシージャが正常に完了しました。

SCOTT>

以上で、Oracle10g R2以降でのDBMS_OUTPUT.PUT_LINE()/PUT()関数の拡張は確認できた。PL/SQL内では、32767バイトがVARCHAR2型の最大サイズなので、32767バイト以内の出力であればDBMS_OUTPUT.PUT_LINE()/PUT()関数1行で済むということはかなり便利だ。(32768バイト以上の出力には今まで通りのコードが必要だが。。。)

ここまでやったついでに、以前紹介したPL/SQLの条件付きコンパイルを利用してOracle9i R2 9.2.0.6.0以降、Oracle10g R1 10.1.0.4.0以降、それに、Oracle10g R2及び、Oracle11g R1の各リリースでコード共有の例を1つ。

以下のサンプルコードは、最大32767バイトまでの文字列を引数で受け取り、DBMS_OUTPUT.PUT_LINE()で表示するという単純なコードだ。


● Oracle10g R1 10.1.0.4.0

PL/SQLの条件付きコンパイルは、Oracle10g R1ではデフォルトでは機能しない。隠しパラメータをTRUEに設定する必要がある。
SYS> show parameter _plsql_conditional

NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
_plsql_conditional_compilation boolean TRUE
SYS> conn scott@fishtank
パスワードを入力してください:
接続されました。
SCOTT> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0 - Prod
PL/SQL Release 10.1.0.4.0 - Production
CORE 10.1.0.4.0 Production
TNS for Linux: Version 10.1.0.4.0 - Production
NLSRTL Version 10.1.0.4.0 - Production

SCOTT> set serveroutput on size 100000
SCOTT> l
1 CREATE OR REPLACE PROCEDURE dbms_output_test
2 (
3 i_str IN VARCHAR2
4 )
5 IS
6 v_str VARCHAR2(32767);
7 $IF DBMS_DB_VERSION.VERSION <= 9
8 OR (DBMS_DB_VERSION.VERSION = 10
9 AND DBMS_DB_VERSION.RELEASE < 2)
10 $THEN
11 v_pices PLS_INTEGER;
12 C_NumOfChars CONSTANT PLS_INTEGER := 85;
13 $END
14 BEGIN
15 v_str := i_str;
16 $IF DBMS_DB_VERSION.VERSION <= 9
17 OR (DBMS_DB_VERSION.VERSION = 10
18 AND DBMS_DB_VERSION.RELEASE < 2)
19 $THEN
20 v_pices := CEIL(LENGTHB(v_str)/C_NumOfChars);
21 FOR i IN 1..v_pices LOOP
22 DBMS_OUTPUT.PUT_LINE(SUBSTR(v_str,(i-1)*C_NumOfChars+1,C_NumOfChars));
23 END LOOP;
24 $ELSE
25 DBMS_OUTPUT.PUT_LINE(v_str);
26 $END
27* END;
SCOTT> /

プロシージャが作成されました。

SCOTT>

Oracle10g R1環境で条件付きコンパイル後のコードを確認!

SCOTT> exec dbms_preprocessor.print_post_processed_source('PROCEDURE','SCOTT','DBMS_OUTPUT_TEST');
PROCEDURE dbms_output_test
(
i_str IN VARCHAR2
)
IS
v_str VARCHAR2(32767);
v_pices PLS_INTEGER;
C_NumOfChars CONSTANT PLS_INTEGER := 85;
BEGIN
v_str := i_str;
v_pices := CEIL(LENGTHB(v_str)/C_NumOfChars);
FOR i IN 1..v_pices LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(v_str,(i-1)*C_NumOfChars+1,C_NumOfChars));
END LOOP;
END;

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> exec dbms_output_test(rpad('32767',32767,'*'));
32767********************************************************************************
*************************************************************************************
*************************************************************************************
・・・・・中略・・・・・
*************************************************************************************
*************************************************************************************
******************************************

PL/SQLプロシージャが正常に完了しました。

SCOTT>

● Oracle10g R2 10.2.0.1.0

Oracle10g R2ではPL/SQLの条件付きコンパイルは最初から有効になっている。
SCOTT> set serveroutput on size 100000
SCOTT> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SCOTT> l
1 CREATE OR REPLACE PROCEDURE dbms_output_test
2 (
3 i_str IN VARCHAR2
4 )
5 IS
6 v_str VARCHAR2(32767);
7 $IF DBMS_DB_VERSION.VERSION <= 9
8 OR (DBMS_DB_VERSION.VERSION = 10
9 AND DBMS_DB_VERSION.RELEASE < 2)
10 $THEN
11 v_pices PLS_INTEGER;
12 C_NumOfChars CONSTANT PLS_INTEGER := 85;
13 $END
14 BEGIN
15 v_str := i_str;
16 $IF DBMS_DB_VERSION.VERSION <= 9
17 OR (DBMS_DB_VERSION.VERSION = 10
18 AND DBMS_DB_VERSION.RELEASE < 2)
19 $THEN
20 v_pices := CEIL(LENGTHB(v_str)/C_NumOfChars);
21 FOR i IN 1..v_pices LOOP
22 DBMS_OUTPUT.PUT_LINE(SUBSTR(v_str,(i-1)*C_NumOfChars+1,C_NumOfChars));
23 END LOOP;
24 $ELSE
25 DBMS_OUTPUT.PUT_LINE(v_str);
26 $END
27* END;
SCOTT> /

プロシージャが作成されました。

Oracle10g R2で条件コンパイル後のコードを確認!(コードがこんなにシンプルに!)

SCOTT> exec dbms_preprocessor.print_post_processed_source('PROCEDURE','SCOTT','DBMS_OUTPUT_TEST');
PROCEDURE dbms_output_test
(
i_str IN VARCHAR2
)
IS
v_str VARCHAR2(32767);
BEGIN
v_str := i_str;
DBMS_OUTPUT.PUT_LINE(v_str);
END;

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec dbms_output_test(rpad('32767',32767,'*'));
32767***************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
・・・・・中略・・・・・
********************************************************************************
********************************************************************************
***********************************************

PL/SQLプロシージャが正常に完了しました。

SCOTT>

| | コメント (0) | トラックバック (0)

2007年10月16日 (火)

Oracle de XMLDB #3 - Oracle10g XEではどうよ?

OracleのXMLDBを試す簡単な環境は? ということで、Oracle10g R2 Express Editionを試してみた。
だが・・・・・今のところ利用できないようだ。次のリリースに期待。

バックナンバー:
Oracle de XMLDB #1
Oracle de XMLDB #2


以下、前回、Oracle Database 11gを構築したPC(CentOS 5)に、Oracle10g R2 Express Edition for Linux x86を追加インストールして試した記録。
尚、Oracle10g EXへは、同環境へインストール済みOracle Database 11g R1のSQL*Plusから接続した。(MacOSXからssh接続しているため、その方が楽だったので・・・)

G5Server:˜ oracle$ ssh oracle@glasscatfish
oracle@glasscatfish's password:
[oracle@glasscatfish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 火 10月 16 0:04:43 2007

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

> conn sys@xe as sysdba
パスワードを入力してください:
接続されました。
SYS>
SYS> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SYS> select comp_name,version,status from dba_registry;

COMP_NAME VERSION STATUS
-------------------------------------------------- ------------------------------ ----------
Oracle Database Catalog Views 10.2.0.1.0 VALID
Oracle Database Packages and Types 10.2.0.1.0 VALID
Oracle Text 10.2.0.1.0 VALID
Oracle XML Database 10.2.0.1.0 VALID

SYS>
SYS> !
[oracle@glasscatfish ˜]$ ll
合計 8
drwxr-xr-x 2 oracle oinstall 4096 10月 14 15:32 Desktop
[oracle@glasscatfish ˜]$ pwd
/home/oracle
[oracle@glasscatfish ˜]$ mkdir scott_xmldir
[oracle@glasscatfish ˜]$ ll
合計 16
drwxr-xr-x 2 oracle oinstall 4096 10月 14 15:32 Desktop
drwxr-xr-x 2 oracle oinstall 4096 10月 14 15:44 scott_xmldir
[oracle@glasscatfish ˜]$ cd scott_xmldir
[oracle@glasscatfish scott_xmldir]$ cat list1.xml
<?xml version="1.0" encoding="UTF-8" ?>
<顧客名簿>
<顧客 id="128">
<住所>
<郵便番号>123-4567</郵便番号>
<都道府県>千葉県</都道府県>
<市町村名>浦安市</市町村名>
<町名番地>舞浜1-2-3</町名番地>
</住所>
<電話 タイプ="会社">03-1234-5678</電話>
<電話 タイプ="自宅">03-5555-6666</電話>
<電話 タイプ="携帯">090-1112-4444</電話>
<ファックス>03-8888-7777</ファックス>
<Eメール>hoge@macdeoracle.jp</Eメール>
</顧客>
<顧客 id="256">
<住所>
<郵便番号>155-5555</郵便番号>
<都道府県>東京都</都道府県>
<市町村名>世田谷区</市町村名>
<町名番地>用賀1-2-3</町名番地>
</住所>
<電話 タイプ="会社">03-7575-7575</電話>
<電話 タイプ="自宅">03-8585-8585</電話>
<電話 タイプ="携帯">090-9191-9191</電話>
<ファックス>03-4141-4141</ファックス>
<Eメール>hoge@discushamburg.jp</Eメール>
</顧客>
<顧客 id="512">
<住所>
<郵便番号>345-4567</郵便番号>
<都道府県>大阪府</都道府県>
<市町村名>中央区</市町村名>
<町名番地>難波2-2-2</町名番地>
</住所>
<電話 タイプ="会社">06-1234-5678</電話>
<電話 タイプ="自宅">06-5555-6666</電話>
<電話 タイプ="携帯">090-0606-0606</電話>
<ファックス>06-8888-7777</ファックス>
<Eメール>hoge@lampeye.jp</Eメール>
</顧客>
</顧客名簿>
[oracle@glasscatfish scott_xmldir]$ exit
exit

SYS>
SYS> create directory scott_xmldir as '/home/oracle/scott_xmldir';

ディレクトリが作成されました。

SYS> grant read on directory scott_xmldir to scott;

権限付与が成功しました。

SYS> grant write on directory scott_xmldir to scott;

権限付与が成功しました。

SYS>

SYS>
SYS>
SYS> conn scott@xe
パスワードを入力してください:
接続されました。
SCOTT>
SCOTT> declare
2 isSuccess boolean;
3 begin
4 isSuccess := dbms_xdb.createfolder('/public/scott');
5 end;
6 /

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> l
1 declare
2 r boolean;
3 begin
4 r := dbms_xdb.createresource(
5 '/public/scott/list1.xml',
6 bfilename('SCOTT_XMLDIR','list1.xml'),
7 nls_charset_id('AL32UTF8'));
8* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> xquery
2 let $n := let("/public/scott/list1.xml")
3 return $n
4 /
ERROR:
ORA-19114: XQuery式を解析中にエラーが発生しました:
ORA-06550:行1、列13:
PLS-00201: 識別子SYS.DBMS_XQUERYINTを宣言してください。
ORA-06550:行1、列7:
PL/SQL: Statement ignored


SCOTT>

この日本語のメッセージでググっても、おそらく Oracle10g R2 XE上のXMLDBに関するものはヒットしないだろうということで・・・・

SCOTT> xquery
2 let $n := fn:doc("/public/scott/list1.xml")
3 return $n
4 /
ERROR:
ORA-19114: error during parsing the XQuery expression:
ORA-06550: line 1, column 13:
PLS-00201: identifier 'SYS.DBMS_XQUERYINT' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

英語メッセージに切り替え、英語のメッセージを表示させてからググってみた。
すると、ありましたよ。US OTNに。

http://forums.oracle.com/forums/message.jspa?messageID=1280038#1280038

ということで、Express Editionでは今のところこの機能は動作しないようだ。
次のリリースに期待するしかなさそうですね。



ついに、奥さんがMacBook Pro 15inchを購入、本日届いた! これで、このCentOS5+Oracle11gの環境も初期化して、初代のiMac G5どもども下取だな、そろそろ。
さてさて、LinuxのOracle11g環境を別に作らねば。。

| | コメント (0) | トラックバック (0)

2007年10月15日 (月)

Oracle de XMLDB #1

前回のエントリでXML Master Professional Database認定試験向けのお勉強用環境をOracle10g/11g環境で作ろうかな。と書いたが早速作ってみた。

Oracle10g R2/Oracle11g R1をインストールすればXMLDBは標準でインストールされているので特に問題になることはないと思う。

ところで、Oracle10g R2からSQL*PlusからXQueryを直接実行できるようになっているのだが、ご存知だろうか?
この例では、Oracle XML RepositoryへXML文書を登録し、SQL*PlusからXQueryを直接発行する環境を作ってみる。

参考:
Oracle XML DB開発者ガイド 10gリリース2(10.2)- 20 Oracle XML DBリポジトリのデータへのアクセス
Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス 10g リリース2(10.2)- 120 DBMS_XDB

まず、今回利用した環境の情報から。
OSは、CentOS4.4(Final) 32bit そう、今年始めに構築した、Oracle10g R2 の Linux RAC環境を利用した。 (Oracle11g R1 EEの環境もあるのだが手順は同じなので Oracle10g R2で構築した例を載せておく。)

[oracle@discus1 ˜]$ uname -svr
Linux 2.6.9-42.EL #1 Sat Aug 12 09:17:58 CDT 2006
[oracle@discus1 ˜]$ cat /etc/redhat-release
CentOS release 4.4 (Final)
[oracle@discus1 ˜]$ srvctl status database -d orcl
インスタンスorcl1はノードdiscus1で実行中です。
インスタンスorcl2はノードdiscus2で実行中です。
[oracle@discus1 ˜]$ srvctl status nodeapps -n discus1
VIPはノードで実行中です: discus1
GSDはノードで実行中です: discus1
リスナーはノードで実行中です: discus1
ONSデーモンはノードで実行中です: discus1
[oracle@discus1 ˜]$ srvctl status nodeapps -n discus2
VIPはノードで実行中です: discus2
GSDはノードで実行中です: discus2
リスナーはノードで実行中です: discus2
ONSデーモンはノードで実行中です: discus2
[oracle@discus1 ˜]$


SYS> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SYS>
SYS> select comp_name,version,status from dba_registry where comp_name like '%XML%';

COMP_NAME VERSION STATUS
-------------------------------------------------- ------------------------------ ----------
Oracle XML Database 10.2.0.1.0 VALID

SYS>


テストに利用するXMLファイル(list1.xml)を $ORACLE_HOME/scott_xmldir以下に作成

[oracle@discus1 scott_xmldir]$ ll
合計 4
-rw-r--r-- 1 oracle dba 2078 10月 13 21:28 list1.xml
[oracle@discus1 scott_xmldir]$ pwd
/u01/app/oracle/scott_xmldir/
[oracle@discus1 scott_xmldir]$ cat list1.xml
<?xml version="1.0" encoding="UTF-8"?>
<顧客名簿>
<顧客 id="128">
<住所>
<郵便番号>123-4567</郵便番号>
<都道府県>千葉県</都道府県>
<市町村名>浦安市</市町村名>
<町名番地>舞浜1-2-3</町名番地>
</住所>
<電話 タイプ="会社">03-1234-5678</電話>
<電話 タイプ="自宅">03-5555-6666</電話>
<電話 タイプ="携帯">090-1112-4444</電話>
<ファックス>03-8888-7777</ファックス>
<Eメール>hoge@macdeoracle.jp</Eメール>
</顧客>
<顧客 id="256">
<住所>
<郵便番号>155-5555</郵便番号>
<都道府県>東京都</都道府県>
<市町村名>世田谷区</市町村名>
<町名番地>用賀1-2-3</町名番地>
</住所>
<電話 タイプ="会社">03-7575-7575</電話>
<電話 タイプ="自宅">03-8585-8585</電話>
<電話 タイプ="携帯">090-9191-9191</電話>
<ファックス>03-4141-4141</ファックス>
<Eメール>hoge@discushamburg.jp</Eメール>
</顧客>
<顧客 id="512">
<住所>
<郵便番号>345-4567</郵便番号>
<都道府県>大阪府</都道府県>
<市町村名>中央区</市町村名>
<町名番地>難波2-2-2</町名番地>
</住所>
<電話 タイプ="会社">06-1234-5678</電話>
<電話 タイプ="自宅">06-5555-6666</電話>
<電話 タイプ="携帯">090-0606-0606</電話>
<ファックス>06-8888-7777</ファックス>
<Eメール>hoge@lampeye.jp</Eメール>
</顧客>
</顧客名簿>
[oracle@discus1 scott_xmldir]$


$ORACLE_HOME/scott_xmldirをdirectoryオブジェクトとして作成。今の所読み込みだけで十分だが、書き込み権限も付与しておく。

SYS> create directory scott_xmldir as '/u01/app/oracle/scott_xmldir/';

ディレクトリが作成されました。

SYS> grant read on directory scott_xmldir to scott;

権限付与が成功しました。

SYS> grant write on directory scott_xmldir to scott;

権限付与が成功しました。

SYS>

SYS>


この例では、XMLファイルをOracle XML repositoryへ登録する。/publicフォルダ以下に scott/xmlフォルダを追加作成後、/public/scott/xml以下へ対象のXMLファイルを登録する。
尚、データベースキャラクタセットは、AL32UTF8であり、登録するXMLファイルのエンコーディングは、UTF-8とした。

まず、/publicフォルダ以下に、scottフォルダを作成する。
SYS> conn scott@orcltest
パスワードを入力してください:
接続されました。

SCOTT> declare
2 r boolean;
3 begin
4 r := dbms_xdb.createfolder('/public/scott');
5 end;
6 /

PL/SQLプロシージャが正常に完了しました。

次に、/public/scottフォルダ以下に、xmlフォルダを作成する。
SCOTT> l
1 declare
2 r boolean;
3 begin
4 r := dbms_xdb.createfolder('/public/scott/xml');
5* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

/public/scott/xmlフォルダ直下へSCOTT_XMLDIRディレクトリオブジェクト以下にあるxmlファイル(list1.xml)を登録し、パスを/public/scott/xml/list1.xmlとする。
SCOTT> l
1 declare
2 r boolean;
3 begin
4 r := dbms_xdb.createresource(
5 '/public/scott/xml/list1.xml',
6 bfilename('SCOTT_XMLDIR','list1.xml'),
7 nls_charset_id('AL32UTF8'));
8* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT>


最後に、確認の意味を含めて、XML repositoryへ登録したxmlをXQueryを利用して、SQL*Plusから直接問い合わせてみる。

SCOTT> set long 4000
SCOTT> l
1 xquery
2 let $d := fn:doc("/public/scott/xml/list1.xml")
3* return $d
SCOTT> /

Result Sequence
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?><顧客名簿><顧客 id="128"><住所><郵便番号>123-4567</郵便番号><都道府県>千葉県</都道府県><市町村
名>浦安市</市町村名><町名番地>舞浜1-2-3</町名番地></住所><電話 タイプ="会社">03-1234-5678</電話><電話 タイプ="自宅">03-5555-6666</電
話><電話 タイプ="携帯">090-1112-4444</電話><ファックス>03-8888-7777</ファックス><Eメール>hoge@macdeoracle.jp</Eメール></顧客><顧客 i
d="256"><住所><郵便番号>155-5555</郵便番号><都道府県>東京都</都道府県><市町村名>世田谷区</市町村名><町名番地>用賀1-2-3</町名番地></
住所><電話 タイプ="会社">03-7575-7575</電話><電話 タイプ="自宅">03-8585-8585</電話><電話 タイプ="携帯">090-9191-9191</電話><ファック
ス>03-4141-4141</ファックス><Eメール>hoge@discushamburg.jp</Eメール></顧客><顧客 id="512"><住所><郵便番号>345-4567</郵便番号><都道府
県>大阪府</都道府県><市町村名>中央区</市町村名><町名番地>難波2-2-2</町名番地></住所><電話 タイプ="会社">06-1234-5678</電話><電話 タ
イプ="自宅">06-5555-6666</電話><電話 タイプ="携帯">090-0606-0606</電話><ファックス>06-8888-7777</ファックス><Eメール>hoge@lampeye.jp
</Eメール></顧客></顧客名簿>



SCOTT>

ここまでできれば、XQuery1.0の実行は、SQL*Plusからダイレクトに行えるようになる。 簡単!。

あとは、いろいろなXQueryを試すのみ! Enjoy!

| | コメント (0) | トラックバック (1)

2007年10月13日 (土)

DBMS_COMPARISONパッケージ で表データの比較 #6

「DBMS_COMPARISONパッケージで表データの比較」のつづき。

マニュアルは、DBMS_COMPARISONを利用するための前提が記載されているいるので、前提を満たしていないとどんなエラーになるか試してみた。

バックナンバー:
DBMS_COMPARISONパッケージ で表データの比較 #1
DBMS_COMPARISONパッケージ で表データの比較 #2
DBMS_COMPARISONパッケージ で表データの比較 #3
DBMS_COMPARISONパッケージ で表データの比較 #4
DBMS_COMPARISONパッケージ で表データの比較 #5



● もしも、2つの表に前提を満たす主キー制約が無かったら。。。。。

SCOTT> alter table emp2 drop constraint emp2_pk;

表が変更されました。

SCOTT> create table emp3 as select * from emp2;

表が作成されました。

SCOTT> begin
2 dbms_comparison.create_comparison(
3 comparison_name => '索引の無い表の比較',
4 schema_name => 'SCOTT',
5 object_name => 'EMP2',
6 dblink_name => null,
7 remote_schema_name => 'SCOTT',
8 remote_object_name => 'EMP3'
9 );
10 end;
11 /
begin
*
行1でエラーが発生しました。:
ORA-23626: 適格な索引が表SCOTT.EMP2にありません
ORA-06512: "SYS.DBMS_COMPARISON", 行4197
ORA-06512: "SYS.DBMS_COMPARISON", 行420
ORA-06512: 行2

ちなみに、ローカル表には主キー制約があり、リモート表(実際にリモートデータベーベースにある表、マテリアライズドビューである必要はない)に主キー制約が存在しない場合は、DBMS_COMPARISONパッケージは可能だった。
ただしその場合、データを比較する際リモート表が全表走査されることになるだろう(実際にトレース取ったわけではないが・・)から、主キー制約、または一意制約はあったほうがよいだろう。(この点には注意が必要だが、主キーベースのレプリケーション環境では影響はないかと。。)


そういえば、XML Master Professional Databaseが今年の12月から開始予定とのことなので、そろそろ、XML絡みのネタを増やしていこうか・・・、Oracle9i/10g さらに11gとXML DBとしての機能も強化してきたOracleなのでOracleを使ってXML Master Professional Databaseの受験対策環境作っておくのもいいなぁ・・・準備しておくか・・・

| | コメント (0) | トラックバック (0)

DBMS_COMPARISONパッケージ で表データの比較 #5

「DBMS_COMPARISONパッケージで表データの比較」の続きです。

表の内容を比較すると比較結果がどんどん記録されていく。不要になった比較結果は削除しときましょ。

バックナンバー:
DBMS_COMPARISONパッケージ で表データの比較 #1
DBMS_COMPARISONパッケージ で表データの比較 #2
DBMS_COMPARISONパッケージ で表データの比較 #3
DBMS_COMPARISONパッケージ で表データの比較 #4



purge_comparison()drop_comparison()、関数名だけだと何を削除するのか分かりにくいな〜。ということでこれらの関数の確認も。。

● 比較結果をpurge_comparison()関数でパージする。

DBMS_COMPARISON.COMPARE()関数を実行すると、比較結果の詳細やサマリーなどが記録される。
不要になった結果はpurge_comparison()関数で、後始末。

SCOTT> select scan_id,comparison_name from user_comparison_scan order by scan_id;

SCAN_ID COMPARISON_NAME
---------- ------------------------------
1 EMP表の比較
2 EMP表の比較
3 EMP表の比較
4 EMP表の比較
5 EMP表の比較
6 EMP表の比較
7 EMP表の比較

7行が選択されました。

SCOTT> select scan_id,comparison_name from user_comparison_scan_summary order by scan_id;

SCAN_ID COMPARISON_NAME
---------- ------------------------------
1 EMP表の比較
2 EMP表の比較
3 EMP表の比較
4 EMP表の比較
5 EMP表の比較
6 EMP表の比較
7 EMP表の比較

7行が選択されました。

SCOTT> select scan_id,comparison_name from user_comparison_scan_values order by scan_id;

SCAN_ID COMPARISON_NAME
---------- ------------------------------
1 EMP表の比較
2 EMP表の比較
3 EMP表の比較
4 EMP表の比較
5 EMP表の比較
6 EMP表の比較
7 EMP表の比較

7行が選択されました。


SCOTT> select scan_id,comparison_name from user_comparison_row_dif order by scan_id;

SCAN_ID COMPARISON_NAME
---------- ------------------------------
3 EMP表の比較
4 EMP表の比較
4 EMP表の比較
6 EMP表の比較

SCOTT>

以下、指定したcomparisonに関連する比較結果全てをパージする例。
SCOTT> exec dbms_comparison.purge_comparison('EMP表の比較');

PL/SQLプロシージャが正常に完了しました。

SCOTT> select scan_id,comparison_name from user_comparison_scan order by scan_id;

レコードが選択されませんでした。

SCOTT> select scan_id,comparison_name from user_comparison_scan_summary order by scan_id;

レコードが選択されませんでした。

SCOTT> select scan_id,comparison_name from user_comparison_scan_values order by scan_id;

レコードが選択されませんでした。

SCOTT> select scan_id,comparison_name from user_comparison_row_dif order by scan_id;

レコードが選択されませんでした。

SCOTT>


● comparisonをdrop_comparison()関数で削除する。

作成したcomparisonが不要になったら、drop_comparison()関数で削除。
SCOTT> select comparison_name from user_comparison;

COMPARISON_NAME
------------------------------
EMP表の比較

SCOTT> select comparison_name,column_position from user_comparison_columns;

COMPARISON_NAME COLUMN_POSITION
------------------------------ ---------------
EMP表の比較 1
EMP表の比較 2
EMP表の比較 3
EMP表の比較 4
EMP表の比較 5
EMP表の比較 6
EMP表の比較 7
EMP表の比較 8

8行が選択されました。

SCOTT> exec dbms_comparison.drop_comparison('EMP表の比較');

PL/SQLプロシージャが正常に完了しました。

SCOTT> select comparison_name from user_comparison;

レコードが選択されませんでした。

SCOTT> select comparison_name,column_position from user_comparison_columns;

レコードが選択されませんでした。

SCOTT>

| | コメント (0) | トラックバック (0)

2007年10月12日 (金)

DBMS_COMPARISONパッケージ で表データの比較 #4

「DBMS_COMPARISONパッケージで表データの比較」の続きです。

バックナンバー:
DBMS_COMPARISONパッケージ で表データの比較 #1
DBMS_COMPARISONパッケージ で表データの比較 #2
DBMS_COMPARISONパッケージ で表データの比較 #3




奥さんが、新しいMacBook Proを購入したので、今奥さんが使っているiMac G5とOracle Database 11g R1 + CentOS 5で遊んでいるIBM ThinkPad R52が下取り処分に。。。

あ〜〜〜、もう少しだけ遊ばせて〜〜〜! と慌てたり。。。まあ、DBMS_COMPARISONパッケージを試す程度はできそうですが。。。さて、Oracle11gで遊ぶ環境が無くなる〜。

どうしよう。。。既存の環境をつぶさなければインストールできそうにない、TurboLinux(United Linux 1.0)+Oracle9i R2/Oracle10g R1環境を潰すか。。

なんて、前置きはこれくらいにして。

● CONVERGE()関数でデータを一致させる。

EMP表の内容にEMP2表の内容を合わせるように指定して実行!。異なるデータだけが処理対象となっていることにお気づきだろうか。。
SCOTT> set serveroutput on
SCOTT> l
1 DECLARE
2 scanInfo DBMS_COMPARISON.COMPARISON_TYPE;
3 BEGIN
4 DBMS_COMPARISON.CONVERGE(
5 comparison_name => 'EMP表の比較',
6 scan_id => 2,
7 scan_info => scanInfo,
8 converge_options => DBMS_COMPARISON.CMP_CONVERGE_LOCAL_WINS

9 );
10 DBMS_OUTPUT.PUT_LINE('ScanID:'||to_char(scanInfo.scan_id));
11 DBMS_OUTPUT.PUT_LINE('Local rows merged:'||to_char(scanInfo.loc_rows_merged));
12 DBMS_OUTPUT.PUT_LINE('Remote rows merged:'||to_char(scanInfo.rmt_rows_merged));
13 DBMS_OUTPUT.PUT_LINE('Local rows deleted:'||to_char(scanInfo.loc_rows_deleted));
14 DBMS_OUTPUT.PUT_LINE('Remote rows deleted:'||to_char(scanInfo.rmt_rows_deleted));
15* END;
SCOTT> /
ScanID:2
Local rows merged:0
Remote rows merged:2
Local rows deleted:0
Remote rows deleted:1

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> select * from emp order by empno;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7000 PLECO MANAGER 7839 07-10-06 2500 30
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
7521 WARD SALESMAN 7698 81-02-22 1250 500 30
7566 JONES MANAGER 7839 81-04-02 2975 20
7654 MARTIN SALESMAN 7698 81-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 81-05-01 2850 30
7782 CLARK MANAGER 7839 81-06-09 2450 10
7788 SCOTT ANALYST 7566 87-04-19 3000 20
7839 KING PRESIDENT 81-11-17 5000 10
7844 TURNER SALESMAN 7698 81-09-08 1500 0 30
7876 ADAMS CLERK 7788 87-05-23 1100 20
7900 JAMES CLERK 7698 81-12-03 950 30
7902 FORD ANALYST 7566 81-12-03 3000 20
7934 MILLER CLERK 7782 82-01-23 1300 10
9999 DISCUS ANALYST 7839 07-10-06 3000 20

16行が選択されました。

SCOTT> select * from emp2 order by empno;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7000 PLECO MANAGER 7839 07-10-06 2500 30
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
7521 WARD SALESMAN 7698 81-02-22 1250 500 30
7566 JONES MANAGER 7839 81-04-02 2975 20
7654 MARTIN SALESMAN 7698 81-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 81-05-01 2850 30
7782 CLARK MANAGER 7839 81-06-09 2450 10
7788 SCOTT ANALYST 7566 87-04-19 3000 20
7839 KING PRESIDENT 81-11-17 5000 10
7844 TURNER SALESMAN 7698 81-09-08 1500 0 30
7876 ADAMS CLERK 7788 87-05-23 1100 20
7900 JAMES CLERK 7698 81-12-03 950 30
7902 FORD ANALYST 7566 81-12-03 3000 20
7934 MILLER CLERK 7782 82-01-23 1300 10
9999 DISCUS ANALYST 7839 07-10-06 3000 20

16行が選択されました。

SCOTT>

となっており、2表の内容は一致したようだ。(黙視しただけなので、RECHECK()関数でも確認してみることに。。。)


● RECHECK()関数で再度比較する。

前回の比較時に返されたscan_idとcomparison名を指定して再チェックするだけ。
SCOTT> l
1 BEGIN
2 DBMS_OUTPUT.PUT_LINE('======== 再比較結果 ========');
3 IF DBMS_COMPARISON.RECHECK('EMP表の比較', 2, true) THEN
4 DBMS_OUTPUT.PUT_LINE('EMP表とEMP2表の内容は同じです。');
5 ELSE
6 DBMS_OUTPUT.PUT_LINE('EMP表とEMP2表の内容に違いがあります。');
7 END IF;
8* END;
SCOTT> /
======== 再比較結果 ========
EMP表とEMP2表の内容は同じです。

PL/SQLプロシージャが正常に完了しました。

SCOTT>

2つの表の内容は一致しました!。めでたしめでたし!


ちょ〜〜〜〜〜っと待った〜〜〜〜〜っ!

マニュアルでは、RECHECK()関数は、2つの表の内容に違いが無かった場合FALSEを返すと記載されています。COMPARE()関数とは逆と記載されています。

しか〜〜〜し。Oracle Database 11g 11.1.0.6.0では、RECHECK()を実行し、2つの表の内容が同一の場合、COMPARE()関数と同様に、TRUEを返してきます。

そうなんです、マニュアルバグのようです!。
いずれ修正されると思うので現時点のマニュアルバグの証拠写真をカシャっ!

Dbms_comparison_manual_bug

以下はマニュアルからの引用


Return Values

This function returns TRUE when differences are found in the database objects being compared. This function returns FALSE when no differences are found in the database objects being compared.

となっており、違いがあれば、TRUEを、同じであれば、FALSEを返すと書かれています。皆さんご注意を。


また、RECHECK()関数は、同一か否かを判定するだけで、どのデータが違うといった情報までは取得していない。データが一致しているか一致していないかだけしか確認できない。どのデータが一致していないのかを確認するには、再度COMPARE()関数を実行する必要がある。とのこと。間違いやすいので要注意ですな〜〜。


Note:
This function does not identify new differences in the database objects that have appeared since the specified scan was run. To identify new differences, run the COMPARE function in this package.

| | コメント (0) | トラックバック (0)

2007年10月11日 (木)

DBMS_COMPARISONパッケージ で表データの比較 #3

DBMS_COMPARISONパッケージで表データの比較の続きです。

バックナンバー:
DBMS_COMPARISONパッケージ で表データの比較 #1
DBMS_COMPARISONパッケージ で表データの比較 #2



前回は、2つの表を比較し内容が同一であることを確認した。というところまでだった。今回は、emp/emp2の内容が異なっている場合の例を。

● まず、emp表、emp2表で内容の一致しないデータを準備しておく。

SCOTT> 
SCOTT> insert into emp values(9999,'DISCUS','ANALYST',7839,sysdate,3000,null,20);

1行が作成されました。

SCOTT> insert into emp2 values(8888,'NEON','CLERK',7839,sysdate,1300,null,20);

1行が作成されました。

SCOTT> insert into emp values(7000,'PLECO','MANAGER',7839,sysdate,2500,null,30);

1行が作成されました。

SCOTT> insert into emp2 values(7000,'PLEGO','MANAGER',7839,sysdate,2500,null,30);

1行が作成されました。

SCOTT> commit;

コミットが完了しました。

SCOTT>

● COMPARE関数で比較してみる。

SCOTT> l
1 DECLARE
2 isSame BOOLEAN;
3 scanInfo DBMS_COMPARISON.COMPARISON_TYPE;
4 BEGIN
5 isSame := DBMS_COMPARISON.COMPARE(
6 comparison_name => 'EMP表の比較'
7 ,scan_info => scanInfo
8 ,perform_row_dif => true
9 );
10 DBMS_OUTPUT.PUT_LINE('========= 結果 =======');
11 DBMS_OUTPUT.PUT_LINE('scan_id='||TO_CHAR(scanInfo.scan_id));
12 IF isSame THEN
13 DBMS_OUTPUT.PUT_LINE('EMP表とEMP2表の内容は同じです。');
14 ELSE
15 DBMS_OUTPUT.PUT_LINE('EMP表とEMP2表の内容に違いがあります。');
16 END IF;
17* END;
SCOTT> /
========= 結果 =======
scan_id=2
EMP表とEMP2表の内容に違いがあります。

PL/SQLプロシージャが正常に完了しました。

SCOTT>

● user_comparison_scan_summaryビューや、user_comparison_row_difビューなどで比較結果を確認。

尚、2票間に同一キーを持つデータは存在するがキー以外の列値が異なっている場合、どの列値が異なっているか? というところまで確認することはできない。
SCOTT> l
1 select
2 c.comparison_name,
3 s.scan_id,
4 s.current_dif_count
5 from
6 user_comparison c join user_comparison_scan_summary s
7 on c.comparison_name = s.comparison_name
8 where
9* s.scan_id = 2
SCOTT> /

COMPARISON_NAM SCAN_ID CURRENT_DIF_COUNT
-------------- ---------- -----------------
EMP表の比較 2 3

SCOTT>
SCOTT> l
1 select
2 s.root_scan_id as scan_id,
3 s.comparison_name,
4 d.index_value,
5 s.status,
6 case
7 when local_rowid is not null
8 and remote_rowid is not null then
9 'ローカル表、リモート表に同一キーを持つ行が存在しますが、キー以外で列値に違いがあります。'
10 when local_rowid is null
11 and remote_rowid is not null then
12 'ローカル表に存在しない行がリモート表に存在します。'
13 when local_rowid is not null
14 and remote_rowid is null then
15 'ローカル表に存在する行がリモート表に存在しません。'
16 end as description
17 from
18 user_comparison_scan_summary s join user_comparison_row_dif d
19 on s.scan_id = d.scan_id
20 where
21 s.root_scan_id = 2
22 and s.parent_scan_id is not null
23 order by
24* d.index_value
SCOTT> /

SCAN_ID COMPARISON_NAME INDEX_VAL STATUS DESCRIPTION
---------- -------------------- --------- ---------------- ---------------------------------------------------------------------------
2 EMP表の比較 7000 ROW DIF ローカル表、リモート表に同一キーを持つ行が存在しますが、キー以外で列値に違いがあります。
2 EMP表の比較 8888 ROW DIF ローカル表に存在しない行がリモート表に存在します。
2 EMP表の比較 9999 ROW DIF ローカル表に存在する行がリモート表に存在しません。

SCOTT>

今日はここまで。
次回は、2つの表の内容を一致させてから再度比較してみる。

| | コメント (0) | トラックバック (0)

2007年10月10日 (水)

DBMS_COMPARISONパッケージ で表データの比較 #2

DBMS_COMPARISONパッケージで表データの比較の続きです。

バックナンバー:
DBMS_COMPARISONパッケージ で表データの比較 #1



DBMS_COMPARISONパッケージを利用し2つの表を比較!。(今回は、同一データベース、同一スキーマ内でテーブルの内容を比較してみることにする。)


● 表データを比較する手順

COMPARISONを作成する。

(比較仕様を作成する。 とでも書いたほうがわかりやすいか?。。。)

・作成したCOMPARISONを元に比較する

(比較仕様を元に比較を実行する。 とでも書いたほうがわかりやすいか?。。。)




では、比較実験開始!

emp表を複製してemp2表を作成する。(まずは、表、索引まで完全に複製して比較。)

SCOTT> create table emp2 as select * from emp;

表が作成されました。

SCOTT>
SCOTT> alter table emp2 add constraint emp2_pk primary key (empno);

表が変更されました。

SCOTT>
SCOTT> select * from emp order by empno;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 NULL 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
7521 WARD SALESMAN 7698 81-02-22 1250 500 30
7566 JONES MANAGER 7839 81-04-02 2975 NULL 20
7654 MARTIN SALESMAN 7698 81-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 81-05-01 2850 NULL 30
7782 CLARK MANAGER 7839 81-06-09 2450 NULL 10
7788 SCOTT ANALYST 7566 87-04-19 3000 NULL 20
7839 KING PRESIDENT NULL 81-11-17 5000 NULL 10
7844 TURNER SALESMAN 7698 81-09-08 1500 0 30
7876 ADAMS CLERK 7788 87-05-23 1100 NULL 20
7900 JAMES CLERK 7698 81-12-03 950 NULL 30
7902 FORD ANALYST 7566 81-12-03 3000 NULL 20
7934 MILLER CLERK 7782 82-01-23 1300 NULL 10

14行が選択されました。

SCOTT> select * from emp2 order by empno;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 NULL 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
7521 WARD SALESMAN 7698 81-02-22 1250 500 30
7566 JONES MANAGER 7839 81-04-02 2975 NULL 20
7654 MARTIN SALESMAN 7698 81-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 81-05-01 2850 NULL 30
7782 CLARK MANAGER 7839 81-06-09 2450 NULL 10
7788 SCOTT ANALYST 7566 87-04-19 3000 NULL 20
7839 KING PRESIDENT NULL 81-11-17 5000 NULL 10
7844 TURNER SALESMAN 7698 81-09-08 1500 0 30
7876 ADAMS CLERK 7788 87-05-23 1100 NULL 20
7900 JAMES CLERK 7698 81-12-03 950 NULL 30
7902 FORD ANALYST 7566 81-12-03 3000 NULL 20
7934 MILLER CLERK 7782 82-01-23 1300 NULL 10

14行が選択されました。

SCOTT>


create_comparison関数でcomparisonを作成する。
2つの表(empとemp2)は、どちらも同一データベースのSCOTTスキーマに存在するため、dblink_name引数にはnullを指定する。

SCOTT> l
1 begin
2 dbms_comparison.create_comparison(
3 comparison_name => 'EMP表の比較'
4 ,schema_name => 'SCOTT'
5 ,object_name => 'EMP'
6 ,dblink_name => null
7 ,remote_schema_name => 'SCOTT'
8 ,remote_object_name => 'EMP2'
9 );
10* end;
SCOTT> /

PL/SQLプロシージャが正常に完了しました。

SCOTT>

作成されたcomparisonを確認するには、user_comparisonビュー/user_comparison_columnsビュー問い合わせる

SCOTT> l
1 select
2 comparison_name
3 ,scan_mode
4 ,schema_name||'.'||object_name||'(type='||object_type||')' as local
5 ,remote_schema_name||'.'||remote_object_name||'(type='||remote_object_type||')' as remote
6 ,dblink_name
7 ,last_update_time
8 from
9 user_comparison
10 where
11* comparison_name = 'EMP表の比較'
SCOTT> /

COMPARISON_NAME SCAN_MODE LOCAL REMOTE DBLINK_NAME LAST_UPDATE_TIME
--------------- --------- -------------------------- -------------------------- ----------- ------------------------------
EMP表の比較 FULL SCOTT.EMP(type=TABLE) SCOTT.EMP2(type=TABLE) NULL 07-10-06 15:58:36.665370

SCOTT>
SCOTT> select * from user_comparison_columns order by column_position;

COMPARISON_NAME COLUMN_POSITION COLUMN_NAME I
------------------------------ --------------- ------------------------------ -
EMP表の比較 1 EMPNO Y
EMP表の比較 2 ENAME N
EMP表の比較 3 JOB N
EMP表の比較 4 MGR N
EMP表の比較 5 HIREDATE N
EMP表の比較 6 SAL N
EMP表の比較 7 COMM N
EMP表の比較 8 DEPTNO N

8行が選択されました。

SCOTT>

compare関数を利用して比較する。

事前に作成されたcomparisonを元に、compare関数を利用して比較を行う。この時、比較処理事に採版されるscan_idを記録しておくとよいだろう。
scan_idは、内容に相違がある場合、その詳細をディクショナリビューから問い合わせたり、再比較する際に利用する。

SCOTT> set serveroutput on format wrapped
SCOTT> l
1 DECLARE
2 isSame BOOLEAN;
3 scanInfo DBMS_COMPARISON.COMPARISON_TYPE;
4 BEGIN
5 isSame := DBMS_COMPARISON.COMPARE(
6 comparison_name => 'EMP表の比較'
7 ,scan_info => scanInfo
8 ,perform_row_dif => true
9 );
10 DBMS_OUTPUT.PUT_LINE('========= 結果 =======');
11 DBMS_OUTPUT.PUT_LINE('scan_id='||TO_CHAR(scanInfo.scan_id));
12 IF isSame THEN
13 DBMS_OUTPUT.PUT_LINE('EMP表とEMP2表の内容は同じです。');
14 ELSE
15 DBMS_OUTPUT.PUT_LINE('EMP表とEMP2表の内容に違いがあります。');
16 END IF;
17* END;
SCOTT> /
========= 結果 =======
scan_id=1
EMP表とEMP2表の内容は同じです。

PL/SQLプロシージャが正常に完了しました。

SCOTT>

ということで、次回は表の内容が異なっている場合はどうなるかという例を。

| | コメント (0) | トラックバック (0)

2007年10月 8日 (月)

DBMS_COMPARISONパッケージ で表データの比較 #1

Oracle Database 11gで新たに追加されたDBMS_COMPARISONパッケージ
このパッケージは2つのTable/Single-table view/Materialized view(シノニムも可)を比較したり、データを一致させたりするための機能を提供するパッケージだ。
レプリケーション関連のマニュアルへのリンクもあるのでレプリケーション環境を意識した機能ではあるようだが、単に2つの表の内容を比較したり一致させることにも利用できるのでレプリケーション環境以外でも利用できる。

ただし、マニュアルに記載されているように利用できるデータ型や索引などの制限があるので、利用に際して事前調査は必要でしょうね。


参考:
Oracle Database PL/SQL Packages and Types Reference 11g Release 1 (11.1.) 31 DBMS_COMPARISON

ということで、早速試してみる。


環境は、先日作成したIBM Thinkpad R52 のCentOS 5上に構築したOracle Database 11g R1 11.1.0.6.0 for Linux (x86)を利用した。)

例によって、MacOSXのTerminalからssh経由で利用した。
(CentOS5/Oracle11gともエンコーディングにUTF-8を利用しているため、TerminalのエンコーティングもUTF-8に設定した。


Dbms_comparison001

まずは、Oracle Database 11gから新規追加されたDBMS_COMPARISONパッケージ関連のディクショナリービューの確認。(尚、DBA_*ビューも追加されている。)

[oracle@glasscatfish ˜]$ sqlplus /nolog

SQL*Plus: Release 11.1.0.6.0 - Production on 月 10月 8 08:50:38 2007

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

> conn scott/tiger
接続されました。
SCOTT>
SCOTT>
SCOTT> desc user_comparison_scan
名前 NULL? 型
----------------------------------------- -------- ----------------------------
COMPARISON_NAME NOT NULL VARCHAR2(30)
SCAN_ID NOT NULL NUMBER
PARENT_SCAN_ID NUMBER
STATUS VARCHAR2(16)
COUNT_ROWS NUMBER
SCAN_NULLS VARCHAR2(1)
LAST_UPDATE_TIME TIMESTAMP(6)


SCOTT> desc user_comparison_scan_summary
名前 NULL? 型
----------------------------------------- -------- ----------------------------
COMPARISON_NAME NOT NULL VARCHAR2(30)
SCAN_ID NOT NULL NUMBER
PARENT_SCAN_ID NUMBER
ROOT_SCAN_ID NUMBER
STATUS VARCHAR2(16)
CURRENT_DIF_COUNT NUMBER
INITIAL_DIF_COUNT NUMBER
COUNT_ROWS NUMBER
SCAN_NULLS VARCHAR2(1)
LAST_UPDATE_TIME TIMESTAMP(6)

SCOTT> desc user_comparison_scan_values
名前 NULL? 型
----------------------------------------- -------- ----------------------------
COMPARISON_NAME NOT NULL VARCHAR2(30)
SCAN_ID NOT NULL NUMBER
COLUMN_POSITION NOT NULL NUMBER
MIN_VALUE VARCHAR2(4000)
MAX_VALUE VARCHAR2(4000)
LAST_UPDATE_TIME TIMESTAMP(6)

SCOTT> desc user_comparison_row_dif
名前 NULL? 型
----------------------------------------- -------- ----------------------------
COMPARISON_NAME NOT NULL VARCHAR2(30)
SCAN_ID NOT NULL NUMBER
LOCAL_ROWID ROWID
REMOTE_ROWID ROWID
INDEX_VALUE VARCHAR2(4000)
STATUS VARCHAR2(3)
LAST_UPDATE_TIME TIMESTAMP(6)

SCOTT>
SCOTT> desc user_comparison
名前 NULL? 型
----------------------------------------- -------- ----------------------------
COMPARISON_NAME NOT NULL VARCHAR2(30)
COMPARISON_MODE VARCHAR2(5)
SCHEMA_NAME VARCHAR2(30)
OBJECT_NAME VARCHAR2(30)
OBJECT_TYPE VARCHAR2(17)
REMOTE_SCHEMA_NAME VARCHAR2(30)
REMOTE_OBJECT_NAME VARCHAR2(30)
REMOTE_OBJECT_TYPE VARCHAR2(17)
DBLINK_NAME VARCHAR2(128)
SCAN_MODE VARCHAR2(9)
SCAN_PERCENT NUMBER
CYCLIC_INDEX_VALUE VARCHAR2(4000)
NULL_VALUE VARCHAR2(4000)
LOCAL_CONVERGE_TAG RAW(2000)
REMOTE_CONVERGE_TAG RAW(2000)
MAX_NUM_BUCKETS NUMBER
MIN_ROWS_IN_BUCKET NUMBER
LAST_UPDATE_TIME TIMESTAMP(6)

SCOTT>
SCOTT> desc user_comparison_columns
名前 NULL? 型
----------------------------------------- -------- ----------------------------
COMPARISON_NAME NOT NULL VARCHAR2(30)
COLUMN_POSITION NOT NULL NUMBER
COLUMN_NAME NOT NULL VARCHAR2(30)
INDEX_COLUMN VARCHAR2(1)


DBMS_COMPARISIONパッケージを利用するには、EXECUTEオブジェクト権限、及び、EXECUTE_CATALOG_ROLEロール(データディクショナリ内のオブジェクトに対するEXECUTE/SELECT権限)を実行するユーザへ付与する必要がある

SCOTT> conn / as sysdba
接続されました。
SYS> grant execute on dbms_comparison to scott;

権限付与が成功しました。

SYS> grant execute_catalog_role to scott;

権限付与が成功しました。

SYS> conn scott/tiger
接続されました。
SCOTT> desc dbms_comparison
FUNCTION COMPARE RETURNS BOOLEAN
引数名 タイプ In/Out Default?
------------------------------ ----------------------- ------ --------
COMPARISON_NAME VARCHAR2 IN
SCAN_INFO RECORD OUT
SCAN_ID NUMBER OUT
LOC_ROWS_MERGED NUMBER OUT
RMT_ROWS_MERGED NUMBER OUT
LOC_ROWS_DELETED NUMBER OUT
RMT_ROWS_DELETED NUMBER OUT
MIN_VALUE VARCHAR2 IN DEFAULT
MAX_VALUE VARCHAR2 IN DEFAULT
PERFORM_ROW_DIF BOOLEAN IN DEFAULT

・・・・・・・中略・・・・・・・

FUNCTION RECHECK RETURNS BOOLEAN
引数名 タイプ In/Out Default?
------------------------------ ----------------------- ------ --------
COMPARISON_NAME VARCHAR2 IN
SCAN_ID NUMBER IN
PERFORM_ROW_DIF BOOLEAN IN DEFAULT

SCOTT>

これでDBMS_COMPARISONパッケージを利用する準備は整った。というところで本日は終わり。

次回へ続く。

| | コメント (0) | トラックバック (0)

2007年9月15日 (土)

MERGE文 #1 - 重複行の削除

ははは、久々のOracleネタです。

最近、OTN-Jのフォーラムを閲覧したり返信したりする回数を控えている。Feedの概要だけ眺めている事が多くなってきていることも影響しているが、興味をそそる内容のものが少ないことや、本家US OTNのフォーラムOracle Aceの方々のブログのほうが面白いのもその理由の一つ)

で、しばらく振りで、面白そうなネタだったのでレスを付けた。
ちょいと前のネタになるが、

定義の同じ2つの表のデータを纏めて表示したい。ただし、重複データを除く。また、重複していた件数も取得したい。。。。

というスレッド。

ただ質問内容を読むと、最近よくある実行環境(Oracleのバージョンなど)を記述せず、●●したいというタイプの質問。
(単に書き忘れかもしれないが、問題が発生している環境やOracleのバージョンを書かずに意図した答えを待ってるなんて時間がもったいないじゃん。そこんとこをちゃんと公開していれば、もっと早く意図した解答得られたと思うが。。)
そして、最後まで、実行環境に関する情報は未提示のままスレッドは終わるのであった〜〜(笑)

ということで質問内容など詳細は下記URLで
http://otn.oracle.co.jp/forum/message.jspa?messageID=35016369&tstart=15

私がレスした内容は以下のようなもの。


(質問内容のカラム名が ”日本語”だったので例題も引用識別子で囲んだ日本語の表/列名にしてあります。私は実際の開発では使いませんけどね、日本語オブジェクト名なんて。。


主キー制約や一意制約、その他の制約などが提示されていないので勝手に作ってありますが、merge文を使えば出来ますよ。
尚、Oracle10gを利用していものと仮定していますので、Oracle9i以前である場合、merge文でdeleteを実施することはできません。

また、暗黙カーソルを利用していますので、sql%rowcount属性で重複行数(マージした行数)を取得しています。
(明示カーソルにした場合は、カーソル名%rowcount)

他の方法もあると思いますので、あとは処理速度等比較し、よい方を採用すれば良いと思います。

詳細は、SQLや、PL/SQLリファレンスマニュアルの merge文及び、カーソル属性あたりを確認してみてください。

SCOTT> create table "テーブルA"
2 ("商品コード" char(5) not null,
3 "送品年月日" date not null,
4 "個数" number(4) not null
5 );

表が作成されました。

SCOTT> create table "テーブルB" as select * from "テーブルA";

表が作成されました。

SCOTT>

データの登録・・・・中略・・・・

SCOTT> alter session set nls_date_format = 'yyyy/mm/dd';

セッションが変更されました。

SCOTT> select * from "テーブルA";

商品コード 送品年月日 個数
-------- ---------- ----------
00001 2007/07/18 5
00002 2007/07/18 6
00003 2007/07/19 7
00004 2007/07/18 5
00005 2007/07/20 4
00001 2007/07/19 8
00002 2007/07/19 2
00003 2007/07/20 0

8行が選択されました。

SCOTT> select * from "テーブルB";

商品コード 送品年月日 個数
-------- ---------- ----------
00001 2007/08/18 5
00002 2007/08/18 6
00003 2007/07/19 9
00004 2007/08/18 5
00005 2007/08/20 4
00001 2007/07/19 10
00002 2007/08/19 2
00003 2007/08/20 0

8行が選択されました。


SCOTT> set serveroutput on
SCOTT> l
1 begin
2 merge
2 into "テーブルA" dest
3 using "テーブルB" src
4 on (
5 dest."商品コード"=src."商品コード"
6 and dest."送品年月日"=src."送品年月日"
7 )
8 when matched then update set dest."個数"=-1
9 delete where dest."個数"=-1;
10 dbms_output.put_line(sql%rowcount);
11* end;
SCOTT> /

2

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> select * from "テーブルA";

商品コード 送品年月日 個数
-------- ---------- ----------
00001 2007/07/18 5
00002 2007/07/18 6
00004 2007/07/18 5
00005 2007/07/20 4
00002 2007/07/19 2
00003 2007/07/20 0

6行が選択されました。

SCOTT>

マニュアルにもしっかり記述されているが、merge文のdelete句を利用する場合のポイントは、マージ条件に一致し、update句で更新対象となったデータがdelete句の処理対象となるという点だ。delete句がupdate句とは個別に実行されるわけではない。
前述の例では、update句でマージ条件に一致したデータ(この場合は重複しているデータ)の”個数”を-1に変更し、delete句で "個数” = -1となったデータ(重複したデータ)を削除している。
このことを理解していないと意図した結果を得られないので要注意。(一度理解してしまえば間違ることもなくなると思うが。。。)

merge文を利用したついでに、merge文のTipsも1つ紹介しておきましょう。(Oracle9iでmerge文が追加された際、OTN-Jでも同じ話題があったので投稿したネタですが使えるTipsなのでね。。
今そのスレッドの日付を見たら、なんと、2002年。。。時の経つのは早いもので。。。)

では、次回へつづく。

| | コメント (0) | トラックバック (0)

2007年8月29日 (水)

Oracle de Fizzbuzz #1 - いまごろ・・・ですが・・

え〜〜っと、前回のエントリで予告していたとおり、あの話題。
今頃。。。という感じのネタですが、少々視点を変えて、fizzbuzzをOracle上で解かせるための簡単な環境作りを中心に。


では、早速、環境作りから。

Oracleではプロファイルによるリソース制限を設定することができる。この機能はOracle7のころから提供されている。(使っている方はどれだけいるか定かでないが。。。)
この機能を利用すれば、セッション単位で、CPU利用時間や、接続時間、アイドル時間などを制限することが可能だ。

ここまで書けば、なにを言いたいか想像できると思う。 

そう、プロファイルを利用すれば、fizzbuzz問題の解答時間制限を設定できるんです!

以下のように、プロファイルで connect_time(接続時間)制限を2分と設定しておけば、接続から2分強経過した時点でオラクルとのセッションが強制的にdisconnectされる。

fizzbuzzユーザに接続して、2分程度でfizzbuzzを解いてみて!? という環境が簡単に作れるわけです。

この制限は、SQL*Plusから接続しても、
iSQL*Plusから接続しても、Oracle SQL Developer、JDeveloperから接続しても同じなので、

例えば、

Linux/MacOSX/Windowのクライアントを用意しておき、
好きなクライアントからSQL*Plusを利用して、SQL又は、PL/SQLでfizzbuzzを解いて! とか

Linux/MacOSXのクライアントからSQL*plusを利用して、SQL又は、PL/SQLでfizzbuzz解いて! 
ただし、editコマンドで起動するのはvi  とか

前提条件を絞って、SQLだけで、fizzbuzz解いて! とか、 

データベースサーバーとして、Oracle9iを用意しておいて、SQLだけで、fizzbuzz解いて! とか

nullカラムで且つ、10行登録されている表を使って、fizzbuzz解いて!

ということを制限時間内に行わせてみる環境が作れるわけです。

(こんなこと考えていると、PL/SQL で Python Challengeをやっていたことを思いだす。。。。。)

注)
コネクションプーリングしているユーザにconnect_timeとか、idle_timeなんて制限付けたりしないでくださいね!。
そんなことする方は居ないと思うけど。。念のため。

以下、fizzbuzzというプロファイルを作成(接続時間制限2分)、fizzbuzzユーザを作成し、fizzbuzzプロファイルを設定。
最後に、初期化パラメータ、 resource_limitをtrueにしてあげれば、準備完了。 という例です。


尚、作成するユーザには、必要最小限のシステム権限やオブジェクト権限だけを付与おくといいですね。例えば、表やシーケンスを作成できないようにしておくとか。

SYS> show parameter resource_limit 

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
resource_limit boolean FALSE
SYS>
SYS> create profile fizzbuzz limit connect_time 2;

プロファイルが作成されました。

SYS> select * from dba_profiles where profile='FIZZBUZZ';

PROFILE RESOURCE_NAME RESOURCE LIMIT
---------- -------------------------------- -------- ----------
FIZZBUZZ COMPOSITE_LIMIT KERNEL DEFAULT
FIZZBUZZ SESSIONS_PER_USER KERNEL DEFAULT
FIZZBUZZ CPU_PER_SESSION KERNEL DEFAULT
FIZZBUZZ CPU_PER_CALL KERNEL DEFAULT
FIZZBUZZ LOGICAL_READS_PER_SESSION KERNEL DEFAULT
FIZZBUZZ LOGICAL_READS_PER_CALL KERNEL DEFAULT
FIZZBUZZ IDLE_TIME KERNEL DEFAULT
FIZZBUZZ CONNECT_TIME KERNEL 2
FIZZBUZZ PRIVATE_SGA KERNEL DEFAULT
FIZZBUZZ FAILED_LOGIN_ATTEMPTS PASSWORD DEFAULT
FIZZBUZZ PASSWORD_LIFE_TIME PASSWORD DEFAULT
FIZZBUZZ PASSWORD_REUSE_TIME PASSWORD DEFAULT
FIZZBUZZ PASSWORD_REUSE_MAX PASSWORD DEFAULT
FIZZBUZZ PASSWORD_VERIFY_FUNCTION PASSWORD DEFAULT
FIZZBUZZ PASSWORD_LOCK_TIME PASSWORD DEFAULT
FIZZBUZZ PASSWORD_GRACE_TIME PASSWORD DEFAULT

16行が選択されました。

SYS>
SYS> create user fizzbuzz identified by jazz
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users
5 profile fizzbuzz;

ユーザーが作成されました。

SYS> grant create session,create procedure to fizzbuzz;

権限付与が成功しました。

SYS>
SYS> alter system set resource_limit = true scope=both;

システムが変更されました。

SYS>


fizzbuzzユーザにconnectして、モタモタしていると・・・・・・。Oracleさんからdisconnectされちゃいます!

FIZZBUZZ> select 'Zzzzzz......' from dual:
select 'Zzzzzz......' from dual
*
行1でエラーが発生しました。:
ORA-02399: 最大接続時間を超えました。ログオフ中です。


FIZZBUZZ>

もし、他の前提条件なしで、Oracle9i以降の環境を利用してfizzbuzz解いて! といきなり言われたとしたら、私なら、linuxのクライアントから以下のような無名PL/SQLブロックだけで解くだろうな〜。
(無難な方法だし、1分もかからないでできるだろう。。ただ、SQLだけで、Oracle9iという前提だと、1分強かもしれないな〜。まず、どうんな方法で100行準備するかを決めなきゃならないからね)

FIZZBUZZ> set serveroutput on 
FIZZBUZZ> l
1 begin
2 for i in 1..100 loop
3 dbms_output.put_line(
4 case when mod(i,15)=0 then 'fizzbuzz'
5 when mod(i,3)=0 then 'fizz'
6 when mod(i,5)=0 then 'buzz'
7 else to_char(i)
8 end
9 );
10 end loop;
11* end;
FIZZBUZZ> /
1
2
fizz
4
・・・・中略・・・・
98
fizz
buzz

PL/SQLプロシージャが正常に完了しました。

FIZZBUZZ>
経過: 00:00:00.05

次回は、幾つかの前提条件を設けて、Oracle de fizzbuzz する予定(そんなにfizzbuzzネタで引っ張るつもりはないですよ。w)

| | コメント (0) | トラックバック (0)

2007年8月19日 (日)

PL/SQL de Conditional Compile #5

さて、PL/SQL条件付きコンパイルもネタが無くなってきたので、最後に、DBMS_DB_VERSIONパッケージを利用して、各リリース毎にコードを切り替えてみよう!
ということで、Oracle database 10g以前のリリースとOracle databse 11g以降のリリースでコードを切り替える例。

● 条件付きコンパイルが無い場合、Oracle11gより前のリリースで以下ようなコードを書いてしまったら....

当然コンパイルエラー!
FUNCTION CONDITIONAL_COMP_SAMPLE3 RETURN NUMBER
IS
vSeq# NUMBER;
BEGIN
vSeq# := mySeq.NEXTVAL;
RETURN vSeq#;
END CONDITIONAL_COMP_SAMPLE3;
/

警告: ファンクションが変更されましたが、コンパイル・エラーがあります。

SCOTT> show errors
FUNCTION CONDITIONAL_COMP_SAMPLE3のエラーです。

LINE/COL ERROR
-------- -----------------------------------------------------------------
9/5 PL/SQL: Statement ignored
9/20 PLS-00357:
表またはビュー、シーケンス参照MYSEQ.NEXTVALは、このコンテキストで
は使用できません。

SCOTT>

● しかし、DBMS_DB_VERSIONパッケージでリリース毎にコードを選択し切り替えたら・・・・便利ですよね。

CREATE OR REPLACE FUNCTION CONDITIONAL_COMP_SAMPLE3 RETURN NUMBER 
IS
vSeq# NUMBER;
BEGIN

$IF DBMS_DB_VERSION.Ver_LE_10 $THEN
SELECT mySeq.NEXTVAL INTO vSeq# FROM DUAL;
$ELSE
vSeq# := mySeq.NEXTVAL;
$END

RETURN vSeq#;

END CONDITIONAL_COMP_SAMPLE3;

DBMS_DB_VERSIONパッケージをリリース番号でどのようにソースコードが変化するか確認。
● Oracle database 10g以前のバージョンでコンパイルした場合

SCOTT> 
SCOTT> set serveroutput on
SCOTT> exec dbms_preprocessor.print_post_processed_source('FUNCTION','SCOTT','CONDITIONAL_COMP_SAMPLE3');
FUNCTION CONDITIONAL_COMP_SAMPLE3 RETURN NUMBER
IS
vSeq# NUMBER;
BEGIN
SELECT mySeq.NEXTVAL INTO vSeq# FROM DUAL;
RETURN vSeq#;
END CONDITIONAL_COMP_SAMPLE3;

PL/SQLプロシージャが正常に完了しました。


● Oracle database 11g以降でコンパイルした場合

SCOTT> exec dbms_preprocessor.print_post_processed_source('FUNCTION','SCOTT','CONDITIONAL_COMP_SAMPLE3');
FUNCTION CONDITIONAL_COMP_SAMPLE3 RETURN NUMBER
IS
vSeq# NUMBER;
BEGIN
vSeq# := mySeq.NEXTVAL;
RETURN vSeq#;
END CONDITIONAL_COMP_SAMPLE3;

PL/SQLプロシージャが正常に完了しました。

SCOTT>


● 各リリース毎のDBMS_DB_VERSIONパッケージの違い
参考 http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_dbver.htm

● 10.2:
package DBMS_DB_Version is 
Version constant pls_integer := 10;
Release constant pls_integer := 2;
Ver_LE_9_1 constant boolean := false;
Ver_LE_9_2 constant boolean := false;
Ver_LE_9 constant boolean := false;
Ver_LE_10_1 constant boolean := false;
Ver_LE_10_2 constant boolean := true;
Ver_LE_10 constant boolean := true;
end DBMS_DB_Version;
● 10.1:
package DBMS_DB_Version is 
Version constant pls_integer := 10;
Release constant pls_integer := 1;
Ver_LE_9_1 constant boolean := false;
Ver_LE_9_2 constant boolean := false;
Ver_LE_9 constant boolean := false;
Ver_LE_10_1 constant boolean := true;
Ver_LE_10 constant boolean := true;
end DBMS_DB_Version;
● 9.2:
package DBMS_DB_Version is 
version constant pls_integer := 9;
release constant pls_integer := 2;
Ver_LE_9_1 constant boolean := false;
Ver_LE_9_2 constant boolean := true;
Ver_LE_9 constant boolean := true;
end DBMS_DB_Version;




PL/SQL de Conditional Compile #1
PL/SQL de Conditional Compile #2
PL/SQL de Conditional Compile #3
PL/SQL de Conditional Compile #4

| | コメント (0) | トラックバック (0)

2007年8月18日 (土)

PL/SQL de Conditional Compile #4

PL/SQLの条件付きコンパイルのつづきです。

今回は、エラーディレクティブ($ERROR)を利用して、ちょっとした物忘れ対策を!

どのような物忘れ対策かというと、コード中に書かなければならないロジックがあるが、今は書かずに後で追加しようとコメントでメモを残しておいた。
だが〜〜、うっかりミスで、コーディングしないまま、結合テストに〜〜〜〜〜!。あ〜〜〜、大変だ〜!!!! 

なんてことを、防止できるかも・・・・・・・・。しれないという使い方!。

たとえば、以下のように、後でコードを追加しようとストアドファンクションをロジックなして仮に作成しておいたとする。
後でロジックを追加するというこを、すっかり忘れてしまっていると、テスト段階になって、あれ? 結果が帰ってこない!!! ソースを見ると。
あ〜〜〜〜、忘れてた〜〜〜 (^^;;;;;;;

なんてことに・・・・ コンパイルが通ってしまうので、実行してみないと気付かない。。なんてことになっちゃいます。

SCOTT> l
1 create or replace
2 FUNCTION CONDITIONAL_COMP_SAMPLE2
3 RETURN TIMESTAMP
4 IS
5 vNow TIMESTAMP;
6 BEGIN
7 -- TODO - 結合テストまでに、ここにロジック書かなきゃ!
8 RETURN vNow;
9* END CONDITIONAL_COMP_SAMPLE2;
10 /

ファンクションが作成されました。

SCOTT> set null 'NULL!'
SCOTT> select conditional_comp_sample2 from dual;

CONDITIONAL_COMP_SAMPLE2
---------------------------------------------------------------------------
NULL!

SCOTT>

しかし、$ERRORディレクティブを利用して、コンパイルエラーになるようにしておけば。。。。
さらに、エラーメッセージには、やることを思い出させてくれるようなコメントを設定しておけば、これまた、物忘れの激しい方でもなんとかなるかもしれません。

SCOTT> l
1 CREATE OR REPLACE
2 FUNCTION CONDITIONAL_COMP_SAMPLE2
3 RETURN TIMESTAMP
4 IS
5 vNow TIMESTAMP;
6 BEGIN
7
8 -- TODO - 結合テストまでに、ここにロジック書かなきゃ!
9 $ERROR
10 '結合テストまでに、ここにロジック書かなきゃ!'
11 $END
12
13
14 RETURN vNow;
15
16* END CONDITIONAL_COMP_SAMPLE2;
SCOTT> /

警告: ファンクションが変更されましたが、コンパイル・エラーがあります。

SCOTT> show errors
FUNCTION CONDITIONAL_COMP_SAMPLE2のエラーです。

LINE/COL ERROR
-------- -----------------------------------------------------------------
7/3 PLS-00179: $ERROR: 結合テストまでに、ここにロジック書かなきゃ!
SCOTT>

応用編としては、上記のように、単純に、コンパイルエラーにはせず、前々回のエントリで利用したPLSQL_DEBUG初期化パラメータ等と組み合わせ、デバッグ時はコンパイル正常に行わせるという使い方も考えられます。


参考
http://www.oracle.com/technology/oramag/oracle/06-jul/o46plsql.html
http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/fundamentals.htm#BEIJFDHG

| | コメント (0) | トラックバック (0)

2007年8月17日 (金)

PL/SQL de Conditional Compile #3

PL/SQL条件付きコンパイルの続きです。

前回までのおさらい。

初期化パラメータをセッション単位で変更してコンパイルしていたが、Oracle10g R1 10.1.0.4.0以降及び、Oracle9i R2 9.2.0.6.0以降へバックポートされた条件付きコンパイル機能では一部利用できない初期化パラメータがあり、全リリースで共通のソースコードを利用するには、各リリースで利用できる初期化パラメータ PLSQL_DEBUG を利用するようにした。というところまでだった。

今回はいままでとは異なる方法で条件付きコンパイルを行ってみることにする。

その方法とは、初期化パラメータを利用せずパッケージの仕様部で宣言した定数を利用する方法だ。
この方法であれば、リリース毎にいくつかの制限のある初期化パラメータを利用せずに条件コンパイルが可能だ。

但し、その都度、パッケージ定数を変更するという手間はかかる。
実際に利用する際には、定数を変更する為のスクリプトを事前に用意しておき、そのスクリプトを実行するだけで行えるようにすると良いだろう。
また、パッケージをどのスキーマに定義するか、という点なども、よ〜〜〜く検討した上で利用した方が良いだろう。
ルール無しで利用した場合、後々混乱の原因になる可能性があるということは容易に想像できると思う。

● 条件コンパイルのフラグだけを定義したパッケージを作成する

以下の例では、C_DEBUG_ON定数だけを定義し、値はfalseとした。
CREATE OR REPLACE PACKAGE MyPROPERTIES AS

C_DEBUG_ON CONSTANT BOOLEAN := false;

END MyPROPERTIES;

● 以下、条件コンパイルのサンプルコード

以前作成したコードとの違いは、初期化パラメータではなく、前述したパッケージのC_DEBUG_ON定数を参照している点である。
CREATE OR REPLACE FUNCTION CONDITIONAL_COMPILATION_SAMPLE
RETURN TIMESTAMP
IS
vNow TIMESTAMP;
BEGIN
$IF myproperties.c_debug_on $THEN
DBMS_OUTPUT.ENABLE(20000);
DBMS_OUTPUT.PUT_LINE('======= start =====');
$END

SELECT SYSTIMESTAMP INTO vNow FROM dual;

$IF myproperties.c_debug_on $THEN
DBMS_OUTPUT.PUT_LINE('======= end =======');
$END

RETURN vNow;

END CONDITIONAL_COMPILATION_SAMPLE;

● MYPROPERTIES.C_DEBUG_ON=falseで上記サンプルコードをコンパイルし実行した例

Conditional_compilation137 Conditional_compilation138 Conditional_compilation139Conditional_compilation1310


● MYPROPERTIES.C_DEBG_ON=trueで、上記サンプルコードをコンパイルし実行した例

Conditional_compilation131 Conditional_compilation132Conditional_compilation133
Conditional_compilation134 Conditional_compilation135 Conditional_compilation136

| | コメント (0) | トラックバック (0)

2007年8月16日 (木)

PL/SQL de Conditional Compile #2


とにかく、熱過ぎる! 沖縄の方が気温が低いってどうよ!? 避暑のために、石垣島なんていいかも。 午前10時の気温。東京:摂氏34.6度、沖縄:摂氏29.9度 沖縄のほうが気温が低い!(爆笑) http://www.weather-eye.com/amedas_graph/index.html

yanokami (矢野顕子 × レイ・ハラカミ) - yanokami - EP - You Showed Me yanokami (矢野顕子 × レイ・ハラカミ) - yanokami - EP - You Showed Me



さて、PL/SQL条件付きコンパイルの続きです。

前回は、本機能が正式にサポートされているOracle10g R2 10.2.0.2.0で行ったが、今回は、バックポートされた Oracle10g R1 10.1.0.4.0で行う。
PL/SQL条件付きコンパイル機能は、前回も書いたように、Oracle10g R1 10.1.0.4.0以降、Oracle9i R2 9.2.0.6.0以降へバックポートされている。

但し、Oracle10g R1 10.1.0.4.0以降及び、Oracle9i R2 9.2.0.6.0以降へバックポートされたPL/SQL条件付きコンパイルでは幾つかの制限があり、Oracle10g R2 からサポートされている同機能と比べて利用できない機能などが存在するので注意が必要だ。
ちなみに、前回のエントリで紹介したPLSQL_CCFLAG初期化パラメータは、パックポートされたOracle10g R1 10.1.0.4.0及び、Oracle9i R2 9.2.0.6.0以降では利用できないと記載されている。

参考:plsql_conditional_compilation.pdfのFunctionality restrictions in 10.1 and 9.2 (P.61)


では、前述の制限を踏まえつつ、以下、Oracle10g 10.1.0.4.0でのテストを!

環境:Oracle10g R1 10.1.0.4.0 for Linux x86
 (TurboLinux Enterprise Server 8 SP3- powered by United Linux 1.0)

前回の例では、ユーザ定義フラグとして、独自に DEBUGONブラグをPLSQL_CCFLAGS初期化パラメータで設定していたが、前述の制限の通り、ハックポートされた機能では利用できない。

そのため、バックポートされた条件付きコンパイルでも利用できるよう、PLSQL_DEBUG初期化パラメータを利用することにした。
このパラメータを利用すれば、Oracle10g R2/R1(10.1.0.4.0以降)/Oracle9i R2(9.2.0.6.0以降)それにOracle11gでも利用できるコードにすることができる。

注)初期化パラメータをしなくても各リリースでソースコードを共有できる方法がある。
但し、初期化パラメータを利用する方法に比べ、いちいちコードに手を加えなければならないなど、イマイチな感じはある。(別途掲載予定)

Conditional_compilation_sql_develop

● まずは、PLSQL関連の初期化パラメータの確認から。

PL/SQL関連の隠しパラメータが幾つかあるが、ここで大切なのは、_plsql_conditional_compilationという初期化パラメータでこれがTRUEであれば、PL/SQLの条件コンパイルが機能する。
また、Oracle10g R2には存在していた、PLSQL_CCFLAGS初期化パラメータが存在していないことも確認できる。前述した通り、今回は、PLSQL_DEBUG初期化パラメータを利用して条件コンパイルを行うことにする。

SYS> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.4.0 - Prod
PL/SQL Release 10.1.0.4.0 - Production
CORE 10.1.0.4.0 Production
TNS for Linux: Version 10.1.0.4.0 - Production
NLSRTL Version 10.1.0.4.0 - Production

SYS> l
1 select
2 a.ksppinm,
3 b.ksppstvl,
4 b.ksppstdf
5 from
6 x$ksppi a join x$ksppcv b
7 on a.indx = b.indx
8 and a.ksppinm like '%plsql%'
9 order by
10* a.ksppinm
SYS> /

KSPPINM KSPPSTVL KSPPSTDF
---------------------------------- ------------------------------ ------------------------------
_plsql_anon_block_code_type INTERPRETED TRUE
_plsql_conditional_compilation TRUE FALSE
_plsql_dump_buffer_events TRUE
plsql_code_type INTERPRETED TRUE
plsql_compiler_flags INTERPRETED, NON_DEBUG TRUE
plsql_debug FALSE TRUE
plsql_native_library_dir TRUE
plsql_native_library_subdir_count 0 TRUE
plsql_optimize_level 2 TRUE
plsql_v2_compatibility FALSE TRUE
plsql_warnings DISABLE:ALL TRUE

11行が選択されました。

SYS>

● 前回のコードから変更したコードは赤字部分

SCOTT> l
1 create or replace
2 FUNCTION CONDITIONAL_COMPILATION_SAMPLE
3 RETURN TIMESTAMP
4 IS
5 vNow TIMESTAMP;
6 BEGIN
7 $IF $$PLSQL_DEBUG $THEN
8 DBMS_OUTPUT.ENABLE(20000);
9 DBMS_OUTPUT.PUT_LINE('======= start =====');
10 $END
11 SELECT SYSTIMESTAMP INTO vNow FROM dual;
12 $IF $$PLSQL_DEBUG $THEN
13 DBMS_OUTPUT.PUT_LINE('======= end =======');
14 $END
15 RETURN vNow;
16* END CONDITIONAL_COMPILATION_SAMPLE;
17 /

ファンクションが作成されました。

● では、PLSQL_DEBUG=falseとして確認!

SCOTT> set serveroutput on
SCOTT> alter session set plsql_debug=false;

セッションが変更されました。

SCOTT> alter function conditional_compilation_sample compile;

ファンクションが変更されました。

SCOTT> exec dbms_preprocessor.print_post_processed_source('FUNCTION','SCOTT','CONDITIONAL_COMPILATION_SAMPLE');
FUNCTION CONDITIONAL_COMPILATION_SAMPLE
RETURN TIMESTAMP
IS
vNow TIMESTAMP;
BEGIN
SELECT SYSTIMESTAMP INTO vNow FROM dual;
RETURN vNow;
END CONDITIONAL_COMPILATION_SAMPLE;

PL/SQLプロシージャが正常に完了しました。


SCOTT> select conditional_compilation_sample from dual;

CONDITIONAL_COMPILATION_SAMPLE
---------------------------------------------------------------------------
07-08-13 22:53:14.161995000


● 次に、PLSQL_DEBUG=trueとして確認!

SCOTT> alter session set plsql_debug=true;

セッションが変更されました。

SCOTT> alter function conditional_compilation_sample compile;

ファンクションが変更されました。

SCOTT> exec dbms_preprocessor.print_post_processed_source('FUNCTION','SCOTT','CONDITIONAL_COMPILATION_SAMPLE');
FUNCTION CONDITIONAL_COMPILATION_SAMPLE
RETURN TIMESTAMP
IS
vNow TIMESTAMP;
BEGIN
DBMS_OUTPUT.ENABLE(20000);
DBMS_OUTPUT.PUT_LINE('======= start =====');
SELECT SYSTIMESTAMP INTO vNow FROM dual;
DBMS_OUTPUT.PUT_LINE('======= end =======');
RETURN vNow;
END CONDITIONAL_COMPILATION_SAMPLE;

PL/SQLプロシージャが正常に完了しました。

SCOTT> select conditional_compilation_sample from dual;

CONDITIONAL_COMPILATION_SAMPLE
---------------------------------------------------------------------------
07-08-13 22:54:01.071903000

======= start =====
======= end =======
SCOTT>
SCOTT>


次回は、初期化パラメータを利用しない場合コードの例を載せる予定。

| | コメント (0) | トラックバック (0)

2007年8月15日 (水)

PL/SQL de Conditional Compile #1

PL/SQLで条件付きコンパイル? 耳慣れないのも方も多いかもしれない。 C/C++では、おなじみの#ifdefなどのディレクティブ!

そう、それです! プリプロセッサといえば分かり易いでしょうか。 
Oracle10g R2以降で、正式に、PL/SQLのプリプロセッサが実装されています。(正式にと書いたのには理由があります、実は、この条件付きコンパイルは、Oracle10g R1 10.1.0.4以降、Oracle9i R2 9.2.0.6.0以降にバックポートされています。) 

マニュアルでは、 conditional compilation (条件付きコンパイル)として解説されています。

PL/SQLの条件付きコンパイル、マニュアルには記載はされているものの、この機能を解説している日本語のサイトはほとんど見た事がありませんし、実際の所、私もまだ本格的に利用したことはありません。しかし、うまく使えばそれなりの効果は期待できそうですね。

では、早速、条件付きコンパイルの例を。

● 正式に機能追加されたリリースである、Oracle10g R2で試す。

SYS> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Prod
PL/SQL Release 10.2.0.2.0 - Production
CORE 10.2.0.2.0 Production
TNS for 32-bit Windows: Version 10.2.0.2.0 - Production
NLSRTL Version 10.2.0.2.0 - Production

初期化パラメータにいくつかのPL/SQLコンパイル用パラメータが追加されている。 (Oracle10g R1や、Oracle9i R2と比較するわかりやすいかも。。) 以下は、初期化パラメータの幾つかをリストしたもの。詳細はマニュアル参照のこと。
SYS> show parameter plsql

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
plsql_ccflags string
plsql_code_type string INTERPRETED
plsql_compiler_flags string INTERPRETED, NON_DEBUG
plsql_debug boolean FALSE
plsql_native_library_dir string
plsql_native_library_subdir_count integer 0
plsql_optimize_level integer 2
plsql_v2_compatibility boolean FALSE
plsql_warnings string DISABLE:ALL


● 条件付きコンパイル、PLSQL_CCFLAG初期化パラメータで独自フラグを利用する例

以下は、PLSQL_CCFLAG初期化パラメータで、DEBUGONという独自のフラグを設定し、条件付きコンパイルを行う例で、選択ディレクティブである$IF - $THENを利用してデバッグ用ログの表示コードを制御しています。

PLSQL_CCFLAGで、debugonフラグをtrueに設定すれば、DBMS_OUTPUT.PUT_LINE()でデバッグ用ログを表示するコードがコンパイルされ、false又はフラグが設定されていなければ、表示しないコードでコンパイルされます。

SCOTT> l
1 create or replace
2 FUNCTION CONDITIONAL_COMPILATION_SAMPLE
3 RETURN TIMESTAMP
4 IS
5 vNow TIMESTAMP;
6 BEGIN
7 $IF $$DEBUGON $THEN
8 DBMS_OUTPUT.ENABLE(20000);
9 DBMS_OUTPUT.PUT_LINE('======= start =====');
10 $END
11 SELECT SYSTIMESTAMP INTO vNow FROM dual;
12 $IF $$DEBUGON $THEN
13 DBMS_OUTPUT.PUT_LINE('======= end =======');
14 $END
15 RETURN vNow;
16* END CONDITIONAL_COMPILATION_SAMPLE;
17 /

ファンクションが作成されました。


● dbms_preprocessorパッケージによる条件付きコンパイル後のソースの確認

dbms_preprocessorパッケージのprint_post_processed_source()プロシージャを利用すると、条件付きコンパイル後のソースを確認することができる。(all_sourceビューには、条件付きコンパイル前のソースが格納されているため、条件付きコンパイル後のソースとは異なってしまう。)
DBMS_PREPROCESSORパッケージに関する詳細は、マニュアルを参照のこと。

SCOTT> set serveroutput on
SCOTT> exec dbms_preprocessor.print_post_processed_source('FUNCTION','SCOTT','CONDITIONAL_COMPILATION_SAMPLE');
FUNCTION CONDITIONAL_COMPILATION_SAMPLE
RETURN TIMESTAMP
IS
vNow TIMESTAMP;
BEGIN
SELECT SYSTIMESTAMP INTO vNow FROM dual;
RETURN vNow;
END CONDITIONAL_COMPILATION_SAMPLE;

PL/SQLプロシージャが正常に完了しました。

上記のコードは、PLSQL_CCFLAG初期化パラメータにdebugonフラグが未定義又は、falseで定義された場合のコードである。


● 実行してみると、デバッグ用ログは表示されていない。(当然!)

SCOTT> set serveroutput on
SCOTT> select conditional_compilation_sample from dual;

CONDITIONAL_COMPILATION_SAMPLE
---------------------------------------------------------------------------
07-08-13 18:20:39.234000000

SCOTT> set serveroutput off

● PLSQL_CCFLAG初期化パラメータに debugonフラグをtrueで設定してみると・・・。

SCOTT> 
SCOTT> alter session set plsql_ccflags='debugon:true';

セッションが変更されました。

SCOTT> l
1 create or replace
2 FUNCTION CONDITIONAL_COMPILATION_SAMPLE
3 RETURN TIMESTAMP
4 IS
5 vNow TIMESTAMP;
6 BEGIN
7 $IF $$DEBUGON $THEN
8 DBMS_OUTPUT.ENABLE(20000);
9 DBMS_OUTPUT.PUT_LINE('======= start =====');
10 $END
11 SELECT SYSTIMESTAMP INTO vNow FROM dual;
12 $IF $$DEBUGON $THEN
13 DBMS_OUTPUT.PUT_LINE('======= end =======');
14 $END
15 RETURN vNow;
16* END CONDITIONAL_COMPILATION_SAMPLE;
17 /

ファンクションが作成されました。


SCOTT> exec dbms_preprocessor.print_post_processed_source('FUNCTION','SCOTT','CONDITIONAL_COMPILATION_SAMPLE');
FUNCTION CONDITIONAL_COMPILATION_SAMPLE
RETURN TIMESTAMP
IS
vNow TIMESTAMP;
BEGIN
DBMS_OUTPUT.ENABLE(20000);
DBMS_OUTPUT.PUT_LINE('======= start =====');
SELECT SYSTIMESTAMP INTO vNow FROM dual;
DBMS_OUTPUT.PUT_LINE('======= end =======');
RETURN vNow;
END CONDITIONAL_COMPILATION_SAMPLE;

PL/SQLプロシージャが正常に完了しました。

SCOTT>
SCOTT> set serveroutput on
SCOTT> select conditional_compilation_sample from dual;

CONDITIONAL_COMPILATION_SAMPLE
---------------------------------------------------------------------------
07-08-13 18:26:13.906000000

======= start =====
======= end =======
SCOTT>
ということで、デバッグ用ログが表示されるコードでコンパイルされています!。

次回は、Oracle10g R1 10.1.0.4.0で試す予定。
Conditional_compilation_sql_develop

| | コメント (0) | トラックバック (0)

2007年8月 5日 (日)

Estimate of rollback completion time

さて、前回、おおよそのロールバック完了時刻を見積もる関数でも作ってみるか! なんて言っていたが実際に作ってみた。

尚、今回は、Oracle SQL Developer 1.2 for MacOSXからWindows XP professional上のOracle10g R2 EEへ接続。

Estimate_rollback_complete1 Estimate_rollback_complete2 Estimate_rollback_complete3

● 準備

まずは、テーブルの作成から。
SCOTT> 
SCOTT> desc test
名前 NULL? 型
----------------------------------------- -------- ----------------------------
DATA VARCHAR2(4000)

SCOTT>
SCOTT>
SCOTT>

● データの登録

ロールバックに長時間を要するデータを登録する。(更新でも削除でも構わないが、この例ではINSERT文で。)
SCOTT> begin 
2 for i in 1..400000 loop
3 insert into test values(lpad('x',4000,'x'));
4 end loop;
5 end;
6 /

PL/SQLプロシージャが正常に完了しました。

経過: 00:05:30.06

SCOTT>
SCOTT>

● ロールバック!

準備が整ったので、早速、ロールバック!!
SCOTT>
SCOTT> rollback;

以下、ロールバック処理中に別途起動した、SQL*plusより実行

========以下、ロールバック中、別途起動したSQL*plusから実行した内容==============

● おおよそのロールバック完了時刻を確認する。

自作関数estimateRollbackCompleteTime()を以下のようにスカラ関数として実行すれば、おおよそのロールバック完了日時を確認できる。尚、関数の引数は、ロールバック完了時刻を見積もりたいセッションのSIDとSERIAL#で事前にv$session、v$transactionを問い合わせて確認しておく。

尚、今回は、dbms_lockパッケージの実行権限と、select any dictionaryシステム権限をSCOTTユーザへ付与し、estimateRollbackCompleteTime()関数を作成してある。

SCOTT> select estimateRollbackCompleteTime(146,91) as "Estimate Time",sysdate as now from dual;
Estimate Time NOW
------------------- -------------------
2007/08/02 16:29:46 2007/08/02 16:21:16

SCOTT>


● 以下、UNDOブロックのモニタリング。

ロールバックが進み、used_ublkの値が減少していくことが確認できる。ロールバックの完了時刻は、前述の自作関数で求めたおおよそのロールバック完了時間に近い。
環境などにも影響sれるのだが、予想時間を超えることもあるし、短くなる場合もあるので何度か実行してみるといいですね。または、関数を改造して、見積もりのベースとしている30秒間の処理件数を1分間の処理件数に変更するなどして、精度を高めることは可能かもしれない。
ただ、いつ終わるか分からないロールバック処理時間のおおよその時間を知るにはこのままでも十分なのではないかと思う。

SYSTEM> r
1 select
2 s.sid,
3 s.serial#,
4 s.username,
5 t.used_ublk
6 ,to_char(sysdate,'yyyy/mm/dd hh24:mi:ss') as time
7 from
8 v$session s join v$transaction t
9 on t.addr = s.taddr
10 where
11* s.username = 'SCOTT'

SID SERIAL# USERNAME USED_UBLK TIME
---------- ---------- ---------- ---------- -------------------
146 91 SCOTT 1813 2007/08/02 16:19:13

経過: 00:00:00.01

SYSTEM> /

SID SERIAL# USERNAME USED_UBLK TIME
---------- ---------- ---------- ---------- -------------------
146 91 SCOTT 1594 2007/08/02 16:24:21

経過: 00:00:00.00
SYSTEM> /

SID SERIAL# USERNAME USED_UBLK TIME
---------- ---------- ---------- ---------- -------------------
146 91 SCOTT 882 2007/08/02 16:26:45

経過: 00:00:00.01
SYSTEM> /

SID SERIAL# USERNAME USED_UBLK TIME
---------- ---------- ---------- ---------- -------------------
146 91 SCOTT 747 2007/08/02 16:27:10

経過: 00:00:00.01
SYSTEM> /

SID SERIAL# USERNAME USED_UBLK TIME
---------- ---------- ---------- ---------- -------------------
146 91 SCOTT 668 2007/08/02 16:27:24

経過: 00:00:00.01
SYSTEM> /

SID SERIAL# USERNAME USED_UBLK TIME
---------- ---------- ---------- ---------- -------------------
146 91 SCOTT 28 2007/08/02 16:29:23

経過: 00:00:00.01
SYSTEM> /

レコードが選択されませんでした。

SYSTEM> select to_char(sysdate,'yyyy/mm/dd hh24:mi:ss') as now from dual;

NOW
-------------------
2007/08/02 16:29:30

経過: 00:00:00.01
SYSTEM>

ということで、今回は、たまたま、見積もり時刻より早めに終わったようですね。ラッキー!

===========ロールバック中に別途起動したSQL*Plusでのログ、ここまで==============

ロールバックが完了しました。

経過: 00:14:34.83
SCOTT>


以下、ロールバック完了時間の見積もり関数の例。
内容は単純で、2点間のused_ublk数の残量から単位時間あたりのロールバック処理時間をもとめ、その時点のused_ublk数を元にロールバックが完了するおおよその日時を算出しているだけ。FORループを利用しているのは、単に、明示カーソルのオープン/フェッチ/クローズと例外処理を書かずにすむから。特に必要性がなければ、このプログラミングスタイルが個人的には好き。(この辺りは、好みの問題だけど。)

CREATE OR REPLACE FUNCTION estimateRollbackCompleteTime
(
iSid IN NUMBER,
iSerial# IN NUMBER
)
RETURN DATE IS
C_INTERVAL CONSTANT PLS_INTEGER := 30;

vStartTimestamp TIMESTAMP;
vEndTimestamp TIMESTAMP;
vStartUsedUndoBlocks NUMBER;
vEndUsedUndoBlocks NUMBER;
vEstimatedSecs NUMBER;
vIsFound BOOLEAN;

CURSOR csr_undoblocks
(
pSid IN NUMBER,
pSerial# IN NUMBER
) IS
SELECT
s.username,
t.used_ublk,
SYSTIMESTAMP AS now
FROM
v$session s JOIN v$transaction t
ON t.addr = s.taddr
WHERE
s.sid = pSid
AND s.serial# = pSerial#;
BEGIN
vIsFound := FALSE;
FOR rUndoBlocks IN csr_undoBlocks(iSid, iSerial#) LOOP
vStartTimeStamp := rUndoBlocks.now;
vStartUsedUndoBlocks := rUndoBlocks.used_ublk;
vIsFound := TRUE;
END LOOP;

IF NOT vIsFound THEN
RETURN NULL;
ELSE
vIsFound := FALSE;
END IF;

DBMS_LOCK.SLEEP(C_INTERVAL);

FOR rUndoBlocks IN csr_undoBlocks(iSid, iSerial#) LOOP
vEndTimestamp := rUndoBlocks.now;
vEndUsedUndoBlocks := rUndoBlocks.used_ublk;
vIsFound := TRUE;
END LOOP;

IF NOT vIsFound
OR (vStartUsedUndoBlocks - vEndUsedUndoBlocks) <= 0
THEN
RETURN NULL;
ELSE
vEstimatedSecs :=
CEIL(vEndUsedUndoBlocks / (vStartUsedUndoBlocks - vEndUsedUndoBlocks)) * C_INTERVAL;
RETURN SYSDATE + NUMTODSINTERVAL(vEstimatedSecs, 'SECOND');
END IF;
END;

| | コメント (0) | トラックバック (0)

2007年7月14日 (土)

Oracle Database 11g - PL/SQL - PL/Scope

これまた、渋い機能追加ですね。
Cscopeならぬ、PL/Scopeですか!。 待望の!?のクロスリファレンスツールの登場のようです。
前のエントリでもかいたプロファイリング機能や、クロスリファレンス機能などは、Oracle SQL Developerでも利用できるんでしょうかねぇ。(別途調べてみますか。。)


そういえば、Oracle7のころ、PL/SQLのクロスリファレンスって取れないのか? なんてPro*Cで、ディクショナリビューを問い合せてクロスリファレンスもどきをリストするプログラムを試しに作ったことあったっけ。。。
遠い目。。。プログラムが複雑かつ巨大になるとディクショナリビューの検索に時間がかかり過ぎ、重くて使い物にならなかったので没でしたけど。。。(笑)


Oracle Database 11g Application Development whitepaperより引用。

PL/SQL: PL/Scope

PL/Scope allows you to browse PL/SQL source code analogously to the way that
Cscope (see http://cscope.sourceforge.net/) allows you to browse C source code.
You can search for and display all types of definitions, declarations, assignments
and references in the PL/SQL source code. The PL/SQL compiler can optionally
derive the metadata needed to support PL/Scope and store it in the database
catalog. The metadata takes into account the nuances of the language, including
scoping and overloading. You can generate reports (especially hyperlinked HTML
reports) with supplied report generators. PL/Scope supports increased developer
productivity, especially for those who need to maintain someone else's code.

| | コメント (0) | トラックバック (0)

Oracle Database 11g - PL/SQL - Sequences

お〜。これは便利。
PL/SQL内から直接、シーケンスにアクセスできるようになるんですね。
これまでは、PL/SQL内でシーケンスにアクセスするには

select hoge_sequence.nextval into vSeq# from dual;

なんてクエリをPL/SQL内で発行する必要があった訳ですけど、これからはダイレクトに

vSeq# := hoge_sequence.nextval;

と書けるということなんでしょうね。便利です。

眠いので今日はこの辺りで。。。。。

Oracle Database 11g Application Development  whitepaperより引用。

PL/SQL: Sequences

The sequence generator provides a sequential series of numbers to applications.
The sequence generator is especially useful in multiuser environments for
generating unique sequential numbers such as an employee id without the overhead
of disk I/O or transaction locking.
In the previous release of Oracle Database, when a PL/SQL program needed to get
a value from syntax, it used SQL. This is a usability irritation for PL/SQL
programmers. In Oracle Database 11g, it is now possible to simply use the
pseudocolumns CURRVAL and NEXTVAL in a PL/SQL expression.
Simplifies coding.

| | コメント (0) | トラックバック (0)

Oracle Database 11g - PL/SQL - Hierarchical Profiler

へぇ〜。 PL/SQLのプロファイリングって、今までは、DBMS_PROFILEパッケージを使っていたけど、DBMS_PROFILERパッケージが進化したってことなのか?、それとも、新しいプロファイラーなのかなぁ。以下の概要ではそこまでは解説されていないけど、結果をHTMLで確認できるとか、深い部分までプロファイリングできそうですね。これまでのPL/SQLプロファイリングよりかなり使い勝手は向上しているようで期待してます。

Oracle Database 11g Application Development whitepaperより引用。

PL/SQL: Hierarchical Profiler

The PL/SQL hierarchical profiler reports the dynamic execution profile of your
PL/SQL program, organized by subprogram calls. It accounts for SQL and
PL/SQL execution times separately. Each subprogram-level summary in the
dynamic execution profile includes information such as number of calls to the
subprogram, time spent in the subprogram itself, time spent in the subprogram's
subtree (that is, in its descendent subprograms), and detailed parent-children
information. You can browse the generated HTML reports in any browser. The
browser's navigational capabilities, combined with well chosen links, provide a
powerful way to analyze performance of large applications, improve application
performance, and lower development costs.

| | コメント (0) | トラックバック (0)

2007年7月 8日 (日)

Stored Procedure で host command #3

前回からの続きです。
さて、前回は、javaクラスをOracle Databaseへデプロイしたところまでだった。

ということで、デプロイしたクラスとメソッドを確認しておきましょう! (以下の例は、 user_java_methodsビューを問い合わせたもの)

このマニュアルも参考になるのでリンクしておきます。

SQL> conn scott/tiger
SQL> select name,method_name,accessibility,is_static,return_class from user_java_methods;

NAME METHOD_NAM ACCESSIBILITY IS_STA RETURN_CLA
---------------------------------------- ---------- ------------------ ------ ----------
jp/macdeoracle/CommandOutputReader $init$ NO -
jp/macdeoracle/CommandOutputReader <init> PUBLIC NO -
jp/macdeoracle/CommandOutputReader run PUBLIC NO -
jp/macdeoracle/HostCommandExecuter <clinit> YES -
jp/macdeoracle/HostCommandExecuter exec PRIVATE YES -
jp/macdeoracle/HostCommandExecuter ls PUBLIC YES -
jp/macdeoracle/HostCommandExecuter main PUBLIC YES -
jp/macdeoracle/HostCommandExecuter <init> PUBLIC NO -

8行が選択されました。

SQL>

● 次にjavaストアドプロシージャのコール仕様を作成する

language java以降がポイントですよ。実行するstatic methodを指定します。
SQL> create or replace procedure ls(directory IN VARCHAR2)
2 as language java
3 name 'jp.macdeoracle.HostCommandExecuter.ls(java.lang.String)';
4 /

プロシージャが作成されました。

では、実行してみると・・・・・。
あれれ、権限が足りないとでますね。。。。。

SQL>
SQL> exec ls('c:¥temp');
BEGIN ls; END;

*
行1でエラーが発生しました。:
ORA-29532: 不明なJava例外でJavaコールが終了しました: java.security.AccessControlException: the Permission (java.io.FilePermission <<ALL
FILES>> execute) has not been granted to SCOTT. The PL/SQL to grant this is dbms_java.grant_permission( 'SCOTT',
'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute' )
ORA-06512: "SCOTT.LS", 行1
ORA-06512: 行1


● エラーメッセージの指示通りに、 dbms_java.grant_permissionを実行してみることに。。
  user_java_policyを確認してみると権限は付与されたようですね。。。

SQL> conn / as sysdba
SQL> execute dbms_java.grant_permission('SCOTT','SYS:java.io.FilePermission','<<ALL FILES>>','execute');

PL/SQLプロシージャが正常に完了しました。

SQL>
SQL> conn scott/tiger
SQL> select action,type_name,name,enabled from user_java_policy;


ACTION TYPE_NAME NAME ENABLED
---------- ---------------------------------------- ---------------------------------------- ----------------
read java.io.FilePermission <<ALL FILES>> ENABLED
java.lang.RuntimePermission accessClassInPackage.* ENABLED
java.lang.RuntimePermission defineClassInPackage.* ENABLED
java.lang.RuntimePermission getProtectionDomain ENABLED
java.lang.RuntimePermission stopThread ENABLED
connect, java.net.SocketPermission * ENABLED
resolve
java.lang.RuntimePermission createSecurityManager ENABLED
java.lang.RuntimePermission exitVM ENABLED
java.lang.RuntimePermission loadLibrary.* ENABLED
java.lang.RuntimePermission modifyThread ENABLED
java.lang.RuntimePermission modifyThreadGroup ENABLED
java.lang.RuntimePermission preferences ENABLED
read java.util.PropertyPermission * ENABLED
write java.util.PropertyPermission user.language ENABLED
oracle.aurora.rdbms.security.PolicyTable 0:java.lang.RuntimePermission#loadLibrar ENABLED
Permission y.*
oracle.aurora.security.JServerPermission DUMMY DISABLED
oracle.aurora.security.JServerPermission LoadClassInPackage.* ENABLED
oracle.aurora.security.JServerPermission LoadClassInPackage.java.* ENABLED
oracle.aurora.security.JServerPermission LoadClassInPackage.oracle.aurora.* ENABLED
oracle.aurora.security.JServerPermission LoadClassInPackage.oracle.jdbc.* ENABLED
execute java.io.FilePermission <<ALL FILES>> ENABLED

21行が選択されました。

SQL>


再度、実行してます!

SQL> exec ls('c:¥temp');
BEGIN ls; END;

*
行1でエラーが発生しました。:
ORA-29532: 不明なJava例外でJavaコールが終了しました: java.security.AccessControlException: the Permission (java.io.FilePermission <<ALL
FILES>> execute) has not been granted to SCOTT. The PL/SQL to grant this is dbms_java.grant_permission( 'SCOTT',
'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute' )
ORA-06512: "SCOTT.LS", 行1
ORA-06512: 行1


なんなんでしょうね。よくわからないエラーメッセージですね。権限はあるのに。
わかりにくいメッセージ。やはりこうでなくちゃ、オラクルは。。なんてね。
イライラしてきたので、javasysprivロールを付与しちゃいました。(セキュリティ面からみれば好ましくないのですけど。)
各クラス毎に実行権限を細かく付与すればうまくいきそうですが、エラーメッセージからは、何のどんな権限が不足しているのか単純には判断できない(予想はつきますけど・・・)ので、この件に関しては別途調べることにして先へ進むことにします。要調査->TODO

SQL> conn / as sysdba
接続されました。
SQL> grant javasyspriv to scott;

権限付与が成功しました。


:-) やっと動いた〜。

SQL> conn scott/tiger
接続されました。

SQL>
SQL> set serveroutput on
SQL> exec dbms_java.set_output(2000);

PL/SQLプロシージャが正常に完了しました。

SQL> exec ls('c:¥temp');
apex_3.0
apex_3.0.zip
jdevstudio10131.zip
version.log

PL/SQLプロシージャが正常に完了しました。

SQL>

なんとか実行できました。。。ね。 (^^;;;;

Jdeveloper_filelist3

| | コメント (0) | トラックバック (0)

2007年7月 4日 (水)

Stored Procedure で host command #2

さて、前回のつづきです。
javaストアドプロシージャのソースは以下の通り。

OSコマンドを実行するjavaの例は、ググればやまほどヒットするので特に解説はなし。
Oracleでjavaストアドプロシージャを作成する方法は、マニュアル「Oracle Database Java開発者ガイド - 3 Oracle DatabaseでのJavaメソッドのコール」を参照のこと。
基本は前述のマニュアルで足りると思います。(今回は、JDBCも利用していませんし。)
それに加えて、OTN-JのOracleJVM and Java Stored Procedures なども参考になるでしょうね。

以下、Oracle JDeveloper 10.1.3.1 for MacOSXを利用。

Jdev10gmacosx_hostcommand

package jp.macdeoracle;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;


public class CommandOutputReader extends Thread {
private InputStream is;
private String lines = "";

public CommandOutputReader(InputStream is) {
this.is = is;
}

public void run()
{
String outputLine;
try {
BufferedReader br = new BufferedReader(new InputStreamReader(this.is));
while ((outputLine = br.readLine()) != null) {
System.out.println(outputLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package jp.macdeoracle;

import java.lang.Runtime;
import java.lang.SecurityException;
import java.io.IOException;

public class HostCommandExecuter
{
public static final String OS_WINDOWS_ = "Windows";
public static final String OS_MACOSX_ = "Mac OS X";
public static final String OS_LINUX_ = "Linux";

private static void exec(String[] command)
throws IOException,
SecurityException,
InterruptedException
{
Process myproc = Runtime.getRuntime().exec(command);
new CommandOutputReader(myproc.getInputStream()).start();
new CommandOutputReader(myproc.getErrorStream()).start();
myproc.waitFor();
}

public static void ls(String directory)
throws IOException,
SecurityException,
InterruptedException
{
String osname = System.getProperty("os.name");
if (osname.indexOf(OS_WINDOWS_) >= 0) {
String[] cmd = {"CMD.EXE", "/C", "DIR", "/B", directory};
exec(cmd);
} else if (
osname.indexOf(OS_MACOSX_) >= 0
|| osname.indexOf(OS_LINUX_) >= 0
) {
String[] cmd = {"/bin/ls", directory};
exec(cmd);
} else {
throw new IOException(osname + ":このOSには対応していません。");
}
}

public static void main(String[] args)
throws IOException,
InterruptedException,
SecurityException
{
ls(".");
}
}

上記ソースをコンパイルしてOracle Databaseへデプロイ! (以下、Oracle10g R2の例)
うまくいけば以下のようなログが表示される。

loadjavaを接続'Oracle10gR2_Scott'で呼出し中。引数:
-order -resolve -definer -force -thin -schema scott -verbose
creating : class SCOTT.jp/macdeoracle/CommandOutputReader
loading : class SCOTT.jp/macdeoracle/CommandOutputReader
creating : class SCOTT.jp/macdeoracle/HostCommandExecuter
loading : class SCOTT.jp/macdeoracle/HostCommandExecuter
resolving: class SCOTT.jp/macdeoracle/CommandOutputReader
resolving: class SCOTT.jp/macdeoracle/HostCommandExecuter
Loadjavaが終了しました。
公開が終了しました。
---- ストアド・プロシージャのデプロイが終了しました ----


次のようなエラーがでたら、J2SE 1.4.xでコンパイルし直してデプロイすべし! 
オラクルにしては、わかり易いメッセージじゃ。 (^^) 

loadjavaを接続'Oracle9iR2_Scott'で呼出し中。引数:
-order -resolve -definer -force -thin -schema scott -verbose
creating : class SCOTT.jp/macdeoracle/CommandOutputReader
loading : class SCOTT.jp/macdeoracle/CommandOutputReader
created : "SCOTT".CREATE$JAVA$LOB$TABLE
Error while creating class jp/macdeoracle/CommandOutputReader
ソケットから読み込むデータはこれ以上ありません。
Error while testing for existence of dbms_java.handleMd5
Exception java.sql.SQLException: OALL8 is in an inconsistent state.
created : "SCOTT".JAVA$CLASS$MD5$TABLE
creating : class SCOTT.jp/macdeoracle/HostCommandExecuter
loading : class SCOTT.jp/macdeoracle/HostCommandExecuter
Error while creating class jp/macdeoracle/HostCommandExecuter
ソケットから読み込むデータはこれ以上ありません。
The following operations failed
class SCOTT.jp/macdeoracle/CommandOutputReader: creation (createFailed)
class SCOTT.jp/macdeoracle/HostCommandExecuter: creation (createFailed)
oracle.aurora.server.tools.loadjava.ToolsException: Failures occurred during processing
at oracle.aurora.server.tools.loadjava.LoadJava.process(LoadJava.java:863)
at oracle.jdeveloper.deploy.tools.OracleLoadjava.deploy(OracleLoadjava.java:116)
at oracle.jdeveloper.deploy.tools.OracleLoadjava.deploy(OracleLoadjava.java:46)
at oracle.jdevimpl.deploy.OracleDeployer.deploy(OracleDeployer.java:97)
at oracle.jdevimpl.deploy.StoredProcHandler.doDeploy(StoredProcHandler.java:473)
at oracle.jdevimpl.deploy.StoredProcHandler.doDeploy(StoredProcHandler.java:360)
at oracle.jdevimpl.deploy.StoredProcHandler.doDeploy(StoredProcHandler.java:284)
at oracle.jdevimpl.deploy.StoredProcProfileDt$Action$1.run(StoredProcProfileDt.java:383)
#### デプロイが不完全です ####
*** Note ***
デプロイ・エラーの可能性の1つとして、ターゲット・データベースがJDKバージョン1.5をサポートしていないことが考えられます。
お使いのプロジェクト・プロパティ・コンパイラのソースとターゲットを古いバージョンに変更することで、この問題を修復できます。
************


プロジェクトプロパティを開いて、j2se 1.4.2を設定している様子。
Change_jdk1 Change_jdk2Change_jdk3Change_jdk4

今日はここまで。次回へつづく。

| | コメント (0) | トラックバック (0)

2007年6月30日 (土)

Stored Procedure で host command

随分前のネタ(Oracle9i R2は、TurboLinux8 Enterprise Server - Powered by United Linux 1.0と Oracle10g R1 は、MacOSX Pantherの頃なので2005年くらいに公開するタイミングを逃していたネタ)なんですが、検索キーワードやOTN-Jなどでもたまに見かけるので、昔のネタに、Oracle10g R2 for Windowsの例も付け加えて公開することにした。

どんなネタかって? まずは実行結果から。

見ての通り、ストアドプロシージャからDOSコマンドのdirや、shellコマンドのlsを実行してます。
Oracleのストアドプロシージャは、PL/SQL以外に、javaやCでを書くこともできます。
以下の例は、javaストアドプロシージャで DOSコマンドのdirや、shellコマンドのlsを実行しています。

セキュリティ上、なんでもかんでも実行できるようにしたりするのはお勧めしませんが、以前、負荷テストで使ったことがあります。
負荷テスト開始のタイミングで、sarを実行し、テスト終了時に停止させるshellスクリプトを実行してましたね。 いつ終わるかはっきりしないような負荷テストを自動起動し、システム側の状態も同時に記録するといったことを行っていました。
ただ、最近は、DBMS_SCHEDULERパッケージがあるので自前で作らなくてできるとは思いますが。。まぁ、こんなことも出来るんだよね。 っていうことを知ってても損はないんじゃないかと思います。


● Linux (United Linux 1.0 なつかしい〜。)

SCOTT> conn scott@zion
パスワードを入力してください:
接続されました。
SCOTT> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
PL/SQL Release 9.2.0.1.0 - Production
CORE 9.2.0.1.0 Production
TNS for Linux: Version 9.2.0.1.0 - Production
NLSRTL Version 9.2.0.1.0 - Production

SCOTT>
SCOTT>
SCOTT> set serveroutput on
SCOTT> exec dbms_java.set_output(20000);

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec ls('/tmp');
UnitedLinux-1.0-SP-3
i830-20030120-i386-linux.tar.gz
turbonetcfg-routing.log
turbonetcfg.log

PL/SQLプロシージャが正常に完了しました。

SCOTT>

● MacOSX 10.3 Panther

SCOTT> conn scott@panther
パスワードを入力してください:
接続されました。
SCOTT> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Prod
PL/SQL Release 10.1.0.3.0 - Production
CORE 10.1.0.3.0 Production
TNS for MacOS X Server: Version 10.1.0.3.0 - Production
NLSRTL Version 10.1.0.3.0 - Production

SCOTT> set serveroutput on
SCOTT> exec dbms_java.set_output(20000);

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec ls('/Users/oracle');
Desktop
Documents
Library
Movies
Music
Pictures
Public
Sites
jdevhome

PL/SQLプロシージャが正常に完了しました。

SCOTT>


● Windows XP Professional

SCOTT> conn scott@catfish
パスワードを入力してください:
接続されました。
SCOTT>
SCOTT>
SCOTT>
SCOTT> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Prod
PL/SQL Release 10.2.0.2.0 - Production
CORE 10.2.0.2.0 Production
TNS for 32-bit Windows: Version 10.2.0.2.0 - Production
NLSRTL Version 10.2.0.2.0 - Production

SCOTT>

SCOTT> set serveroutput on
SCOTT> exec dbms_java.set_output(20000);

PL/SQLプロシージャが正常に完了しました。

SCOTT> exec ls('c:¥temp');
apex_3.0
apex_3.0.zip
jdevstudio10131.zip
version.log

PL/SQLプロシージャが正常に完了しました。

SCOTT>

ってとこですね。ほんとにお遊びでした。(笑)

ということで、次回はどうやってOracleのPL/SQL、java、ホストコマンドで遊んでいるかお見せします。

| | コメント (0) | トラックバック (0)

2007年6月 8日 (金)

Mac De Oracle : PL/SQL de Collection #5


Marcus Miller - Silver Rain - It'll Come Back to YouMarcus Miller - Silver Rain - It'll Come Back to You

ちょいと間が空いたが、PL/SQLのコレクションでのお遊び。その5回目。

検索ワードで結構目にするのが、"N次元 結合配列" というキーワード。

ということで、今回は、多次元のコレクションの例を。

N次元のコレクションってどうやって作るの? ってことで情報を検索しているのだと思いますが、しっかりマニュアルにも記載されているので、そちらもしっかり読んでおくことをおすすめしますよ!。

Associative Array(以下、結合配列)、VARRAYやNested Table(以下、ネスト表)どれでも、考え方は同じ。
コレクション自体を別コレクションの要素にすればできるんですよ。 コレクションを入れ子にする と言えばイメージしやすい? ですかね。


以下のコードで赤太字で示しているところが多次元コレクション定義とアクセスのポイント。
まず、empType型を要素とするNestedTableType型(ネスト表)を定義し、次にNestedTalbType型を要素とするStrAssociativeArrayType型(結合配列)を定義している。
以下の例は多少、ひねくれた例? として結合配列とネスト表という異なるコレクションを利用して多次元コレクションを定義している。その影響でコレクションの操作は多少面倒になるのだが..

尚、empType型は、事前に作成しておいたオブジェクト型。

create or replace
PROCEDURE multiLevelCollections
AS
TYPE NestedTableType IS TABLE OF empType;
TYPE StrAssociativeArrayType IS TABLE OF NestedTableType INDEX BY VARCHAR2(50);

myNestedTable NestedTableType := NestedTableType();
myStrAssociativeArray StrAssociativeArrayType;


claerMyStrAssociateArray StrAssociativeArrayType;

myEmp empType;
j dept.dname%TYPE;
vDeptName dept.dname%TYPE := NULL;

CURSOR csrEmp IS
SELECT
emp.job,
emp.deptno,
dept.dname,
emp.empno,
emp.ename,
emp.sal,
emp.hiredate
FROM
emp JOIN dept
ON emp.deptno = dept.deptno
ORDER BY
emp.deptno,
emp.ename;

PROCEDURE printArray
IS
BEGIN
DBMS_OUTPUT.NEW_LINE;
DBMS_OUTPUT.PUT_LINE('**** コレクションに要素が存在している状態 ****');
DBMS_OUTPUT.PUT_LINE(
'myStrAssociativeArray('
|| myStrAssociativeArray.COUNT
|| ')'
);

j := myStrAssociativeArray.FIRST;
WHILE j IS NOT NULL LOOP
DBMS_OUTPUT.NEW_LINE;
DBMS_OUTPUT.PUT_LINE(
'myStrAssociativeArray('
|| j || ')(' || myStrAssociativeArray(j).COUNT || ')'
);

FOR k IN
myStrAssociativeArray(j).FIRST..myStrAssociativeArray(j).LAST
LOOP
DBMS_OUTPUT.PUT_LINE(
'myStrAssociativeArray(' || j || ').'
|| 'myNestedTable(' || TO_CHAR(k) || ') = '
|| myStrAssociativeArray(j)(k).TO_STRING()
);
END LOOP;
j := myStrAssociativeArray.NEXT(j);
END LOOP;
END;

BEGIN
FOR emp_rec IN csrEmp LOOP
IF csrEmp%ROWCOUNT = 1 THEN
vDeptName := emp_rec.dname;
END IF;

myEmp := empType (
emp_rec.empno,
emp_rec.ename,
emp_rec.job,
emp_rec.hiredate,
emp_rec.sal,
emp_rec.deptno
);

IF vDeptName <> emp_rec.dname THEN
myStrAssociativeArray(vDeptName) := myNestedTable;
vDeptName := emp_rec.dname;
myNestedTable := NestedTableType();
END IF;

myNestedTable.EXTEND(1);
myNestedTable(myNestedTable.COUNT) := myEmp;
END LOOP;

IF myNestedTable.COUNT > 0 THEN
myStrAssociativeArray(vDeptName) := myNestedTable;
END IF;

printArray();

-- 結合配列を空にする!
myStrAssociativeArray := claerMyStrAssociateArray;

DBMS_OUTPUT.NEW_LINE;
DBMS_OUTPUT.PUT_LINE('**** コレクションが空の状態 ****');
DBMS_OUTPUT.PUT_LINE(
'myStrAssociativeArray('
|| myStrAssociativeArray.COUNT
|| ')'
);


END;
/

SCOTT> l
1 select
2 emp.deptno,
3 dept.dname,
4 emp.empno,
5 emp.ename,
6 emp.sal,
7 emp.hiredate
8 from
9 emp join dept
10 on emp.deptno = dept.deptno
11 order by
12 emp.deptno,
13* emp.ename
SCOTT> /

DEPTNO DNAME EMPNO ENAME SAL HIREDATE
---------- -------------- ---------- ---------- ---------- --------
10 ACCOUNTING 7782 CLARK 2450 81-06-09
10 ACCOUNTING 7839 KING 5000 81-11-17
20 RESEARCH 7876 ADAMS 1100 87-05-23
20 RESEARCH 7566 JONES 2975 81-04-02
20 RESEARCH 7788 SCOTT 3000 87-04-19
20 RESEARCH 7369 SMITH 800 80-12-17
30 SALES 7499 ALLEN 1600 81-02-20
30 SALES 7698 BLAKE 2850 81-05-01
30 SALES 7900 JAMES 950 81-12-03
30 SALES 7654 MARTIN 1250 81-09-28
30 SALES 7844 TURNER 1500 81-09-08
30 SALES 7521 WARD 1250 81-02-22

12行が選択されました。

SCOTT>

実行結果は次のようになる。(Oracle SQL Developer 1.1 for MacOSX) 
1.2がリリースされたようなので後でダウンロードしとくか・・> TODO

Oracleplsqldev11

Mlevelcollresults


ということで、今日はここまで。

Have a good Week end!

| | コメント (0) | トラックバック (0)

2007年6月 6日 (水)

PL/SQL de File Upload / Download #5


Kate Bush - The Whole Story - Experiment IV Kate Bush - The Whole Story - Experiment IV


PL/SQL de File Upload / Download の最終回。

さて、前回は、日本語ファイル名のファイルをダウンロードするとFirefoxやMozilla以外のブラウザでは文字化け等が発生するというところまでだった。

また、IE6では、Content-Disposition: attachment; filenameを指定する方法であれば文字化けを回避できるということも確認した。

ただ、Mac De Oracleでは一番大切な Safari。そのSafariでは常に文字化けしていた。残念!〜〜で終わらせないのがMac De Oracle.

調べた結果、文字エンコードをUTF-8で統一すれば回避できるのでは? という考えに至り、即実行!


OTN-J の Code Tipsでも公開されました。(2007/6/16更新) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2235 http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2236

下記手順で mod_plsqlのファイルアップロード/ダウンロード環境を再構築した。

  1. データベースキャラクタセットをAL32UTF8で新たなデータベースを作成する。JA16SJISTILDEからAL32UTF8へデータベースキャラクタセットを変更することはできないため、新たにデータベースを作成することになる。
  2. dads.confのPlsqlNLSLanguageをJAPANESE_JAPAN.JA16SJISTILDEからJAPANESE_JAPAN.AL32UTF8へ変更する。
  3. ストアドプロシージャで生成するHTMLのcharsetをShift_JISからUTF-8へ変更する。
  4. utl_url.escapeプロシージャでURLエンコードする際の文字コードをShift_JISからAL32UTF8へ変更する。

1.データベースの作成

DBCA (Database Configuration Assistant)を利用し、データベースキャラクタセット:AL32UTF8のデータベースをサクッと作成しちゃいます。時間のかかるのはこの部分だけですね。
既に、データベースキャラクタセットがAL32UTF8であればこのステップはスキップしてください。

2.dads.confの変更

PlsqlNLSLanguageをJAPANESE_JAPAN.JA16SJISTILDEからJAPANESE_JAPAN.AL32UTF8へ変更します。
# ============================================================================ 
# mod_plsql DAD Configuration File
# ============================================================================
# 1. Please refer to dads.README for a description of this file
# ============================================================================

# Note: This file should typically be included in your plsql.conf file with
# the "include" directive.

# Hint: You can look at some sample DADs in the dads.README file

# ============================================================================
<Location /plsql_de_fileupload>
SetHandler pls_handler
Order deny,allow
Allow from all
AllowOverride None
PlsqlDatabaseUsername scott
PlsqlDatabasePassword tiger
PlsqlDatabaseConnectString 192.168.1.19:1521:amazon
PlsqlAuthenticationMode Basic
PlsqlDefaultPage scott.fileUploadForm
PlsqlDocumentTablename scott.discusDocTable
PlsqlDocumentPath docs
PlsqlDocumentProcedure scott.fileDownloader
PlsqlNLSLanguage JAPANESE_JAPAN.AL32UTF8
</Location>

3.プロシージャの変更
(1)ファイルを最大5件同時にアップロードするフォームを表示するプロシージャの変更。

charsetをShift_JISからUTF-8へ変更するだけ。
CREATE OR REPLACE PROCEDURE fileUpLoadForm
IS
numOfFiles CONSTANT PLS_INTEGER := 5;
BEGIN
htp.htmlopen;
htp.headopen;
htp.meta('CONTENT-Type',null,'text/html; charset=UTF-8');
htp.title('PL/SQL de File Upload');
htp.headclose;

htp.bodyopen;
htp.centeropen;
htp.print('<div align="center" style="width:500; height:600">');
htp.STRONG(
cattributes=> 'style="font-size:24px; color:#ff0000; '
|| 'text-shadow:1px 2px 3px #7f7f7f"',
ctext=> 'PL/SQL de ファイルアップロード'
);
htp.prn('<br><br>');
htp.formopen(
cenctype=>'multipart/form-data',
curl=>'action',cmethod=>'POST'
);

FOR i IN 1..numOfFiles LOOP
htp.prn(
'<p><span style="text-shadow:1px 2px 3px #7f7f7f">ファイルの選択:</span>'
);
htp.formfile(cname=>'file');
htp.br;
END LOOP;
htp.prn('<br><br><p>');
htp.formsubmit(cattributes=>'align=right',cvalue=>'アップロード');

htp.formclose;
htp.print('</div>');
htp.centerclose;
htp.bodyclose;
htp.htmlclose;
END;
/


(2)<FORM>要素のaction属性に指定するプロシージャの変更

charsetをShift_JISからUTF-8へ変更するだけ。
CREATE OR REPLACE PROCEDURE action
(
file IN owa_util.vc_arr
) IS
vOpe# number(10);
BEGIN
htp.htmlopen;
htp.meta('CONTENT-TYPE',null,'text/html; charset=UTF-8');
htp.headopen;
htp.title('PL/SQL de File Upload (Action)');
htp.headclose;
htp.bodyopen;
htp.header(1,'アップロード・ステータス');
htp.print('以下のアップロードが終了しました。<br><br>');
htp.prn('<span style="color:#ff0000; text-shadow:1px 2px 3px #7f7f7f">');
FOR i IN file.FIRST..file.LAST LOOP
IF FILE(i) IS NOT NULL THEN
htp.print('-&gt; ' || file(i) || '<br>');
END IF;
END LOOP;
htp.print('</span>');

-- 同一操作でアップロードしたファイルへ、同一操作番号を設定する。
SELECT upload_operation#.nextval INTO vOpe# FROM dual;
FOR i IN file.FIRST..file.LAST LOOP
UPDATE DISCUSDOCTABLE SET operation# = vOpe# WHERE name=file(i);
END LOOP;

htp.bodyclose;
htp.htmlclose;
END;
/


(3)ダウンロード可能なファイルリストを表示するプロシージャの変更。

charsetをShift_JISからUTF-8へ変更、utl_url.escapeでURLエンコードする際の文字コードをShift_JISからAL32UTF8へ変更。
CREATE OR REPLACE PROCEDURE fileList
IS
BEGIN
htp.htmlopen;
htp.headopen;
htp.meta('CONTENT-Type',null,'text/html; charset=UTF-8');
htp.title('PL/SQL de File upload - ダウンロード可能なファイル一覧');
htp.headclose;
htp.bodyopen;
htp.print(
'<span style="text-shadow:1px 2px 3px #7f7f7f; font-size: 22px">'
|| 'ダウンロードファイル一覧</span><br><br>'
);
FOR doc IN (SELECT name FROM discusDocTable) LOOP
htp.anchor('docs/' || utl_url.escape(doc.name, false, 'AL32UTF8'), 'docs/' || doc.name);
htp.br;
END LOOP;
htp.bodyclose;
htp.htmlclose;
END;
/

(4)ファイルのダウンロード時にmod_plsqlから呼び出されるプロシージャの変更。

charsetをShift_JISからUTF-8へ変更。
CREATE OR REPLACE PROCEDURE fileDownloader
IS
vFilePath VARCHAR2(256);
BEGIN
vFilePath := SUBSTR(owa_util.get_cgi_env('PATH_INFO'), 2);
wpg_docload.download_file(vFilePath);
EXCEPTION
WHEN OTHERS THEN
htp.htmlopen;
htp.headopen;
htp.meta('Ccntent-Type',null,'text/html; charset=UTF-8');
htp.headclose;
htp.bodyopen;
htp.print('ダウンロードファイル:' || vFilePath);
htp.print('<strong style="color:#ff0000">' || sqlerrm() || '</strong>');
htp.bodyclose;
htp.htmlclose;
END fileDownloader;
/


最後に、各プラットフォーム、各ブラウザでダウンロードしているスクリーンショットを。
MacOSX
Safari:
Macosx_safari

Firefox:
Macosx_firefox

Opera9.2:
Macosx_opera92

Linux(TurboLinux8 , CentOS4.4)
Firefox:
Centos44_firefox

SeaMonkey:
Centos44_seamonkey103

Mozilla1.4.2(TurboLinux8):
Turbolinux_mozilla142

Windows XP Professional
IE6:
Windows_ie6

FIrefox:
Windows_firefox


結果として、データベースからHTMLまでの文字エンコードを UTF-8 に統一することで、Firefox以外のブラウザで発生していた文字化けを回避することができるということになる。   (^▽^)v

追記、Oracle10gでは、(おそらく Oracle11g以降も)、新規に作成するデータベースのキャラクタセットは、Unicodeが推奨されているので、データベース作成時のキャラクタセットは、AL32UTF8にしておいたほうがいいだろうね。

以下、マニュアルより引用


データベース・キャラクタ・セットとしてのUnicodeの選択

すべての新規システム配置にUnicodeを使用することをお薦めします。レガシー・システムも最終的にはUnicodeに移行することをお薦めします。現在システムをUnicodeで配置すると、利便性、互換性および拡張性の面で多くの利点があります。Oracle Databaseの包括的なサポートにより、Unicodeの利点を活かしながら高パフォーマンス・システムを高速かつ容易に配置できます。現時点で多言語データをサポートする必要がない場合、またはUnicodeが必要ない場合でも、長期的には新規システムに最適な選択となる可能性が高く、結局は時間を短縮してコストを節減し、競争上の優位性を得ることになります。Unicodeの詳細は、第6章「Unicodeを使用した多言語データベースのサポート」を参照してください。


ついでに、グローバリゼージョンガイドの6 Unicodeを使用した多言語データベースのサポートあたりも熟読して最終的にどの文字コードやエンコーディングにするか判断するべし。

| | コメント (0) | トラックバック (0)

2007年6月 5日 (火)

PL/SQL de File Upload / Download #4


Howard Jones - The Peaceful Tour - Things Can Only Get BetterHoward Jones - The Peaceful Tour - Things Can Only Get Better

PL/SQL de File Upload / Download のつづきです。


前回は、MacOSXのSafariで発生する問題。日本語ファイル名のファイルをダウンロードした際、ファイル名が、 hostname.拡張子 のような形式で保存されてしまうというところまでだった
Firefoxでは全く問題が発生していないので、ブラウザ依存の問題ということなのだろうか。


ということで、今回は、MacOSX以外のプラットフォームで試した結果+αも。


OTN-J の Code Tipsでも公開されました。(2007/6/16更新) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2235 http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2236

ファイル名が日本語であるファイルをダウンロードした場合のファイル名の文字化けについて

・Firefox 2 (Mozilla含む) : MacOSX/Linux/Windows XP すべてのプラットフォームで
 文字化け等の問題は発生しない。

Firefox2macosxok Firefox2windowsok Mozillalinuxok


・IE6 : 文字化け。

Ieng_1


・Safari : 前述の通り。 hostname.拡張子 という形式で保存されてしまう。

・Opera 9.2 (MacOSX版): URLエンコードされた文字列.拡張子 という形式で保存されてしまう


Operamacosxng



文字エンコードが統べてUTF-8だったらどうなんだろう。。。解決できたりして。。。という思いつきは置いといて、今日は、Shift_JISのままでIE6での文字化けを(無理矢理?)解決する方法があったので載せておくことにする。

参考:
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19260-01/concept.htm#i1011220


※2007/6/8一部修正
以下のようにContent-Disposition: attachment; filename=UTF-8でURLエンコードしたファイル名を指定する方式であれば、IE6でも正しいファイル名で保存できるようになる。
MacOSXのSafariでは依然として改善されず、下記方法では文字化けしてしまう。 

以下の方法もマニュアルに記載されている方法だが、あくまで英語圏で作成されたマニュアルの翻訳なので、ファイル名が日本語である場合の文字化け回避方法までは記載されていない。
文字化けの回避はブラウザにも依存する部分なのでなかなか面倒ですね。文字コードやエンコーディングがいろいろとありすぎてうれしくないな〜。

create or replace PROCEDURE fileDownloader
IS
vFilePath VARCHAR2(256);
vUserAgent VARCHAR2(512);
vContentType discusdoctable.BLOB_CONTENT%TYPE;
vMimeType discusdoctable.MIME_TYPE%TYPE;
vDocSize discusdoctable.DOC_SIZE%TYPE;
vFileName discusdoctable.NAME%TYPE;

BEGIN
vFilePath := SUBSTR(owa_util.get_cgi_env('PATH_INFO'), 2);
vUserAgent := owa_util.get_cgi_env('HTTP_USER_AGENT');
IF INSTR(vUserAgent,'MSIE') != 0 THEN
-- IE (かなり無理矢理な対応)
-- IE6 - Version 6.0.290000.2180.xpsp_sp2_dgr.070227-2254 で動作確認!
-- 他のバージョンのIEではどうなるか未確認。。。
SELECT
SUBSTR(name, INSTR(name, '/')+1),
blob_content,
mime_type,
doc_size
INTO
vFileName,
vContentType,
vMimeType,
vDocSize
FROM
discusDocTable
WHERE
name = vFilePath;
OWA_UTIL.mime_header(vMimeType, FALSE);
HTP.p('Content-Length: ' || TO_CHAR(vDocSize));
HTP.p(
'Content-Disposition: attachment; filename=' || utl_url.escape(vFileName,false, 'AL32UTF8')
);
OWA_UTIL.http_header_close;
wpg_docload.download_file(vContentType);
ELSE
-- その他のブラウザ(MacOSX Safariでは日本語ファイル名のダウンロードは文字化けする)
wpg_docload.download_file(vFilePath);
END IF;
EXCEPTION
WHEN OTHERS THEN
htp.htmlopen;
htp.headopen;
htp.meta('Ccntent-Type',null,'text/html; charset=Shift_JIS');
htp.headclose;
htp.bodyopen;
htp.print('ダウンロードファイル:' || vFilePath);
htp.print('<strong style="color:#ff0000">' || sqlerrm() || '</strong>');
htp.bodyclose;
htp.htmlclose;
END fileDownloader;
/

IE6で日本語ファイル名のファイルをダウンロードしたスクリーンショット。
Ieok

| | コメント (0) | トラックバック (0)

2007年6月 4日 (月)

PL/SQL de File Upload / Download #3


Foundation - The Best of House, Vol 2 - Somebody's Watching Me Foundation - The Best of House, Vol 2 - Somebody's Watching Me


PL/SQL de File Upload / Download のつづきです。

前回は、プロシージャの実装まで行ったので実際にアップロードとダウンロードを行った結果を載せておく。


以下、MacOSXのSafariとFirefox2でファイルアップロードを行ったスクリーンショット

Modplsql3_1
Modplsql3_2
Modplsql3_3





OTN-J の Code Tipsでも公開されました。(2007/6/16更新)
http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2235
http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2236


5.ファイルアップロード後のドキュメント表の内容の例

(1)〜(4)のようなプロシージャを実装するだけで簡単にファイルアップロード/ダウンロードを行うWebアプリケーションを作成できる。
ただし、多少の癖はあるようですが。。。

尚、OPERATION#が等しいファイルは同一操作でアップロードされたことを意味する。今回、拡張した部分です!。想定通りうまくいきました。 (^^。

SCOTT> col name for a46
SCOTT> col content_type for a10
SCOTT> set linesize 132
SCOTT> set pagesize 1000
SCOTT> select name,content_type,doc_size,operation# from discusdoctable;

NAME CONTENT_TY DOC_SIZE OPERATION#
---------------------------------------------- ---------- ---------- ----------
F1416265333/DSC00002.JPG BLOB 32970 1
F462708383/CocoaAdvanced.zip BLOB 6189625 1
F701507294/Cocoaセミナー上級編.pdf BLOB 2673700 2
F622467197/MyQuickTimeMovieSoundTrack#3.m4a BLOB 663868 2
F1413335442/PLSQL_COLLECTION_sample.txt BLOB 15865 2
F612154227/ユーザの等価化.txt BLOB 1706 2
F1814846582/secondLife.jpg BLOB 231581 2
F621341128/ピクチャ 1.png BLOB 904551 3

8行が選択されました。

SCOTT>


まず、MacOSXの SafariとFirefoxで同じファイルをダウンロードしてみたのだが、ファイル名が日本語のファイルについては、Safariでダウンロードしたファイルのファイル名称は元のファイル名称とは異なりダウンロード元サーバのIPアドレスになっていた。(ホスト名を指定していればホスト名になっていただろう)。
また、Firefox(Mozillaでも)であればWindows/Linux上であっても文字化け等は発生しなかった。という結果であった。

Modplsql3_4

SafariとFirefoxで ピクチャ 1.pngというファイルを開いてたところなのだが、どちらもファイルは開けるものの、Safariではファイル名が192.168.1.19.pngとなっている。。
Modplsql3_5


Safariでも Cocoaセミナー上級編スライド.pdfをダウンロードしたのだが、ダウンロードされたファイル名は、192.168.1.19.pdfとなってしまった。FirefoxやMozillaでは問題ないんですが。。。

Modplsql3_6 Modplsql3_7

Modplsql3_8

初回にも書いたのだが、今回の環境は全てのレイヤーで文字コードはシフトJISにしてある。それがSafariの挙動に影響しているような・・・・・。
ということで、今日はここまで。 次回へつづく。

| | コメント (0) | トラックバック (0)

2007年6月 3日 (日)

PL/SQL de File Upload / Download #2


Ultravox - Vienna - ViennaUltravox - Vienna - Vienna

さて、環境が整ったのでプロシージャを作成する。
(今回はマニュアルに記載されているサンプルのようにそれぞれ独立したプロシージャとしたが、これらを纏めてパッケージ化しても問題ない。 私が仕事で依頼されたものならパッケージとして実装するでしょうね。)


OTN-J の Code Tipsでも公開されました。(2007/6/16更新) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2235 http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2236

4.ファイルアップロード/ダウンロードプロシージャの例

注)style属性のtext-shadowを利用していますが、MacOSXのSafari以外のブラウザではドロップシャドウ効果はありません。


URLの例)- hostnameが discus 、 portが 7780 である場合、以下のようなURLでアクセスする。
http://discus:7780/plsql_de_fileupload/fileuploadform


(1)ファイルを最大5件同時にアップロードするフォームを表示するプロシージャ。

参考:
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19260-01/concept.htm#i1005985
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19260-01/concept.htm#i1011204

CREATE OR REPLACE PROCEDURE fileUpLoadForm
IS
numOfFiles CONSTANT PLS_INTEGER := 5;
BEGIN
htp.htmlopen;
htp.headopen;
htp.meta('CONTENT-TYpe',null,'text/html; charset=Shift_JIS');
htp.title('PL/SQL de File Upload');
htp.headclose;

htp.bodyopen;
htp.centeropen;
htp.print('<div align="center" style="width:500; height:600">');
htp.STRONG(
cattributes=> 'style="font-size:24px; color:#ff0000; '
|| 'text-shadow:1px 2px 3px #7f7f7f"',
ctext=> 'PL/SQL de ファイルアップロード'
);
htp.prn('<br><br>');
htp.formopen(
cenctype=>'multipart/form-data',
curl=>'action',cmethod=>'POST'
);

FOR i IN 1..numOfFiles LOOP
htp.prn(
'<p><span style="text-shadow:1px 2px 3px #7f7f7f">ファイルの選択:</span>'
);
htp.formfile(cname=>'file');
htp.br;
END LOOP;
htp.prn('<br><br><p>');
htp.formsubmit(cattributes=>'align=right',cvalue=>'アップロード');

htp.formclose;
htp.print('</div>');
htp.centerclose;
htp.bodyclose;
htp.htmlclose;
END;
/


(2)<FORM>要素のaction属性に指定するプロシージャの例

下記サンプルコードでは、マニュアルに記載されているサンプルの他に、同一操作でアップロードされたファイルに対してシーケンスから採番した操作番号を設定する処理を追加している。

CREATE OR REPLACE PROCEDURE action
(
file IN owa_util.vc_arr
) IS
vOpe# number(10);
BEGIN
htp.htmlopen;
htp.meta('CONTENT-TYPE',null,'text/html; charset=Shift_JIS');
htp.headopen;
htp.title('PL/SQL de File Upload (Action)');
htp.headclose;
htp.bodyopen;
htp.header(1,'アップロード・ステータス');
htp.print('以下のアップロードが終了しました。<br><br>');
htp.prn('<span style="color:#ff0000; text-shadow:1px 2px 3px #7f7f7f">');
FOR i IN file.FIRST..file.LAST LOOP
IF FILE(i) IS NOT NULL THEN
htp.print('-&gt; ' || file(i) || '<br>');
END IF;
END LOOP;
htp.print('</span>');

-- 同一操作でアップロードしたファイルへ、同一操作番号を設定する。
SELECT upload_operation#.nextval INTO vOpe# FROM dual;
FOR i IN file.FIRST..file.LAST LOOP
UPDATE DISCUSDOCTABLE SET operation# = vOpe# WHERE name=file(i);
END LOOP;

htp.bodyclose;
htp.htmlclose;
END;
/


(3)ダウンロード可能なファイルリストを表示するプロシージャの例。

URLの例) - hostname = discus, port = 7780である場合。
http://discus:7780/plsql_de_fileupload/filelist

マニュアルに記載されているファイルダウンロードのサンプルは、同マニュアルに記載されている他のサンプルコードに比べ、少々不親切(端折り過ぎ)なサンプルコードになっている。(CGIなどのWebアプリケーションに慣れている方なら想像できなくもないのだが・・・・。)
下記サンプルコードを見れば容易に理解できると思うのだが、アップロードしたファイルをダウンロードするには、dads.confのPlsqlDocumentPathパラメータで指定したドキュメントルートのパスと、ドキュメント表のname列の値を連結したパスでダウンロードするファイル指すURLを生成できる。

CREATE OR REPLACE PROCEDURE fileList
IS
BEGIN
htp.htmlopen;
htp.headopen;
htp.meta('CONTENT-Type',null,'text/html; charset=Shift_JIS');
htp.title('PL/SQL de File upload - ダウンロード可能なファイル一覧');
htp.headclose;
htp.bodyopen;
htp.print(
'<span style="text-shadow:1px 2px 3px #7f7f7f; font-size: 22px">'
|| 'ダウンロードファイル一覧</span><br><br>'
);
FOR doc IN (SELECT name FROM discusDocTable) LOOP
htp.anchor('docs/' || utl_url.escape(doc.name, false, 'Shift_JIS'), 'docs/' || doc.name);
htp.br;
END LOOP;
htp.bodyclose;
htp.htmlclose;
END;
/

(4)ファイルのダウンロード時にmod_plsqlから呼び出されるプロシージャの例。

このプロシージャは、(3)の方法でダウンロードする場合には必須であり、dads.confのPlsqlDocumentProcedureパラメータで指定する。
このプロシージャのサンプルコードはマニュアルにも記載されているのだが少々難解ですね。
実際には、以下のように wpg_docload.download_file()プロシージャを実行するだけの処理なのだがマニュアルのサンプルコードを見ると少々混乱してしまう! 私も少々考えましたもん!!!

以下コードを見てもらうと実は非常にシンプルな操作であることに気付くと思う。 解説するまでも無いと思うが念のために解説しておくと、wpg_docload.download_file(環境変数PATH_INFOの値)を実行しているだけなのである。

CREATE OR REPLACE PROCEDURE fileDownloader
IS
vFilePath VARCHAR2(256);
BEGIN
vFilePath := SUBSTR(owa_util.get_cgi_env('PATH_INFO'), 2);
wpg_docload.download_file(vFilePath);
EXCEPTION
WHEN OTHERS THEN
htp.htmlopen;
htp.headopen;
htp.meta('Ccntent-Type',null,'text/html; charset=Shift_JIS');
htp.headclose;
htp.bodyopen;
htp.print('ダウンロードファイル:' || vFilePath);
htp.print('<strong style="color:#ff0000">' || sqlerrm() || '</strong>');
htp.bodyclose;
htp.htmlclose;
END fileDownloader;
/


以上でプロシージャの作成は終わり。 簡単ですよね!。 

次回へつづく。

| | コメント (0) | トラックバック (0)

2007年6月 1日 (金)

PL/SQL de File Upload / Download #1

先日、OTN-Jでmod_plsqlが提供するファイルアップロード/ダウンロードフレームワークに関連するスレッドがあり、その中でのやり取りと、作成したサンプルコードに多少手を加えて公開しておく。
ファイルダウンロード及び、ドキュメント表の拡張方法など明確な解説が無いこともあり、一部マニュアルの行間を読みつつ試した結果を含む。
(OTN-JのCodeTipsへも投稿する予定)
http://otn.oracle.co.jp/forum/message.jspa?messageID=35011699&tstart=0


mod_plsqlのファイルアップロード/ダウンロードに関する詳細は、下記ドキュメント参照のこと。
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19260-01/concept.htm#i1009257
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19260-01/concept.htm#i1005866


※ファイルアップロード/ダウンロードサンプルの概要

・複数のファイル(この例では最大5件)を1操作でアップロードする。
・同一操作でアップロードされた複数のファイルは、同一の操作番号(OPERATION#)を
 設定する。

※環境

HTTP Servetとデータベースは同ーサーバ上に構築。(尚、$ORACLE_HOMEは別にしてインストールする必要がある。)
尚、今回はWindows XP Professional上に構築し、Oracle SQL Developer for MacOSXを利用してプロシージャを作成した。

・サーバ

・Oracle10g HTTP Server (Apache Standalone 10.1.2.0.0)
  - Oracle Database 10g Compaion CD Release 1 (10.1.0.3.0)
・Oracle10g Database R1 EE
  - Oracle Database 10g Release 1 (10.1.0.3.0)
  - データベースキャラクタセット: JA16SJISTILDE
・OWA - 10.1.2.0.6

・クライアント(ブラウザ)

・Safari 2 - MacOSX 10.4.9
・Opera 9.2 - MacOSX 10.4.9
・FireFox 2 - MacOSX 10.4.9
・Firefox 2 - Linux (TurboLinux 8 - powered by United Linux1.0)
・FireFox 2 - Linux (CentOS 4.4)
・IE6 - Windows XP Professional
・FireFox 2 - Windows XP Professional


OTN-J の Code Tipsでも公開されました。(2007/6/16更新) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2235 http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2236

1.ドキュメント表の定義

ドキュメント表で定義する必要のある列に加て、OPERATION#という列を追加した。
尚、アップロードするコンテンツはすべて BLOB列へ格納する。
(同一操作でアップロードされたファイルに同一操作番号を設定する為に利用する。)
SCOTT> desc discusdoctable
名前 NULL? 型
----------------------------------------- -------- ----------------------------
NAME NOT NULL VARCHAR2(128)
MIME_TYPE VARCHAR2(128)
DOC_SIZE NUMBER
DAD_CHARSET VARCHAR2(128)
LAST_UPDATED DATE
CONTENT_TYPE VARCHAR2(128)
BLOB_CONTENT BLOB
OPERATION# NUMBER(10)

SCOTT>

2.操作番号を取得するシーケンスの定義

CREATE SEQUENCE UPLOAD_OPERATION#  
MINVALUE 1 MAXVALUE 9999999999
INCREMENT BY 1 START WITH 1
NOCACHE NOORDER NOCYCLE;

3.dads.confの定義

dads.confに関連するマニュアルは以下の通り。
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19260-01/concept.htm#i1012038
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19260-01/concept.htm#i1011190
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19260-01/concept.htm#i1010512

# ============================================================================ 
# mod_plsql DAD Configuration File
# ============================================================================
# 1. Please refer to dads.README for a description of this file
# ============================================================================

# Note: This file should typically be included in your plsql.conf file with
# the "include" directive.

# Hint: You can look at some sample DADs in the dads.README file

# ============================================================================
<Location /plsql_de_fileupload>
SetHandler pls_handler
Order deny,allow
Allow from all
AllowOverride None
PlsqlDatabaseUsername scott
PlsqlDatabasePassword tiger
PlsqlDatabaseConnectString 192.168.1.19:1521:amazon
PlsqlAuthenticationMode Basic
PlsqlDefaultPage scott.fileUploadForm
PlsqlDocumentTablename scott.discusDocTable
PlsqlDocumentPath docs
PlsqlDocumentProcedure scott.fileDownloader
PlsqlNLSLanguage JAPANESE_JAPAN.JA16SJISTILDE
</Location>


環境、構成ファイル、ドキュメント表及び、その拡張部分の定義はこれで終了。次回へつづく。
Making1

| | コメント (0) | トラックバック (0)

2007年5月29日 (火)

Mac De Oracle : PL/SQL de Collection #4

さて、PL/SQLのコレクションでのお遊び。その4回目。

今回は、既に要素を持っているコレクションを空にしてみましょう。

第二回目にも似たようなことをやっているので、VarrayとNested Tableについては想像できると思いますが、Associative Arrayにいてはどうすればよいでしょう?

ということで、答えは以下のコードを読めば分かりますよ!

create or replace
PROCEDURE COLLECTIONS AS
TYPE VarrayType IS VARRAY(100) OF empType;
TYPE NestedTableType IS TABLE OF empType;
TYPE StrAssociativeArrayType IS TABLE OF empType INDEX BY VARCHAR2(50);
TYPE NumAssociativeArrayType IS TABLE OF empType INDEX BY BINARY_INTEGER;

myVarray VarrayType := VarrayType();
myNestedTable NestedTableType := NestedTableType();
myStrAssociativeArray StrAssociativeArrayType;
myNumAssociativeArray NumAssociativeArrayType;

claerMyStrAssociateArray StrAssociativeArrayType;
clearMyNumAssociateArray NumAssociativeArrayType;

myEmp empType;

CURSOR csrEmp IS
SELECT
job,
empno,
ename,
hiredate,
sal,
deptno
FROM
emp
ORDER BY
empno;

PROCEDURE printCount
IS
BEGIN
DBMS_OUTPUT.PUT_LINE(
'Varray : '
|| myVarray.COUNT
|| ' 件の要素が存在します。'
);
DBMS_OUTPUT.PUT_LINE(
'Nested Table : '
|| myNestedTable.COUNT
|| ' 件の要素が存在します。'
);
DBMS_OUTPUT.PUT_LINE(
'Associative Array(String) :'
|| myStrAssociativeArray.COUNT
|| ' 件の要素が存在します。'
);
DBMS_OUTPUT.PUT_LINE(
'Associative Array(Number) :'
|| myNumAssociativeArray.COUNT
|| ' 件の要素が存在します。'
);
END;

BEGIN
FOR emp_rec IN csrEmp LOOP
myEmp := empType (
emp_rec.empno,
emp_rec.ename,
emp_rec.job,
emp_rec.hiredate,
emp_rec.sal,
emp_rec.deptno
);
myVarray.EXTEND(1);
myVarray(myVarray.COUNT) := myEmp;
myNestedTable.EXTEND(1);
myNestedTable(myNestedTable.COUNT) := myEmp;
myStrAssociativeArray(TO_CHAR(myEmp.empno) || ':' || myEmp.ename) := myEmp;
myNumAssociativeArray(myEmp.empno) := myEmp;
END LOOP;


DBMS_OUTPUT.PUT_LINE('**** コレクションに要素が存在している状態 ****');
printCount;


myVarray := VarrayType();
myNestedTable := NestedTableType();
myStrAssociativeArray := claerMyStrAssociateArray;
myNumAssociativeArray := clearMyNumAssociateArray;

DBMS_OUTPUT.NEW_LINE;
DBMS_OUTPUT.PUT_LINE('**** コレクションが空の状態 ****');
printCount;


END;
/


上記のコードの通り、Assciative Array(結合配列)を空にする方法は、同じ型の”空”結合配列をセットしてやればいいわけです。
今回の例では1次元の結合配列ですが、N次元の結合配列でも考え方は同じです。(VarrayやNested Tableとは異なります。)
ちなみに、第二回目にも書きましたが、VarrayやNexted Tableは、NULLにすることができます。その場合、VarrayやNexted Tableは、atomic nullであるためコンストラクタによる初期化が行われるまで一切の操作は行えないということもお忘れなく。

最後に、上記プロシージャの実行結果。

SCOTT> set serveroutput on size 10000 format wrapped
SCOTT> exec collections;
**** コレクションに要素が存在している状態 ****
Varray : 29 件の要素が存在します。
Nested Table : 29 件の要素が存在します。
Associative Array(String) :29 件の要素が存在します。
Associative Array(Number) :29 件の要素が存在します。

**** コレクションが空の状態 ****
Varray : 0 件の要素が存在します。
Nested Table : 0 件の要素が存在します。
Associative Array(String) :0 件の要素が存在します。
Associative Array(Number) :0 件の要素が存在します。

PL/SQLプロシージャが正常に完了しました。

SCOTT>

Collection4

今日はこのへんで。

| | コメント (0) | トラックバック (0)

2007年5月27日 (日)

Mac De Oracle : PL/SQL de Collection #3

前回の続き

各コレクションの初期化の方法は見えたと思うので、今回は実際に要素をセットしたり取り出したりして遊んでみる。
最初にも書いたが今回セットするのはオブジェクト型。emp表をempno順に問い合せ、empType型として各コレクションの要素としてある。)

マニュアルなどを見ながらいろいろ試してみたほうが面白いと思うので特に解説はしません。。Enjoy!!

CREATE OR REPLACE
PROCEDURE COLLECTIONS AS
TYPE VarrayType IS VARRAY(100) OF empType;
TYPE NestedTableType IS TABLE OF empType;
TYPE StrAssociativeArrayType IS TABLE OF empType INDEX BY VARCHAR2(50);
TYPE NumAssociativeArrayType IS TABLE OF empType INDEX BY BINARY_INTEGER;

myVarray VarrayType := VarrayType();
myNestedTable NestedTableType := NestedTableType();
myStrAssociativeArray StrAssociativeArrayType;
myNumAssociativeArray NumAssociativeArrayType;

myEmp empType;
strIdx VARCHAR2(50);
numIdx PLS_INTEGER;

CURSOR csrEmp IS
SELECT
job,
empno,
ename,
hiredate,
sal,
deptno
FROM
emp
ORDER BY
empno;


BEGIN
FOR emp_rec IN csrEmp LOOP
myEmp := empType (
emp_rec.empno,
emp_rec.ename,
emp_rec.job,
emp_rec.hiredate,
emp_rec.sal,
emp_rec.deptno
);
myVarray.EXTEND(1);
myVarray(myVarray.COUNT) := myEmp;
myNestedTable.EXTEND(1);
myNestedTable(myNestedTable.COUNT) := myEmp;
myStrAssociativeArray(TO_CHAR(myEmp.empno) || ':' || myEmp.ename) := myEmp;
myNumAssociativeArray(myEmp.empno) := myEmp;
END LOOP;

DBMS_OUTPUT.PUT_LINE('**** VARRAY ****');
FOR j IN myVarray.FIRST..myVarray.LAST LOOP
DBMS_OUTPUT.PUT_LINE(
'myVarray(' || TO_CHAR(j) || ')=' || myVarray(j).TO_STRING()
);
END LOOP;

DBMS_OUTPUT.NEW_LINE();
DBMS_OUTPUT.PUT_LINE('**** NESTED TABLE ****');
FOR j IN myNestedTable.FIRST..myNestedTable.LAST LOOP
DBMS_OUTPUT.PUT_LINE(
'myNestedTable(' || TO_CHAR(j) || ')=' || myNestedTable(j).TO_STRING()
);
END LOOP;

DBMS_OUTPUT.NEW_LINE();
DBMS_OUTPUT.PUT_LINE('**** Associative Array (String) ****');
strIdx := myStrAssociativeArray.FIRST();
WHILE strIdx IS NOT NULL LOOP
DBMS_OUTPUT.PUT_LINE(
'myStrAssociativeArray(' || strIdx || ')=' || myStrAssociativeArray(strIdx).TO_STRING()
);
strIdx := myStrAssociativeArray.NEXT(strIdx);
END LOOP;

DBMS_OUTPUT.NEW_LINE();
DBMS_OUTPUT.PUT_LINE('**** Associative Array (Number) ****');
numIdx := myNumAssociativeArray.FIRST();
WHILE numIdx IS NOT NULL LOOP
DBMS_OUTPUT.PUT_LINE(
'myNumAssociativeArray(' || TO_CHAR(numIdx) || ')=' || myNumAssociativeArray(numIdx).TO_STRING()
);
numIdx := myNumAssociativeArray.NEXT(numIdx);
END LOOP;
END;
/

以下、SQL*Plusでの実行結果。
尚、SQL*Plusのset serveroutputコマンドのオプション format wrappedは覚えておくといいですよ。
このオプションの意味も特に解説はしません。 format wrappedがある場合と無い場合の違いはご自分で確認してみてください


SCOTT> set serveroutput on size 10000 format wrapped
SCOTT> exec collections;

**** VARRAY ****
myVarray(1)=7369,SMITH,CLERK,1980/12/17, 800.00,20
myVarray(2)=7499,ALLEN,SALESMAN,1981/02/20, 1600.00,30
myVarray(3)=7521,WARD,SALESMAN,1981/02/22, 1250.00,30
myVarray(4)=7566,JONES,MANAGER,1981/04/02, 2975.00,20
myVarray(5)=7654,MARTIN,SALESMAN,1981/09/28, 1250.00,30
myVarray(6)=7698,BLAKE,MANAGER,1981/05/01, 2850.00,30
myVarray(7)=7782,CLARK,MANAGER,1981/06/09, 2450.00,10
myVarray(8)=7788,SCOTT,ANALYST,1987/04/19, 3000.00,20
myVarray(9)=7839,KING,PRESIDENT,1981/11/17, 5000.00,10
myVarray(10)=7844,TURNER,SALESMAN,1981/09/08, 1500.00,30
myVarray(11)=7876,ADAMS,CLERK,1987/05/23, 1100.00,20
myVarray(12)=7900,JAMES,CLERK,1981/12/03, 950.00,30

**** NESTED TABLE ****
myNestedTable(1)=7369,SMITH,CLERK,1980/12/17, 800.00,20
myNestedTable(2)=7499,ALLEN,SALESMAN,1981/02/20, 1600.00,30
myNestedTable(3)=7521,WARD,SALESMAN,1981/02/22, 1250.00,30
myNestedTable(4)=7566,JONES,MANAGER,1981/04/02, 2975.00,20
myNestedTable(5)=7654,MARTIN,SALESMAN,1981/09/28, 1250.00,30
myNestedTable(6)=7698,BLAKE,MANAGER,1981/05/01, 2850.00,30
myNestedTable(7)=7782,CLARK,MANAGER,1981/06/09, 2450.00,10
myNestedTable(8)=7788,SCOTT,ANALYST,1987/04/19, 3000.00,20
myNestedTable(9)=7839,KING,PRESIDENT,1981/11/17, 5000.00,10
myNestedTable(10)=7844,TURNER,SALESMAN,1981/09/08, 1500.00,30
myNestedTable(11)=7876,ADAMS,CLERK,1987/05/23, 1100.00,20
myNestedTable(12)=7900,JAMES,CLERK,1981/12/03, 950.00,30

**** Associative Array (String) ****
myStrAssociativeArray(7369:SMITH)=7369,SMITH,CLERK,1980/12/17, 800.00,20
myStrAssociativeArray(7499:ALLEN)=7499,ALLEN,SALESMAN,1981/02/20, 1600.00,30
myStrAssociativeArray(7521:WARD)=7521,WARD,SALESMAN,1981/02/22, 1250.00,30
myStrAssociativeArray(7566:JONES)=7566,JONES,MANAGER,1981/04/02, 2975.00,20
myStrAssociativeArray(7654:MARTIN)=7654,MARTIN,SALESMAN,1981/09/28, 1250.00,30
myStrAssociativeArray(7698:BLAKE)=7698,BLAKE,MANAGER,1981/05/01, 2850.00,30
myStrAssociativeArray(7782:CLARK)=7782,CLARK,MANAGER,1981/06/09, 2450.00,10
myStrAssociativeArray(7788:SCOTT)=7788,SCOTT,ANALYST,1987/04/19, 3000.00,20
myStrAssociativeArray(7839:KING)=7839,KING,PRESIDENT,1981/11/17, 5000.00,10
myStrAssociativeArray(7844:TURNER)=7844,TURNER,SALESMAN,1981/09/08, 1500.00,30
myStrAssociativeArray(7876:ADAMS)=7876,ADAMS,CLERK,1987/05/23, 1100.00,20
myStrAssociativeArray(7900:JAMES)=7900,JAMES,CLERK,1981/12/03, 950.00,30

**** Associative Array (Number) ****
myNumAssociativeArray(7369)=7369,SMITH,CLERK,1980/12/17, 800.00,20
myNumAssociativeArray(7499)=7499,ALLEN,SALESMAN,1981/02/20, 1600.00,30
myNumAssociativeArray(7521)=7521,WARD,SALESMAN,1981/02/22, 1250.00,30
myNumAssociativeArray(7566)=7566,JONES,MANAGER,1981/04/02, 2975.00,20
myNumAssociativeArray(7654)=7654,MARTIN,SALESMAN,1981/09/28, 1250.00,30
myNumAssociativeArray(7698)=7698,BLAKE,MANAGER,1981/05/01, 2850.00,30
myNumAssociativeArray(7782)=7782,CLARK,MANAGER,1981/06/09, 2450.00,10
myNumAssociativeArray(7788)=7788,SCOTT,ANALYST,1987/04/19, 3000.00,20
myNumAssociativeArray(7839)=7839,KING,PRESIDENT,1981/11/17, 5000.00,10
myNumAssociativeArray(7844)=7844,TURNER,SALESMAN,1981/09/08, 1500.00,30
myNumAssociativeArray(7876)=7876,ADAMS,CLERK,1987/05/23, 1100.00,20
myNumAssociativeArray(7900)=7900,JAMES,CLERK,1981/12/03, 950.00,30

PL/SQLプロシージャが正常に完了しました。

SCOTT>

以下のスクリーンショットは、Oracle SQL Developerで上記プロシージャを作成、テストしているところ。
Collection3_sdev

今日はここまで。

| | コメント (0) | トラックバック (0)

2007年5月25日 (金)

Mac De Oracle : PL/SQL de Collection #2

PL/SQL de Collectionのつづきです。

VarrayとNested Tableを利用するには、まず最初に初期化する必要がある。(Associated Arrayでは、その必要はない。)
オブジェクト指向的だとインスタンスの作成と言ったほうが分かりやすいですかね。

以下、VarrayType型とNestedTableType型では、インスタンスを作成しないと、Javaで言うところのNull Pointer Exceptionが発生する。という例。
PL/SQLなのでNull Pointer Exceptionではなく、ORA-6531が発生するのですがね。
(私個人としては、ORA-6531より、ORA-2309: atomic NULL violation の方がストレートで分かりやすいんでない? なんて思う事しばしば。初めてNested Tableを使おうとして、そのメッセージの意味が分からずハマったことも。。。)

SCOTT> l
1 DECLARE
2 -- VARRAY
3 TYPE VarrayType IS VARRAY(100) OF empType;
4 -- NESTED TABLE
5 TYPE NestedTableType IS TABLE OF empType;
6 -- ASSOCIATIVE ARRAY (formaly called PL/SQL TABLE)
7 TYPE StrAssociativeArrayType IS TABLE OF empType INDEX BY VARCHAR2(50);
8 TYPE NumAssociativeArrayType IS TABLE OF empType INDEX BY BINARY_INTEGER;
9
10 myVarray VarrayType;
11 myNestedTable NestedTableType;
12 myStrAssociativeArray StrAssociativeArrayType;
13 myNumAssociativeArray NumAssociativeArrayType;
14 BEGIN
15 DBMS_OUTPUT.PUT_LINE('Associative Array:' || myStrAssociativeArray.COUNT());
16
17 BEGIN
18 DBMS_OUTPUT.PUT_LINE('Varray:' || myVarray.COUNT());
19 EXCEPTION
20 WHEN OTHERS THEN
21 DBMS_OUTPUT.PUT_LINE('Varray: ' || SQLERRM());
22 END;
23
24 BEGIN
25 DBMS_OUTPUT.PUT_LINE('Nested Table:' || myNestedTable.COUNT());
26 EXCEPTION
27 WHEN OTHERS THEN
28 DBMS_OUTPUT.PUT_LINE('Nested Table:' || SQLERRM());
29 END;
30* END;
SCOTT> /
Associative Array:0
Varray: ORA-06531: 参照しているコレクションは初期化されていません。
Nested Table:ORA-06531: 参照しているコレクションは初期化されていません。

PL/SQLプロシージャが正常に完了しました。

SCOTT>


ちなみに、Associative Arrayは、atomic nullには出来ない。やってみれば分かると思いますが、コンパイルエラーになります。
なのでこの点については、コンパイラから注意されるので特に問題はないでしょうね。

SCOTT> l
1 DECLARE
2 -- VARRAY
3 TYPE VarrayType IS VARRAY(100) OF empType;
4 -- NESTED TABLE
5 TYPE NestedTableType IS TABLE OF empType;
6 -- ASSOCIATIVE ARRAY (formaly called PL/SQL TABLE)
7 TYPE StrAssociativeArrayType IS TABLE OF empType INDEX BY VARCHAR2(50);
8 TYPE NumAssociativeArrayType IS TABLE OF empType INDEX BY BINARY_INTEGER;
9
10 myVarray VarrayType;
11 myNestedTable NestedTableType;
12 myStrAssociativeArray StrAssociativeArrayType;
13 myNumAssociativeArray NumAssociativeArrayType;
14 BEGIN
15 myStrAssociativeArray := NULL;
16 DBMS_OUTPUT.PUT_LINE('Associative Array:' || myStrAssociativeArray.COUNT());
17
18 myVarray := NULL;
19 BEGIN
20 DBMS_OUTPUT.PUT_LINE('Varray:' || myVarray.COUNT());
21 EXCEPTION
22 WHEN OTHERS THEN
23 DBMS_OUTPUT.PUT_LINE('Varray: ' || SQLERRM());
24 END;
25
26 myNestedTable := NULL;
27 BEGIN
28 DBMS_OUTPUT.PUT_LINE('Nested Table:' || myNestedTable.COUNT());
29 EXCEPTION
30 WHEN OTHERS THEN
31 DBMS_OUTPUT.PUT_LINE('Nested Table:' || SQLERRM());
32 END;
33* END;
SCOTT> /
myStrAssociativeArray := NULL;
*
行14でエラーが発生しました。:
ORA-06550: 行15、列28:
PLS-00382: 式の型が正しくありません。
ORA-06550: 行15、列3:
PL/SQL: Statement ignored


SCOTT>


VarrayやNested Tableを利用する際には、事前にコンストラクタを実行して初期化しておく必要がありますが、実行時エラーの危険を避けるため、定義時に初期化しておく方が無難でしょう。
以下の例では、各変数の宣言時にコンストラクタであるVarrayType()や、NestedTableType()を実行し初期化しています。

SCOTT> l
1 DECLARE
2 -- VARRAY
3 TYPE VarrayType IS VARRAY(100) OF empType;
4 -- NESTED TABLE
5 TYPE NestedTableType IS TABLE OF empType;
6 -- ASSOCIATIVE ARRAY (formaly called PL/SQL TABLE)
7 TYPE StrAssociativeArrayType IS TABLE OF empType INDEX BY VARCHAR2(50);
8 TYPE NumAssociativeArrayType IS TABLE OF empType INDEX BY BINARY_INTEGER;
9
10 myVarray VarrayType := VarrayType();
11 myNestedTable NestedTableType := NestedTableType();
12 myStrAssociativeArray StrAssociativeArrayType;
13 myNumAssociativeArray NumAssociativeArrayType;
14 BEGIN
15 DBMS_OUTPUT.PUT_LINE('Associative Array:' || myStrAssociativeArray.COUNT());
16 DBMS_OUTPUT.PUT_LINE('Varray:' || myVarray.COUNT());
17 DBMS_OUTPUT.PUT_LINE('Nested Table:' || myNestedTable.COUNT());
18* END;
SCOTT> /
Associative Array:0
Varray:0
Nested Table:0

PL/SQLプロシージャが正常に完了しました。

SCOTT>

こんどは問題なく要素数を表示できましたね。 この時点で、Associative Array、Varray、Nested Tableの各コレクションは空の状態。

尚、上記の例では、いきなりコレクションのメソッド (COUNT)を使っているが、コレクションで利用できるメソッドは以下のマニュアルで確認できる。
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/appdev.102/B19257-01/langelems.html#6420

ということで、今日はここまで。

Oracleのオブジェクトに関しては、
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/appdev.102/B19256-01/adobjint.htm#sthref39を中心に読めばそれなりに理解できるかと。

| | コメント (0) | トラックバック (0)

2007年5月22日 (火)

Mac De Oracle : PL/SQL de Collection #1

最近のOracle Master試験は、PL/SQLは試験範囲に含まれていないわけですが、Oracleの開発や運用管理でもPL/SQLを利用する場面は少なく無いと思います。
(Mac De OracleでもPL/SQL関連ネタは多いです。)

Oracleデータベースありきですけが、Webアプリケーションからバッチ処理、さらに、運用管理、移行時など、PL/SQLは利用範囲が意外と広いのです。

ところで、
ブログの検索キーワードで、ORA-20000〜ORA-20999に次いで多いのが、実は、PL/SQLネタ。
Oracle Master試験の対象外になったことが影響しているんでしょうかねぇ?
Oracle Masterだからといっても、PL/SQLを使いこなせるとは限らない? という状況になりつつあるなんて話もちらほら。 少々心配です。

ということで、PL/SQLの Collectionについて少し書いてみるか! と思った次第。


では、早速。。。

PL/SQLで扱えるコレクションは、

・Associative Array
・Nested Table
・Varray

の3種。


・Associative Array


結合配列(索引付き配列と呼ばれたり、以前はPL/SQL表とも呼ばれていました。)これだけ日本語で書いてもイメージできないですよね。おそらく。
Javaをやっている方には、HashTableみたいな〜〜。とか、Perlをやっている方には連想配列みたいな〜。とか説明すること、「あ〜〜〜! なるほど。」とイメージできるようですね。(〜みたいな〜〜、なんですけどね。)

・Nested Table

Oracleが、Object Relational Database (ORDB)へと進化した際(Oracle8だったか?!)に登場したのコレクションの一つが、このNested Table(ネスト表)。このNested Tableは、Associate Arrayとは異なり、データベースへ格納することも可能。
また、PL/SQLで利用する場合、Associative Arrayとは異なり、事前に初期化しておく必要がある。
初期化って何? ということになりますが、要するにインスタンスを作成しておいてね。ってことになりますね。(詳細は簡単な例も含めて別エントリにて。)
#マニュアルには「初期化」と書いてあるので、そのまま使っています。

・Varray

Oracleが、Object Relational Database (ORDB)へと進化した際に登場したもう一つのコレクションがこのVarray。
事前に要素数が分かっている場合に利用することが多い。データベースに格納することができるが、更新する際にはコレクション全体を更新する必要がある。
PL/SQLで利用するには、Nested Table同様、事前に初期化しておく必要がある。

メモリを食らいつくすくらい巨大なコレクションを作る方も居たりして。。。。
限度はあるよ何事も。。。。。 (^^;;;

PL/SQLのコレクションに関するマニュアルは以下
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/appdev.102/B19257-01/collections.html#740

ということで、今回は準備だけ。

Object Relationalな部分にもちょっとだけ足を踏み込む次いでに、Collectionに格納する要素もオブジェクト型にしておきましょう。

以下のようにempType型を定義し、TO_STRING() メンバーファンクション(Java等では、メソッド相当)を定義しておく。
(見ての通り、 empTypeの値をCSV形式の文字列にするファンクション。)

ちなみに、デフォルトコンストラクタをオーバーライドしたり、コンストラクタを追加することもできますよ。(簡単な例は別エントリにて)

create or replace TYPE empType AS OBJECT
(
empno NUMBER(4),
ename VARCHAR2(10, BYTE),
job VARCHAR2(9, BYTE),
hiredate DATE,
sal NUMBER(7,2),
deptno NUMBER(2),
MEMBER FUNCTION TO_STRING RETURN VARCHAR2
);
/
create or replace TYPE BODY empType AS
MEMBER FUNCTION TO_STRING
RETURN VARCHAR2 IS
BEGIN
RETURN
TO_CHAR(SELF.empno) ||','||
SELF.ename ||','||
SELF.job ||','||
TO_CHAR(SELF.hiredate, 'YYYY/MM/DD') ||','||
TO_CHAR(SELF.sal, '99999.99') ||','||
TO_CHAR(SELF.deptno);
END;
END;
/


Prepare_collection_sample
今日はここまで。

| | コメント (0) | トラックバック (0)

2007年4月19日 (木)

DBマガジン2007年6月号

OTN-Jのこのスレッドでアナウンスされていますが、私がOTN-Jに投稿したCodeTips#1531(OTN-JのCodeTipsを参照するにはOTNにログインする必要があります。)が、月刊DBマガジン 6月号 (4/24発売)の OTN傑作選 Oracleデータベース Tipsで紹介されるとのこと。。

ちなみに、投稿したコードと Oracle SQL Developerを絡めたネタは、こちら。

思いつきで書いたコード及び方法ですが、どなたかのお役に立っているようですね。
選んでいただき、ありがとうございます。 --> OTN-Jシスオペ様。  m(_ _)m

| | コメント (0) | トラックバック (0)

2007年4月10日 (火)

Oracle SQL Developer #12

Oracle SQL Developer 1.1 Patch 1 (1.1.1.25.14) for MacOSX でと思ったが、Oracle SQL Developer 1.1 Patch 2 (1.1.2.25.79) for MacOSX が既にリリースされていたので最新版で、Oracle SQL Developerのデバッグ機能を試してみた。

http://www.oracle.com/technology/software/products/sql/index.html
尚、ダウンロードにはユーザ登録(無料)が必要。

リリースノートは以下。
http://www.oracle.com/technology/products/database/sql_developer/files/relnotes_v1.1.html

SQL Developer 1.1 Path 1(1.1.1.25.14) for MacOSXの時点で確認できていたので、ネタとしては少々鮮度が落ちるが、PL/SQLのデバッガ機能でハングが発生しなくなった。 
1.0か、1.1のころデバッグ機能を試した時は、デバッグモードで実行するとSQL Developerがハングしてしまい強制終了するしか無かったが、前回リリースされた Oracle SQL Developer 1.1 Patch 1 (1.1.1.25.14) for MacOSXで解決されていた。
これができるようになれば MacOSX上でもPL/SQLの開発が楽になりますね。

以下、Oracle10g R2 EE 10.2.0.2.0に接続してdebugしている画面のスナップショット。

Oraclesqldeveloper_debug

ちなみに、Oracle SQL Developerでデバッグ機能を利用するには、DEBUG CONNECT SESSION及び、DEBUG ANY PROCEDUREシステム権限が必要。もし実行するユーザが該当システム権限を付与されていない場合、以下のようなメッセージが返される。

Connecting to the database pleco.
Executing PL/SQL: ALTER SESSION SET PLSQL_DEBUG=TRUE
Executing PL/SQL: CALL DBMS_DEBUG_JDWP.CONNECT_TCP( '192.168.1.2', '53865' )
ORA-01031: 権限が不足しています。
ORA-06512: "SYS.DBMS_DEBUG_JDWP", 行68
ORA-06512: 行1
This session requires DEBUG CONNECT SESSION and DEBUG ANY PROCEDURE user privileges.
Process exited.
Disconnecting from the database pleco.

| | コメント (0) | トラックバック (0)

2007年4月 9日 (月)

ORA-20001

マニュアルにもしっかり記載されているが、意外に多いなぁと感じた検索ワードの ”ORA-20001”を取り上げておこうと思います。

ORA-20001 を エラーメッセージマニュアルで確認してみると、

ORA-20000: %s
原因:
このメッセージが発生する原因となったストアド・プロシージャraise_application_errorが呼び出されました。
処置:
エラー・メッセージの記述どおりに問題を修正するか、詳細をアプリケーション管理者またはDBAに問い合せてください。

と、少々、不親切な書き方になっています。

上記、エラーメッセージの解説からは、ORA-20001が、ORA-20000と同じ、ユーザ定義エラーとして予約されているエラーコードであるとは読み取れません。
(Oracleさん、もうちょっとだけ、親切なドキュメントに修正してくれるとありがたいのですが・・・・・)


PL/SQLに慣れた方なら、最初に、冒頭でリンクしているこのマニュアルを見る確立は高いでしょうが、そうで無い方は、ORA-20001というエラーコードを見て、最初に参照するマニュアルはエラーメッセージマニュアルであることの方が多いはず!。 

で、「マニュアルに記載されていない!」 ということになり、ハマるわけです。。。。ね。

前置きはこれくらいにして、本題。

Oracle Database PL/SQLユーザーズ・ガイドおよびリファレンス 10g リリース2(10.2)に書かれているように、ORA-20000からORA-20999は、ユーザが自由にメッセージを割り当てる事ができるように予約されているエラーコードだ。

つまり、ORA-20000 というエラーコードには、Oracle側では対応するエラーメッセージが割り当てられていない。
ユーザが自由にエラーメッセージを割当て意味を持たせることができるエラーコードなんですよ。

たとえば、プロシージャAでは、ORA-20000は、「URLが指定されていません。」というエラーメッセージを割り当てたり、ファンクションBでは、ORA-20001には「指定された予約がありません。」というメッセージを割り当てることができるわけです。


尚、ORA-20000からORA-20999までのエラーコードはユーザが自由に設定できるエラーコードであるため、ほとんどの場合、プロジェクト毎に標準化されることが多いと思います。理由は、ORA-20000からORA-20999のエラーコードに対して一意にエラーメッセージを割り当て、1つのエラーコードが複数の意味を持たないようにするためです。
私が関わったプロジェクトでは、台帳で一元管理し、リリース後は該当システム独自のエラーメッセージマニュアルとしても利用させました。

サンプルコードは、Oracle Database PL/SQLユーザーズ・ガイドおよびリファレンス 10g リリース2(10.2)にもあるのでそちらも参照してください。

以下、簡単なサンプル。。。と行きたいところだがここまで。
(後日、このエントリを更新してサンプルを載せるかも。。。マニュアルに記載されているから追記しないかも。。。。気分次第です。)

| | コメント (0) | トラックバック (0)

2007年4月 2日 (月)

Mac De PL/SQL RSS Reader #33 (XSLT編 #5)

さて、前回からのつづき。

●プロシージャのソースです。

HTMLで表示しているため以下のソースをそのままコピー/ペーストするとコンパイルエラーなど不都合が発生することがあるかもしれませんので、ソースを利用される場合は、XSLTスタイルシートも含め、こちらからダウンロードしたソースをお使いください。 source.zip (3.9K)

CREATE OR REPLACE 
PROCEDURE RSS_READER_XSLT
(
i_feedXmlUrl IN VARCHAR2,
i_feedXmlCharset IN VARCHAR2,
i_styleSheetDir IN VARCHAR2,
i_styleSheetName IN VARCHAR2,
DEBUG_ IN BOOLEAN DEFAULT FALSE
)
AS
--===========================================================
rss_reader_xslt.sql : 2007/3/26 - Mac De Oracle
http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/
--============ ===============================================

--============ TYPEs/VARIABLEs ===============================================
XSL_CHARSET_ CONSTANT VARCHAR(30) := 'UTF8';
v_feedXmlUrl VARCHAR2(32767);
v_feedXmlCharset VARCHAR2(30);
v_styleSheetDir VARCHAR2(30);
v_styleSheetName VARCHAR2(100);

myParser DBMS_XMLPARSER.Parser;
v_feedDoc DBMS_XMLDOM.DomDocument;
v_feedSourceClob CLOB;

myProcessor DBMS_XSLPROCESSOR.Processor;
v_xsl DBMS_XSLPROCESSOR.StyleSheet;
v_xslDoc DBMS_XMLDOM.DomDocument;
v_xslSourceClob CLOB;
v_xslDocFragment DBMS_XMLDOM.DomdocumentFragment;
v_transformedDoc DBMS_XMLDOM.DomNode;

v_clobbuffer CLOB;

--========== Internal PROCEDUREs/FUNCTIONs ===================================
PROCEDURE getXMLSource(
i_url IN VARCHAR2,
i_charset IN VARCHAR2 DEFAULT 'UTF-8',
io_sourceClob IN OUT NOCOPY CLOB
)
IS
v_httpReq UTL_HTTP.REQ;
v_httpResp UTL_HTTP.RESP;
v_xmlSource VARCHAR2(1024);
BEGIN
v_httpReq := UTL_HTTP.BEGIN_REQUEST(i_url);
UTL_HTTP.SET_HEADER(
v_httpReq,
'User-Agent',
'Oracle UTL_HTTP/Oracle10g R1;'
);

UTL_HTTP.SET_HEADER(
v_httpReq,
'Content-Type',
'text/xml;charset='||i_charset
);

v_httpResp := UTL_HTTP.GET_RESPONSE(v_httpReq);
DBMS_LOB.CREATETEMPORARY(io_sourceClob, FALSE);
BEGIN
LOOP
UTL_HTTP.READ_LINE(v_httpResp, v_xmlSource, true);
v_xmlSource := v_xmlSource || UTL_TCP.CRLF;
DBMS_LOB.WRITEAPPEND(
io_sourceClob,
LENGTH(v_xmlSource),
v_xmlSource
);
END LOOP;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(v_httpResp);
END;
END getXMLSource;

PROCEDURE drawFeedEntries(
i_buffer IN CLOB
)
IS
chunkSize_ CONSTANT PLS_INTEGER := 10922;
v_numOfChunk PLS_INTEGER;
v_src CLOB;
v_tempStr VARCHAR2(32767);
BEGIN
v_src := i_buffer;
FOR chunk# IN 0..CEIL(DBMS_LOB.GETLENGTH(v_src) / chunkSize_) LOOP
v_tempStr := SUBSTR(i_buffer, (chunk#*chunkSize_)+1, chunkSize_);
HTP.PRN(v_tempStr);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'Error Occured : rss_reader_xslt.drawFeedEntries(CLOB).'
);
DBMS_OUTPUT.PUT_LINE(sqlerrm());
RAISE;

END drawFeedEntries;

-- for DEBUG
PROCEDURE pl(text IN CLOB)
IS
BEGIN
IF length(text)> 80 THEN
FOR i IN 1..(trunc(length(text)/80)+1) LOOP
dbms_output.put_line(substr(text,1+ 80*(i-1),80));
END LOOP;
ELSE
dbms_output.put_line(text);
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error occured : pl(VARCHAR2).');
RAISE;
END pl;

--
--
--****************************************************************************
-- Main
--****************************************************************************
BEGIN

v_feedXmlUrl := i_feedXmlUrl;
v_feedXmlCharset := i_feedXmlCharset;
v_styleSheetDir := UPPER(i_styleSheetDir);
v_styleSheetName := i_styleSheetName;

IF v_feedXmlUrl IS NULL THEN
RAISE_APPLICATION_ERROR(-20000, 'FEEDのURLを指定してください。');
END IF;
IF v_styleSheetDir IS NULL THEN
RAISE_APPLICATION_ERROR(
-20001,
'XSLTスタイルシートが保存されているディレクトリを指定してください。'
);
END IF;
IF v_styleSheetName IS NULL THEN
RAISE_APPLICATION_ERROR(-20002, 'XSLTスタイルシート名を指定してください。');
END IF;

-- RSS FEEDの取得する
getXMLSource(
i_url => v_feedXmlUrl,
i_charset => v_feedXmlCharset,
io_sourceClob => v_feedSourceClob
);
myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSECLOB(myParser, v_feedSourceClob);
v_feedDoc := DBMS_XMLPARSER.GETDOCUMENT(myParser);

-- XSLTスタイルシートを読み込む
v_xslSourceClob := DBMS_XSLPROCESSOR.READ2CLOB(
v_styleSheetDir,
v_styleSheetName,
NLS_CHARSET_ID(XSL_CHARSET_)
);
DBMS_XMLPARSER.PARSECLOB(myParser, v_xslSourceClob);
v_xslDoc := DBMS_XMLPARSER.GETDOCUMENT(myParser);
v_xsl := DBMS_XSLPROCESSOR.NEWSTYLESHEET(v_xslDoc, NULL);

-- DOMにXSLTスタイルシートを適用する
myProcessor := DBMS_XSLPROCESSOR.NEWPROCESSOR();
v_xslDocFragment := DBMS_XSLPROCESSOR.PROCESSXSL(
myProcessor,
v_xsl,
v_feedDoc
);
v_transformedDoc := DBMS_XMLDOM.MAKENODE(v_xslDocFragment);
DBMS_LOB.CREATETEMPORARY(v_clobbuffer, FALSE);
DBMS_XMLDOM.WRITETOCLOB(v_transformedDoc, v_clobbuffer);

-- 変換後のHTMLを出力する
IF DEBUG_ THEN
pl(v_clobbuffer);
ELSE
drawFeedEntries(v_clobbuffer);
END IF;

DBMS_LOB.FREETEMPORARY(v_feedSourceClob);
DBMS_LOB.FREETEMPORARY(v_xslSourceClob);
DBMS_LOB.FREETEMPORARY(v_clobbuffer);
DBMS_XSLPROCESSOR.FREESTYLESHEET(v_xsl);
DBMS_XMLDOM.FREEDOCUMENT(v_feedDoc);
DBMS_XMLDOM.FREEDOCUMENT(v_xslDoc);
DBMS_XMLPARSER.FREEPARSER(myParser);
DBMS_XSLPROCESSOR.FREEPROCESSOR(myProcessor);

EXCEPTION
WHEN OTHERS THEN
IF v_feedSourceClob IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(v_feedSourceClob);
END IF;
IF v_xslSourceClob IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(v_xslSourceClob);
END IF;
IF v_clobbuffer IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(v_clobbuffer);
END IF;
DBMS_XSLPROCESSOR.FREESTYLESHEET(v_xsl);
DBMS_XMLDOM.FREEDOCUMENT(v_feedDoc);
DBMS_XMLDOM.FREEDOCUMENT(v_xslDoc);
DBMS_XMLPARSER.FREEPARSER(myParser);
DBMS_XSLPROCESSOR.FREEPROCESSOR(myProcessor);

IF DEBUG_ THEN
DBMS_OUTPUT.PUT_LINE('RSS Reader error:'||SQLERRM());
ELSE
HTP.TABLEOPEN();
HTP.TABLEROWOPEN();
HTP.TABLEHEADER('RSS Reader error:'||SQLERRM());
HTP.TABLEROWCLOSE();
HTP.TABLECLOSE();
END IF;
END RSS_READER_XSLT;
/


このサンプルは OTN-Jの CodeTipsでも公開しています。

(1/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2135
(2/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2137
(3/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2138

| | コメント (0) | トラックバック (0)

2007年4月 1日 (日)

Mac De PL/SQL RSS Reader #32 (XSLT編 #4)

つづきです。

XSLTスタイルシートに関して細かく解説するつもりはありませんが、少しだけ解説しておくと。

RSS 0.91/RSS 0.92/ RDF(RSS)1.0ATOM 0.3 / ATOM 1.0の FEEDからタイトルと元ネタへのリンク、各エントリ毎の要約とリンク、そして、存在してれば、[エントリの作成日]を抜き出してHTMLへ変換している。
尚、OTN-JRSS2.0で配信されているが 各エントリには、<pubDate>要素や、<dc:date>要素は存在せず、拡張された<jf:creationDate>要素に作成日を持っているようなので、<jf:creationDate>要素を処理している。

XSLTについては、@ITの記事などや、検索すれば沢山ヒットするので理解できる範囲かと。。。
(難しいことはやってないですから。)
http://www.atmarkit.co.jp/fxml/tanpatsu/xslt/xslt04.html
http://www.atmarkit.co.jp/fxml/tanpatsu/xslt/xslt10.html

尚、DBMS_XSLPROCESSORパッケージなどは、
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/appdev.102/B19245-01/d_xslpro.htmを参照のこと。

簡単な解説はこれぐらいにして、以下、XSLTスタイルシートのソース。
#1時間くらいで作ったものなので、バグが無いとは言えません。あしからず。
#ちなみに、私が読んでいるFEEDでは特に問題は発生していません。

但し、こんな問題もあり2月に入ってからDTDが開けないエラーが発生している。大抵、他の形式でも配布しているからRSS0.91使わなきゃいいだけかも。。

尚、今回作成したXSLTスタイルシートとPL/SQLのソースコードは、こちらからダウンロードできます。 source.zip (3.9K)

<?xml version="1.0" encoding="utf-8"?>
<!-- ===================================================================
rss2html.xsl : 2007/3/26 - Mac De Oracle
http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/
==================================================================== -->
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rss10="http://purl.org/rss/1.0/"
xmlns:atom03="http://purl.org/atom/ns#"
xmlns:atom10="http://www.w3.org/2005/Atom"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:jf="http://www.jivesoftware.com/xmlns/jiveforums/rss"
>


<xsl:output method="html" encoding="utf-8" />
<xsl:template match="/">
<table border="0" cellpadding="0" cellspacing="2">
<tr>
<th>
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:apply-templates select="//rdf:RDF/rss10:channel/rss10:link"/>
<xsl:apply-templates select="//atom03:feed/atom03:link/@href"/>
<xsl:apply-templates select="//atom10:feed/atom10:link/@href"/>
<xsl:apply-templates select="//rss/channel/link"/>
</xsl:attribute>
<xsl:apply-templates select="//rdf:RDF/rss10:channel/rss10:title"/>
<xsl:apply-templates select="//atom03:feed/atom03:title"/>
<xsl:apply-templates select="//atom10:feed/atom10:title"/>
<xsl:apply-templates select="//rss/channel/title"/>
</xsl:element>
</th>
</tr>
<xsl:apply-templates select="//rdf:RDF/rss10:item" mode="normal"/>
<xsl:apply-templates select="//atom03:feed/atom03:entry" mode="normal"/>
<xsl:apply-templates select="//atom10:feed/atom10:entry" mode="normal"/>
<xsl:apply-templates select="//rss/channel/item" mode="normal"/>
</table>
</xsl:template>


<!-- RDF/RSS1.0 template -->
<xsl:template match="rss10:item" mode="normal">
<tr>
<td valign="top">
<xsl:element name="a">
<xsl:attribute name="href"><xsl:value-of select="rss10:link"/></xsl:attribute>
<xsl:attribute name="title"><xsl:value-of select="rss10:link"/></xsl:attribute>
<xsl:attribute name="style">color:#FF0000</xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
<xsl:value-of select="concat(rss10:title, ' - 続きを読む...')" />
</xsl:element>
<xsl:choose>
<xsl:when test="dc:date">
<xsl:value-of select="concat(' - ', substring-before(dc:date,'T'))"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</td>
</tr>
</xsl:template>

<xsl:template match="//rdf:RDF/rss10:channel/rss10:title">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="//rdf:RDF/rss10:channel/rss10:link">
<xsl:value-of select="."/>
</xsl:template>


<!-- ATOM 1.0 template -->
<xsl:template match="//atom10:feed/atom10:entry" mode="normal">
<tr>
<td valign="top">
<xsl:element name="a">
<xsl:attribute name="href"><xsl:value-of select="atom10:link/@href"/></xsl:attribute>
<xsl:attribute name="title"><xsl:value-of select="atom10:summary"/></xsl:attribute>
<xsl:attribute name="style">color:#FF0000</xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
<xsl:value-of select="concat(atom10:title,' - 続きを読む...')"/>
</xsl:element>
<xsl:choose>
<xsl:when test="atom10:published">
<xsl:value-of select="concat(' - ',substring-before(atom10:published,'T'))"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</td>
</tr>
</xsl:template>

<xsl:template match="//atom10:feed/atom10:title">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="//atom10:feed/atom10:link/@href">
<xsl:if test="../@rel = 'alternate'">
<xsl:if test="../@type = 'text/html'">
<xsl:value-of select="."/>
</xsl:if>
</xsl:if>
</xsl:template>


<!-- ATOM 0.3 template -->
<xsl:template match="//atom03:feed/atom03:entry" mode="normal">
<tr>
<td valign="top">
<xsl:element name="a">
<xsl:attribute name="href"><xsl:value-of select="atom03:link/@href"/></xsl:attribute>
<xsl:attribute name="title"><xsl:value-of select="atom03:summary"/></xsl:attribute>
<xsl:attribute name="style">color:#FF0000</xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
<xsl:value-of select="concat(atom03:title, ' - 続きを読む...')"/>
</xsl:element>
<xsl:choose>
<xsl:when test="atom03:issued">
<xsl:value-of select="concat(' - ', substring-before(atom03:issued, 'T'))"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</td>
</tr>
</xsl:template>

<xsl:template match="//atom03:feed/atom03:title">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="//atom03:feed/atom03:link/@href">
<xsl:if test="../@rel = 'alternate'">
<xsl:if test="../@type = 'text/html'">
<xsl:value-of select="."/>
</xsl:if>
</xsl:if>
</xsl:template>


<!-- RSS 0.91/0.92/2.0 template -->
<xsl:template match="//rss/channel/item" mode="normal">
<tr>
<td valign="top">
<xsl:element name="a">
<xsl:attribute name="href"><xsl:value-of select="link"/></xsl:attribute>
<xsl:attribute name="title"><xsl:value-of select="link"/></xsl:attribute>
<xsl:attribute name="style">color:#FF0000</xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
<xsl:value-of select="concat(title, ' - 続きを読む...')"/>
</xsl:element>
<xsl:choose>
<xsl:when test="pubDate">
<xsl:value-of
select="concat(
' - ',
substring(
substring-before(jf:creationDate, ':'),
1,
string-length(substring-before(jf:creationDate, ':'))-3
)
)"
/>
</xsl:when>
<xsl:when test="dc:date">
<xsl:value-of select="concat(' - ', substring-before(dc:date, 'T'))"/>
</xsl:when>
<xsl:otherwise>
<!-- for OTN rss -->
<xsl:if test="jf:creationDate">
<xsl:value-of
select="concat(
' - ',
substring(
substring-before(jf:creationDate, ':'),
1,
string-length(substring-before(jf:creationDate, ':'))-3
)
)"
/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
</xsl:template>

<xsl:template match="//rss/channel/title">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="//rss/channel/link">
<xsl:value-of select="."/>
</xsl:template>

</xsl:stylesheet>

長くなるので、PL/SQLのソースは次回。




このサンプルは OTN-Jの CodeTipsでも公開しています。

(1/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2135
(2/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2137
(3/3) http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=2138

| | コメント (0) | トラックバック (0)

2007年3月30日 (金)

Mac De PL/SQL RSS Reader #31 (XSLT編 #3)

前回前々回と、いきなりデバッグの後半部分とApex3.0 での動作確認を載せていたので、今回は、少しだけ解説を。

XSLTスタイルシートは、Oracleのディレクトリオブジェクトから読み込んだと書いたが、まずはその点から解説しておこう。
ディレクトリオブジェクトを作成し、Apex3.0でアプリケーションの格納に利用する「作業領域」に割り当てられたスキーマへディレクトリオブジェクトの読み込み権限を付与しておく。

SYS> create directory plsql_de_xslt as '/Volumes/Discus/4oracle/oracle/plsql_de_xslt/';

ディレクトリが作成されました。

SYS> grant read on directory plsql_de_xslt to aquarium;

権限付与が成功しました。

尚、「作業領域」に割り当てられているスキーマの確認方法は、
Application Express管理サービスにログイン->「作業領域の管理」->「作業領域とスキーマの割当の管理」

31 32
33 34
上記のスクリーンショットを見れば一目瞭然だが、作業領域:aquariumにaquariumスキーマが割り当てられていることが確認できる。


ディレクトリオブジェクトの準備が済んだら、事前に作成しておいたXSLTスタイルシート(文字エンコーディングは、UTF-8とした)をディレクトリオブジェクトに対応付けされたディレクトリへ配置する。(以下は配置後の状態)

discus:˜/plsql_de_xslt oracle$ pwd
/Volumes/Discus/4oracle/oracle/plsql_de_xslt
discus:˜/plsql_de_xslt oracle$ ls
RssToXhtml.xsl
discus:˜/plsql_de_xslt oracle$

PL/SQLでは、DBMS_XSLPROCESSOR.READ2CLOB()ファンクションを使って読み込むことができる。


例えば、
●ディレクトリオブジェクト名:"PLSQL_DE_XSLT"
●XSLTスタイルシート名:"RssToXhtml.xsl"
●文字エンコーディング: "UTF-8"

である場合は以下のように指定する。
注意する点は、キャラクタセットIDだろう。NLS_CHARSET_ID関数を利用しキャラクタセット名からキャラクタセットIDに変換する必要がある。また、指定するキャラクタセット名は、Oracle Database グローバリゼーション・サポート・ガイドに記載されている名称を指定する。 この例では、UTF8

==> 私もハマりました。つい、"UTF-8"って指定してしまって。。。(^^;;;; しばらく悩みました。。はい。

  tempClob :=  DBMS_XSLPROCESSOR.READ2CLOB(
'PLSQL_DE_XSLT',
'RssToXhtml.xsl',
NLS_CHARSET_ID('UTF8')
);

また、以前にも書いたが、 DBMS_XMLPARSER.PARSER(url)を使ってRSS FEEDをパースできればいいのだが、今のところ、マルチバイトを利用している場合には文字化けの影響があるので、面倒だがUTL_HTTPパッケージを利用し自前でCLOBに取込んでからパースするようにしている。 

| | コメント (0) | トラックバック (0)

2007年3月29日 (木)

Mac De PL/SQL RSS Reader #30 (XSLT編 #2)

さて、SQL Developerでの確認も終わり、さっそく、Apex3.0で試してみた。

いつものように、「Hide and Show Region」を選択し、RSS 0.91/0.92/1.0/2.0 ATOM 0.3/1.0で配信されているFEEDを読み込むよう設定した。

Ap1_1 Ap2 


アプリケーションを実行した結果は以下。思い通りに変換されている。(XSLTスタイルシートを利用しているので、見栄えを変更する場合はXSLTスタイルシートを修正するだけ。。)

Ap3 Ap4

まあ、なんとか、以前のものとおなじような見栄えにはなりますね。(XSLT2.0ならもっといろいろとできるでしょうけども)
以下マニュアル引用


PL/SQL XSLT Processor for XMLType: Features

PL/SQL XSLT Processor for XMLType (DBMS_XSLPROCESSOR) is the Oracle XML DB implementation of the XSL processor. This follows the W3C XSLT final recommendation (REC-xslt-19991116).

W3C XSL Transformations(XSLT) バージョン 1.0の和訳はこちら。
http://www.infoteria.com/jp/contents/xml-data/REC-xslt-19991116-jpn.htm

次回へつづく。




植木等さんの名作といえば、無責任シリーズかもしれません。(今見ても、笑えますもん)
ただ、私などはリアルタイムで無責任シリーズを見た世代ではないので、「オヨビでない奴!」というドラマの印象が強烈かもしれない。
所ジョージと高橋良明が植木等にからみ、植木等の3乗くらいの面白さのあったドラマに仕上がっていたと思います。
ところで、所ジョージに植木等のまねをやらせたら似てるよ、きっと。。。

植木等さんのご冥福を心よりお祈りいたします。

| | コメント (0) | トラックバック (0)

Mac De PL/SQL RSS Reader #29 (XSLT編#1)

ノドが痛いと思っていたら、熱。インフルエンザではないが、風邪には違いない。(油断禁物ですね。。)1日休んだら、回復しましたけど、本調子に戻っていないので今日はおとなしくして明日は完全復活する予定。(週末は花見もしないとならんし。。な)


さて、PL/SQLでRSS Readerを作ってきたが、XSLTスタイルシートを利用した場合はどうなるか?
ということで、以前のプロシージャをベースに、XSLT版に書き換えてみることにする。

利環境は前回からの続きなので変更はないのだが、念のために、データベース、Web Toolkit、そして、Apexのバージョンを載せておく。

SYS> select version from v$instance;

VERSION
-----------------
10.1.0.3.0


SYS> select owa_util.get_version from dual;

GET_VERSION
--------------------------------------------------------
10.1.2.0.6

SYS> select flows_030000.wwv_flows_release from dual;

WWV_FLOWS_RELEASE
--------------------------------------------------------
3.0.0.00.20

SYS>

尚、開発には、 Oracle SQL Developer 1.1.2.25 Build Main 25.79 を使用した。

SQL Developerでは、OWAの出力もできるようなので試したかったということもあったのだが。。。

試してみるとOWAが書き出す量が多いとエラーになるようだ、具体的にどの程度ということまでは確認していないのだが。。HTP.PRNで4000バイト以上は書き出している。
但し、エラー時にもHTP.PRINTでエラー内容を出力しているのだが、こちらは、画面のスナップショットからも判るように問題なく表示されている
(前述の問題は、dbms_outputパッケージで代用できるので、特に困るということもないので深入りしないでスルー。(^^;;;)


X1 X2

前回までとは異なり、PL/SQL内部でDOMをトラバースしたりすることはせず、XSLTスタイルシートを利用してRSS/RDF/ATOMをHTMLに変換する。
変換後のHTMLには、FEEDのタイトル及びリンク、各記事の要約とリンク、それに記事の作成日があれば表示することにした。
尚、記事の作成日については、該当要素値から日付(RFC3339形式)部分を表示することにした。(RFC882形式の場合は、曜日も含める)
また、XSLスタイルシートの読み込み方法は幾つかあるが、今回はディレクトリオブジェクト以下にあるスタイルシートを読み込むことにした。。

XSLTスタイルシートで、xsl:choose要素や、xsl:if要素。xsl:variable要素なんて多用してしまうと、もの凄く読みにくいJSPのようになってしまいそうな気がする。。。
ところで、しっかりと内容を確認していないのだが、XML Master professional Database を取るべきか、Applicationを取るべきか悩みなすね。。


DBMS_OUTPU.PUT_LINEを利用してデバック変換後のHTMLを表示しているところ。

X3 X4
X5 X6


適当に作ったXSLTスタイルシートもなんとか思い通りのもにに仕上がったので、Apex3.0でお試し。。

次回へつづく。

| | コメント (0) | トラックバック (0)

2007年3月23日 (金)

Mac De Apex3.0 #5

さて、以前にも少々触れたが、Apexのupgradeの失敗、又は、upgrade後に以前のリリースに戻す方法について、備忘録程度に記述しておく。

手順については、マニュアルにも記載されているが、imageファイルについては、移行前に別名で保存して必要があるのでお忘れなく。
http://download-west.oracle.com/docs/cd/B32472_01/doc/install.300/b32468/trouble.htm#BABDJIFE


HTMLDB1.5からはじまり、HTMLDB2.0、APEX2.2そして、APEX3.0へと移行したのだが、前リリースのimagesフォルダや、marvel.conf(利用しているHTTP Serverによっては、dads.confを使用している場合あり)は、それぞれ別名で退避、また移行後、旧リリースのスキーマを削除していないことを前提としている。

以下はApex3.0移行後にApex2.2へ戻す例である。尚、apexは停止しておくこと!。


  1. Apex3.0用imagesディレクトリを別名で退避(以下例では、images_30として改名)又は、削除する。

  2. 事前に退避しておいた、Apex2.2用imagesディレクトリ(以下の例では、images_22)をimagesディレクトリとして改名又はコピーする。

  3. Apex3.0用に書き換えたmarvel.confを別名で退避(以下例では、marvel.conf.30と改名)又は、削除する。

  4. 事前に退避しておいた、Apex2.2用marvel.confファイル(以下例では、marvel.conf.22)をmarvel.confに改名又はコピーする。

  5. SQL*Plusを起動し、SYSユーザ接続後、スキーマを FLOWS_020200(Apex2.2用スキーマ)に変更する。

  6. flows_020200.wwv_flow_upgrade.switch_schemas()プロシージャにて、APEXのスキーマをFLOWS_030000(Apex3.0用スキーマ)からFLOWS_020200(Apex2.2スキーマ)に切り替える。

  7. flows_030000スキーマを削除する。


以上のような手順でApex3.0からApex2.2に戻す事ができる。以下はApex3.0からApex2.2に戻した際のログである。
pb17:/Volumes/WorkVol/u01/app/oracle/product/10.1.0/htmlDB/marvel oracle$ ll | grep images
drw-r----- 881 oracle oinstall 29954 Mar 18 17:21 images
drw-r----- 998 oracle oinstall 33932 Mar 18 14:33 images_20
drw-r----- 876 oracle oinstall 29784 Mar 18 13:00 images_22
pb17:/Volumes/WorkVol/u01/app/oracle/product/10.1.0/htmlDB/marvel oracle$
pb17:/Volumes/WorkVol/u01/app/oracle/product/10.1.0/htmlDB/marvel oracle$ mv images images_30
pb17:/Volumes/WorkVol/u01/app/oracle/product/10.1.0/htmlDB/marvel oracle$ cp -rf images_22 images
pb17:/Volumes/WorkVol/u01/app/oracle/product/10.1.0/htmlDB/marvel oracle$ cd ../apache/modplsql/conf
pb17:/Volumes/WorkVol/u01/app/oracle/product/10.1.0/htmlDB/apache/modplsql/conf oracle$ ls marvel*
marvel.conf marvel.conf.20 marvel.conf.22
pb17:/Volumes/WorkVol/u01/app/oracle/product/10.1.0/htmlDB/apache/modplsql/conf oracle$ mv marvel.conf marvel.conf.30
pb17:/Volumes/WorkVol/u01/app/oracle/product/10.1.0/htmlDB/apache/modplsql/conf oracle$ mv marvel.conf.22 marvel.conf
pb17:/Volumes/WorkVol/u01/app/oracle/product/10.1.0/htmlDB/marvel oracle$ sqlplus /nolog
> conn sys/xxxx@tiger as sysdba
SYS> l
1 select
2 username,
3 account_status
4 from
5 dba_users
6 where
7 username like '%¥_PUBLIC¥_%' escape '¥'
8 or username like 'FLOWS¥_%' escape '¥'
9 order by
10 account_status,
11* username
SYS> /

USERNAME ACCOUNT_STATUS
------------------------------ --------------------------------
FLOWS_020000 LOCKED
FLOWS_020200 LOCKED
FLOWS_030000 LOCKED
FLOWS_FILES LOCKED
APEX_PUBLIC_USER OPEN
HTMLDB_PUBLIC_USER OPEN

6行が選択されました。

SYS>
SYS> alter session set current_schema = FLOWS_020200;

セッションが変更されました。

SYS> exec flows_020200.wwv_flow_upgrade.switch_schemas('FLOWS_030000','FLOWS_020200');

PL/SQLプロシージャが正常に完了しました。

SYS> drop user flows_030000 cascade;

ユーザーが削除されました。

SYS>

これでApex2.2への戻しは終了である。

注意)HTMLDB_PUBLIC_USERというスキーマは、HTMLDB2.0までの接続スキーマである。HTMLDB2.0以前に戻す可能性がある場合にはこれも残しておく(lockしておいたほうがより安全だが)か、退避しておく必要がある。また、FLOWS_020000というスキーマはHTMLDB2.0のスキーマである。

| | コメント (0) | トラックバック (0)

2007年3月22日 (木)

Mac De APEX3.0 #4

さて、HTMLDB2.0からAPEX3.0への移行は簡単だったが、HTMLDB2.0や、APEX2.2でいろいろな問題のあったSVGチャートはどうなったのか?
SVGViewerの開発元であるアドビ社は、SVGViewerの開発を中止したようなので、APEXのチャートのサポートはどうなるのか少々気になっていたのだが、先日APEX3.0がリリースされ、SVGではなく、Flashもサポートされていた。お〜〜〜っ。これで、日本語も表示できるか??? 

まずは、はやり、AppleのCMからどうぞ。

Apple_pie_chart



ということで、マニュアルに示されている手順で、SVGチャート扱うアプリケーションをFLASHチャートを扱えるように移行する。実はこの移行手順も簡単なのだ。クリック、クリック、クリック。とクリックするだけで移行作業を行える。
(尚、MacOSXは、最新パッチを適用した 10.4.9 である。)

最後に、前回、日本語が化けるので凡例部分をローマ字にしていたバリバリ鎌倉円グラフを。。。おおお〜〜表示されました〜〜。

Fin

移行手順は、SVGチャートを配置しているページの該当リージョン開き、右側の枠に表示される、"SVGチャートのFLASHチャートへの移行"というリンクをクリックだけ!
その模様はQuickTImeムービーでどうぞ。


(再生にはQuickTimeが必要です。)


svg_2_flash

| | コメント (0) | トラックバック (0)

2007年3月21日 (水)

Mac De APEX3.0 #3

● APEX3.0 日本語リソースのインストール

apex_3.0.zipを解凍して作成されるディレクトリのbuilder/jaに移動し、load_ja.sqlスクリプトをsysユーザで実行する。
NLS_LANGは、AL32UTF8へ一時的に変更し、Terminalの文字エンコーディングもUTF-8変更しておく!

Apex30_terminal_utf8

G5Server:/Volumes/DiscusWork/temp/apex/builder/ja oracle$ ls -l load_ja.sql
-r--r--r-- 1 oracle oinstall 2319 Feb 28 04:35 unload_ja.sql
G5Server:/Volumes/DiscusWork/temp/apex/builder/ja oracle$
G5Server:/Volumes/DiscusWork/temp/apex/builder/ja oracle$ echo $NLS_LANG
Japanese_Japan.JA16SJISTILDE
G5Server:/Volumes/DiscusWork/temp/apex/builder/ja oracle$ export NLS_LANG=japanese_japan.AL32UTF8
G5Server:/Volumes/DiscusWork/temp/apex/builder/ja oracle$ sqlplus /nolog

SQL*Plus: Release 10.1.0.3.0 - Production on 月 3月 17 23:17:47 2007

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

> conn / as sysdba
接続されました。
SYS> alter session set current_schema = FLOWS_030000;

セッションが変更されました。

SYS> @load_ja
. ____ ____ ____ ____
. / \ | \ /\ / | /
.| || / / \ | | |
.| ||--- ---- | | |--
.| || \ / \ | | |
. \____/ | \/ \ \____ |____ \____
.
. Application Express Hosted Development Service Installation.
.........................................................

PL/SQLプロシージャが正常に完了しました。

Install Application Express applications

PL/SQLプロシージャが正常に完了しました。

APPLICATION 4420 - APEX - System Messages

・・・・中略・・・・

APPLICATION 4009 - APEX - Application Builder
Set Credentials...
Check Compatibility...
API Last Extended:20070108
Your Current Version:20070108
This import is compatible with version: 20070108
COMPATIBLE (You should be able to run this import without issues.)
Set Application ID...
...authorization schemes
...navigation bar entries
...application processes
...application items
...application level computations
...Application Tabs
...Application Parent Tabs
...Shared Lists of values
...Application Trees
...page groups
...PAGE .4009: ページ0(ゼロ)
...PAGE 1.4009: アプリケーション・ビルダー
...PAGE 2.4009: サポートするオブジェクト
...PAGE 3.4009: ブレッドクラム・エントリ
...PAGE 4.4009: マスター表の定義
...PAGE 5.4009: ディテール表を定義
...PAGE 6.4009: アイテム・ラベルのグリッド編集

・・・・中略・・・・

...PAGE 1.4709: 作業領域のリクエスト - 最初のページ
...PAGE 3.4709: 作業領域のリクエスト - 確認
...PAGE 10.4709: 作業領域のリクエスト - 管理者
...PAGE 20.4709: 作業領域のリクエスト - 作業領域
...PAGE 25.4709: 作業領域のリクエスト - スキーマの指定
...PAGE 26.4709: 作業領域のリクエスト - スキーマに関する警告
...PAGE 27.4709: 作業領域のリクエスト - プロジェクトの説明
...PAGE 30.4709: 作業領域のリクエスト - 確認
...PAGE 40.4709: 作業領域のリクエスト - 新規または既存のスキーマ

・・・・中略・・・・

...authentication schemes
......scheme 108165525079033088.4709
...done
Adjust instance settings

PL/SQLプロシージャが正常に完了しました。

SYS> exit
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Production
With the Partitioning, OLAP and Data Mining optionsとの接続が切断されました。
G5Server:/Volumes/DiscusWork/temp/apex/builder/ja oracle$

● 確認

APEX3.0への移行は特に問題もなく終了した。作業が簡単なのは、本当にうれしいねぇ。 (^^;;;。
(9iASや、10g Application Serverのupgradeも、もっと簡単になれば、もっとうれしいと思うのだが。。) 


Start_apex30 Apex30_test

今日はここまで。
次回は、チャートの表示がSVGViewerからFlashに変更されたので、以前SVGチャートを試したdemoアプリケーションをFlashに移行し、「パイチャート」を表示してみることにする。

| | コメント (0) | トラックバック (0)

2007年3月20日 (火)

Mac De Apex3.0 #2

HTMLDB2.0からAPEX3.0への移行作業。その2。

事前準備は整ったので、HTMLDB2.0からAPEX3.0へupgradeする。
尚、新規インストールなのか移行なのかを意識することはない楽で簡単ですね。
apex_3.0.zipを解凍した際に作成されるapexディレクトリ直下にあるapexins.sqlを実行するだけでよいので、非常に簡単。とは言っても心配ならはバックアップを取得しておいたほうがよいだろう。


尚、APEXのインストールでは、リリース毎に新たなスキーマが作成され、旧スキーマが残されている。
APEX3.0に移行したとしても、容易に以前のリリースに戻せるようになっている。 したがって、移行後すぐに旧スキーマを削除せず、しばらくの間は移行前のスキーマを残しておくという方法も取れる。
HTMLDB2.0からAPEX3.0の例でいえば、 FLOWS_020000が、HTMLDB2.0のスキーマで、新たにFLOWS_030000というスキーマが作成される。FLOWS_020000と関連するイメージファイル、marvel.conf(dads.confの場合もあり)を別途退避しておけば、その必要があればHTMLDB2.0環境へ戻すこともできる。

前置きが長くなったが作業再開。

尚、apexins.sqlでは、英語版がインストールされるので注意が必要、日本語リソースを別途インストールしないと、APEXのメニューなどは英語表記のままだ(online helpには日本語ヘルプは用意されていないようだ。)

ただし、日本語リソースをインストールしなくても、日本語を扱うアプリケーションは作成できる(ようだ)。
簡単に確認しただけなので、全く問題とは言い切れないが・・・・。


SYS> @apexins apex_master SYSAUX SYSAUX TEMP /i/
. ____ ____ ____ ____
. / ¥ | ¥ /¥ / | /
.| || / / ¥ | | |
.| ||--- ---- | | |--
.| || ¥ / ¥ | | |
. ¥____/ | ¥/ ¥ ¥____ |____ ¥____
.
. Application Express Installation.
...................................

F
-
2


FOO_USR
------------------------------
FLOWS_020000


PL/SQLプロシージャが正常に完了しました。


PL/SQLプロシージャが正常に完了しました。


レコードが選択されませんでした。


PL/SQLプロシージャが正常に完了しました。

I. O R A C L E S Y S I N S T A L L P R O C E S S
...create flows user

ユーザーが作成されました。

・・・・中略・・・・

......Message master_detail
......Message master_detail_edit
......Message master_detail_detail
......Message sw_empty_script
......Message sw_greater_than_30k
......Message confirm_create_master_detail
......Message confirm_3_page_master_detail
......Message confirm_2_page_master_detail
......Message confirm_master_table
......Message confirm_master_display_columns
......Message confirm_detail_table
......Message confirm_detail_display_columns
......Message confirm_master_sort
......Message confirm_include_master_report

・・・・中略・・・・

...PAGE 0: Page Zero
...PAGE 1: Application Builder
...PAGE 2: Supporting Objects
...PAGE 3: Breadcrumb Entries
...PAGE 4: Define Master Table
...PAGE 5: Define Detail Table
...PAGE 6: Item Label Grid Edit
...PAGE 7: Delete Multiple Items
...PAGE 8: Referenced Components
...PAGE 9: Shared Components

・・・・中略・・・・

...done load verification images
Verification Images Loadのタイミング。
経過: 00:00:01.13
VII. L O A D E N G L I S H D I C T I O N A R Y

トリガーが変更されました。

...10000 rows
...20000 rows
...30000 rows
...40000 rows
...50000 rows
...60000 rows
...70000 rows
English Dictionaryのタイミング。
経過: 00:04:56.56



Thank you for installing Oracle Application Express.

Oracle Application Express is installed in the FLOWS_030000 schema.

The structure of the link to the Application Express administration services is as follows:
http://host:port/pls/apex/apex_admin

The structure of the link to the Application Express development interface is as follows:
http://host:port/pls/apex

-- Now beginning upgrade. This will take several minutes.-------
-- Ensuring template names are unique -------
-- Migrating metadata to new schema -------
-- Switching builder to new schema -------
-- Migrating SQL Workshop metadata -------
-- Upgrading new schema. -------
-- Copying preferences to new schema. -------
-- Updating user account expiration. -------
Upgrade completed successfully no errors encountered.
-- Upgrade is complete -----------------------------------------
Upgradeのタイミング。
経過: 00:01:15.78
JOB_QUEUE_PROCESSES: 10

Performing Application Express component validation - please wait...

Completing registration process.
Validating installation.
Validate Installationのタイミング。
経過: 00:05:56.91
Complete Installationのタイミング。
経過: 00:31:02.26

● お約束、imagesフォルダの入れ替え。


このディレクトリは、前述のapexins.sqlで指定した /i/ という仮想ディレクトリにマッピングされている。
仮想ディレクトリ /i/ にマップされている実ディレクトリはmarvel.confで確認できる。
尚、利用しているHTTPサーバー毎に構成ファイルが異なるので要注意。詳細は、マニュアルの4.3.1.1 Copying the Images Directory When Upgradingを参照のこと。

G5Server:˜/u01/app/oracle/product/10.1.0/htmlDB/marvel oracle$ ls -l images*
drw-rw---- 998 oracle oinstall 33932 Mar 17 20:19 images
drw-rw---- 1334 oracle oinstall 45356 Mar 10 22:10 images_1_5
G5Server:˜/u01/app/oracle/product/10.1.0/htmlDB/marvel oracle$ mv images images_2_0
G5Server:˜/u01/app/oracle/product/10.1.0/htmlDB/marvel oracle$ cp -rf /Volumes/DiscusWork/temp/apex/images .
G5Server:˜/u01/app/oracle/product/10.1.0/htmlDB/marvel oracle$ ls -l images*
drw-rw---- 881 oracle oinstall 29954 Mar 17 22:45 images
drw-rw---- 1334 oracle oinstall 45356 Mar 10 22:10 images_1_5
drw-rw---- 998 oracle oinstall 33932 Mar 17 20:19 images_2_0


● HTTPサーバーの構成ファイルの書き換え


利用しているHTTPサーバーに対応した構成ファイルをapex30向けに書き換える。
当環境では、marvel.confである。変更内容は以下の通り。

(余談だが、marvel.confを書き換えずに試したところ、特に問題もなくAPEX3.0が利用できた。URLのパスを変更したくない場合には、他のパラメータを変更するだけでも問題ないかもしれない。詳細未確認。)

G5Server:˜/u01/app/oracle/product/10.1.0/htmlDB/Apache/modplsql/conf oracle$ diff marvel.conf.org marvel.conf
2c2
< <Location /pls/htmldb>
---
> <Location /pls/apex>
7c7
< PlsqlDatabaseUsername HTMLDB_PUBLIC_USER
---
> PlsqlDatabaseUsername APEX_PUBLIC_USER
10c10
< PlsqlDefaultPage htmldb
---
> PlsqlDefaultPage apex
13c13
< PlsqlDocumentProcedure wwv_flow_file_manager.process_download
---
> PlsqlDocumentProcedure wwv_flow_file_mgr.process_download
15c15
< PlsqlNLSLanguage JAPANESE_JAPAN.JA16SJISTILDE
---
> PlsqlNLSLanguage JAPANESE_JAPAN.AL32UTF8
G5Server:˜/u01/app/oracle/product/10.1.0/htmlDB/Apache/modplsql/conf oracle$

今日はここまで、日本語リソースのインストールへつづく。


聞いている曲:
Howard Jones - The Peaceful Tour - Things Can Only Get Better Howard Jones - The Peaceful Tour - Things Can Only Get Better

| | コメント (0) | トラックバック (0)

2007年2月22日 (木)

Mac De PL/SQL RSS Reader #28 - メモ

OTN-JフォーラムのFEEDはUS OTNと同じく、RSS2.0となっているようだ。(下記XMLソース抜粋参照のこと。)


item要素にはネームスペースで拡張された、jf:creationDate要素や、jf:author要素は存在するが、author要素や、pubDate要素が存在しない。

そのため、FirefoxやSarafi、Google RSS readerなどでは、投稿者や日時が表示されない。
US OTNの場合と同じなのだが、投稿日があると便利でしょと思うのは私だけ?

Safariでは投稿日関連する要素が存在しない場合には、FEEDを取込んだ日時を表示してくれるので、多少は助かる。
Safari


Firefox2では、日時表示は全くない(pubDate要素がないので当然だが。。)
Firefox2


Google ReaderでもFirefox2に同じ。
Googlerssreader

リニューアルついでなので、author要素や、pubDate要素くらい追加してもらえるといいのだが・・・OTN-Jさん。。。と思いつつ。。





ということで、Apex2.2に組み込んだPL/SQLのRSS FEED Readerのコードを変更するのもいいかと思い始めた。


例えば、OTNのRSS2.0 FEEDのように、item要素には、pubDate要素が含まれず、名前空間で拡張されたjf:creationDate要素がある場合、
RSS FEED Reader側で、どのネームスペースのどの要素を使うかなんて設定できるようにすれば、便利かな〜〜と思った次第。。
(あと、jf:createDate要素値は、rfc822形式のようだが、曜日が日本語表記なので、英語表記へ変換する必要あり。(現行のコードのままだと例外が飛ぶはずなので、それも含め、コードの見直しを考えてみますか。。。

<rss version="2.0" xmlns:jf="http://www.jivesoftware.com/xmlns/jiveforums/rss">
<channel>
・・・・中略・・・・
<item>
<title>Re: 追記: 名前空間を使用したXqueryの使用方法に関して</title>
<link>http://otn.oracle.co.jp/forum/thread.jspa?messageID=35001142&tstart=0#35001142</link>

<description><![CDATA[名前空間のURLが間違っているのでは? (.xsd が抜けているとか。)]]></description>

<jf:creationDate>金, 09 2 2007 18:55:56 +0900</jf:creationDate>
<jf:modificationDate>金, 09 2 2007 18:55:56 +0900</jf:modificationDate>
<jf:author>xxxxxx</jf:author>
<jf:replyCount>0</jf:replyCount>
</item>
・・・・以下略・・・・

| | コメント (2) | トラックバック (0)

2007年2月21日 (水)

Mac De PL/SQL RSS Reader番外編-OTN-J Forum RSS FEED配信開始記念?!

2月1日からOTN-JのForumがリニューアルされ、US OTNのForumのように新規投稿がRSS FEEDで配信されるようになった。(やっとと言った感じ。US OTNに遅れること。。。?年という感じなので待ちくたびれていたところだった。。。)

さっそく、Safariで、会議室のFEEDをブックマークしてみるとUS OTNのように新着記事が取込まれている。。
クリックして各記事を眺めてみても問題なさそうだなぁ。
と思い、折角だから、Apex2.2に組み込んだ RSS READERで試しはじめたころから、リニューアルしたフォーラムの問題に気づき始める。。。。

まず、以前にも試していた、PL/SQLでRSS FEED ReaderをApex2.2に組み込み、OTN-JのFEEDを取込むと、、、なんと、パースエラー!
ん? このエラーは、以前にも見たような気がする。。が、ちゃんとUTL_HTTPパッケージを利用し、UTF-8で取込むことで回避したはずだ。。おかしい。。Safariでは文字化けなど発生していない!!

Xml_parse_error_plsql


そこで、MacOSX版 Firefox2でプレビューモードにしてOTN-JのFEEDを取込んでみると。。。
お〜〜〜。見事にXMLパースエラー!!

Xml_parse_error


ところが、再度行うと、今度は、文字化け!
さらに不思議なことに、、、ブックマークしたFEEDのエントリは文字化けしていないではないか??(なんだこりゃ!)

Xml_no_parse_error_but


その後、何度か試していると、上手く取込める場合、XMLパースエラーになる場合、パースエラーにはならないが文字化けする状態がランダムに発生することが分かった。
UTF-8以外の文字コードで送信されてしまう状態がランダムに発生しているようにみえた。(・・・経路が違うのかもしれない。例えばキャッシュを経由した場合とそれ以外のように、。。と勝ってに想像したりしている。)

そして、OTN-Jがリニューアルされてから、9日目のこと、Firefox2上でのFeedの文字化けも収まった?模様?で、文字化けやXMLパースエラーにはお目にかからなくなった。


ということで、再度、Apex2.2に組み込んだPL/SQLで作成したFEED READERで、OTN-JのXMLの部屋のFEEDを取込んでみた。


(再生にはQuickTimeが必要です。)

apex2.2

なんとか、読めるようになりましたね。。。。。OTN-J様。ご苦労さまです。m(_ _)m。

| | コメント (0) | トラックバック (0)

2006年11月20日 (月)

Mac De PL/SQL RSS Reader #27 (+)

Mac De PL/SQL RSS Reader #27で公開したコードがOTN-JapanのCocd Tipsで公開されました。

尚、記事が大きく3分割してあります。

Code Tips PL/SQLで RSS Feed Reader (1/3)
Code Tips PL/SQLで RSS Feed Reader (2/3)
Code Tips PL/SQLで RSS Feed Reader (3/3)

尚、OTN-JapanのCode Tipsを見るには、OTN-Japanへのユーザ登録が必要です。

※オラクルライセンスセンターのアフィリエイトも追加しました。



いいねぇ、Saigenji

聞いている曲:Saigenji - SAIGENJI - 孤動 saigenji - SAIGENJI - 孤動

| | コメント (0) | トラックバック (0)

2006年11月 4日 (土)

Mac De PL/SQL RSS Reader #27

RSS Readerの続き。

週末、美味しいワインのつまみのレシピを多摩美の芸術祭りに模擬店を出しているmiwaさん教えてもらいニッコリ!!

さて、APEX2.2に組み込んだPL/SQLで作成したRSS Readerストアドプロシージャのソースを公開。
ひとまず、これで、RSS Readerネタは終了。
Oracle Portalのデータベースポートレット向けにするとか、XSLT版というのも面白いと思っているが、それらはまた、気が向いたときにでも。。 

以下は、APEXに組み込んだデモをQiuckTime Movieにしたもの。(再生にはQuickTimeが必要です。)


Apex_de_rss_reader_demo4


そして、RSS Readerストアドプロシージャのソースは以下。
ただし、ブラウザに表示するためソースコードの一部の文字を
文字参照に置換してある。( < > " ¥ など) 

オリジナルのスクリプトrss_reader.sqlはこちら。(エンコーディングは、shift_jis。)

(RFC822や、RFC3339のDate / Time関連関数は、ストアドプロシージャの内部関数化してある。これらをパッケージ化するほうが分かりやすくなるかもしれないが、それらの内部関数を単独で利用することもないのでストアドプロシージャの内部関数としてある。)

CREATE OR REPLACE PROCEDURE RSS_READER
(
i_feedXmlUrl IN VARCHAR2
)
AS
--============ TYPEs/VARIABLEs ===============================================
C_RSS CONSTANT VARCHAR2(7) := 'rss';
C_RDF CONSTANT VARCHAR2(7) := 'rdf:RDF';
C_ATOM CONSTANT VARCHAR2(7) := 'feed';
-- C_ATTR_NAME_VERSION CONSTANT VARCHAR2(7) := 'version';

v_feedXmlUrl VARCHAR2(32767);

TYPE FeedEntryType IS RECORD
(
title VARCHAR2(2000),
link VARCHAR2(200),
published TIMESTAMP WITH LOCAL TIME ZONE
);
v_feedEntryList DBMS_XMLDOM.DomNodeList;
v_feedTitle VARCHAR2(2000);
v_feedUrl VARCHAR2(200);

v_myParser DBMS_XMLPARSER.Parser;
v_feedDoc DBMS_XMLDOM.DomDocument;

v_rootElementTagName VARCHAR2(7);
-- v_feedVersion VARCHAR2(40);
v_feedSourceClob CLOB;
v_nsAttrXmlNameSpaces VARCHAR2(32767);

--========== Internal PROCEDUREs/FUNCTIONs ===================================
FUNCTION RFC3339_DateStrToTimeStampLTZ(
i_dateTimeString IN VARCHAR2
)
RETURN TIMESTAMP WITH LOCAL TIME ZONE
AS
C_NLS_DATE_LANGUAGE CONSTANT VARCHAR2(40) := 'NLS_DATE_LANGUAGE=AMERICAN';
v_tempTimeStampTz TIMESTAMP WITH LOCAL TIME ZONE := NULL;
v_dateTimeString VARCHAR2(50) := NULL;
v_timeStampTzFormat VARCHAR2(40) := NULL;
BEGIN
v_dateTimeString := REGEXP_REPLACE(
REGEXP_REPLACE(
UPPER(i_dateTimeString),
'T', NULL, 1, 1
),
'Z$', 'UTC'
);

IF v_dateTimeString IS NULL THEN
RETURN NULL;
END IF;


v_timeStampTzFormat := 'RRRR-MM-DD';

IF LENGTH(v_dateTimeString) >= 10 THEN

IF REGEXP_INSTR(v_dateTimeString , '([0-9]{2}:){2}[0-9]{2}¥.?') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI:SSXFF';
END IF;

IF REGEXP_INSTR(v_dateTimeString, '(¥+|¥-)[0-9]{2}:[0-9]{2}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZH:TZM';
ELSIF REGEXP_INSTR(v_dateTimeString, 'UTC$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZR';
END IF;
END IF;

v_tempTimeStampTz := TO_TIMESTAMP_TZ(
v_dateTimeString,
v_timeStampTzFormat,
c_nls_date_language
);

RETURN v_tempTimeStampTz;

EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(
-20002,
'RFC3339_DateStrToTimeStampLTZ():' || SQLERRM()
);
RETURN NULL;
END RFC3339_DateStrToTimeStampLTZ;


FUNCTION RFC822_DateStrToTimeStampLTZ
(
i_dateTimeString IN VARCHAR2
)
RETURN TIMESTAMP WITH LOCAL TIME ZONE
AS
C_NLS_DATE_LANGUAGE CONSTANT VARCHAR2(40) := 'NLS_DATE_LANGUAGE=AMERICAN';
v_tempTimeStampTz TIMESTAMP WITH LOCAL TIME ZONE := NULL;
v_dateTimeString VARCHAR2(50) := NULL;
v_timeStampTzFormat VARCHAR2(40) := NULL;
BEGIN
v_dateTimeString := UPPER(i_dateTimeString);
IF v_dateTimeString IS NULL THEN
RETURN NULL;
END IF;

IF REGEXP_INSTR(v_dateTimeString, '^[A-Z]{3}¥, ') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'DY, ';
END IF;

v_timeStampTzFormat := v_timeStampTzFormat || 'DD MON RRRR';
IF REGEXP_INSTR(v_dateTimeString, '[0-9]{2}:[0-9]{2}:[0-9]{2}') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI:SS ';
ELSIF REGEXP_INSTR(v_dateTimeString, '[0-9]{2}:[0-9]{2}') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI ';
END IF;

IF REGEXP_INSTR(v_dateTimeString, ' (¥+|¥-)[0-9]{4}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZHTZM';
ELSIF REGEXP_INSTR(v_dateTimeString, ':[0-9]{2}$') = 0
AND REGEXP_INSTR(v_dateTImeString, '[0-9]{2} [A-Z]{3} [0-9]{2,4}$') = 0
AND REGEXP_INSTR(v_dateTImeString, ' [A-Z]{1,3}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZR';
END IF;

v_tempTimeStampTz := TO_TIMESTAMP_TZ(
v_dateTimeString,
v_timeStampTzFormat,
c_nls_date_language
);

RETURN v_tempTimeStampTz;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(
-20001,
'RFC822_DateStrToTimeStampLTZ():' || SQLERRM()
);
RETURN NULL;
END RFC822_DateStrToTimeStampLTZ;


PROCEDURE getFeedSource(
i_feedXmlUrl IN VARCHAR2,
i_feedXmlCharset IN VARCHAR2 DEFAULT 'UTF-8',
io_feedSourceClob IN OUT NOCOPY CLOB
)
IS
v_httpReq UTL_HTTP.REQ;
v_httpResp UTL_HTTP.RESP;
v_feedSource VARCHAR2(1024);
BEGIN
v_httpReq := UTL_HTTP.BEGIN_REQUEST(i_feedXmlUrl);
UTL_HTTP.SET_HEADER(
v_httpReq,
'User-Agent',
'Oracle UTL_HTTP/Oracle10g R1;'
);

UTL_HTTP.SET_HEADER(
v_httpReq,
'Content-Type',
'text/xml;charset='||i_feedXmlCharset
);

v_httpResp := UTL_HTTP.GET_RESPONSE(v_httpReq);
DBMS_LOB.CREATETEMPORARY(io_feedSourceClob, FALSE);
BEGIN
LOOP
UTL_HTTP.READ_LINE(v_httpResp, v_feedSource, true);
v_feedSource := v_feedSource || UTL_TCP.CRLF;
DBMS_LOB.WRITEAPPEND(
io_feedSourceClob,
LENGTH(v_feedSource),
v_feedSource
);
END LOOP;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(v_httpResp);
END;
END getFeedSource;


PROCEDURE getNameSpaces(
i_feedType IN VARCHAR2,
i_feedDoc IN DBMS_XMLDOM.DomDocument,
io_feedXmlNameSpaces IN OUT NOCOPY VARCHAR2
)
IS
v_attrTagName VARCHAR2(32767);
v_feedNodelist DBMS_XMLDOM.DomNodeList;
v_nsAttrNamedNodeMap DBMS_XMLDOM.DomNamedNodeMap;
BEGIN

CASE i_feedType
WHEN C_RSS THEN
v_feedNodeList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, C_RSS);

WHEN C_RDF THEN
-- name spaceが影響しているのだと思われるが上手い解決方法が
-- 見つからなかったので、全要素を取得している。
v_feedNodeList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, '*');

WHEN C_ATOM THEN
v_feedNodeList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, C_ATOM);

END CASE;

v_nsAttrNamedNodeMap
:= DBMS_XMLDOM.GETATTRIBUTES(DBMS_XMLDOM.ITEM(v_feedNodeList, 0));

FOR i IN 0..DBMS_XMLDOM.GETLENGTH(v_nsAttrNamedNodeMap)-1 LOOP
v_attrTagName
:= DBMS_XMLDOM.GETNODENAME(DBMS_XMLDOM.ITEM(v_nsAttrNamedNodeMap, i));

IF REGEXP_INSTR(v_attrTagName, '^xmlns') = 1 THEN
io_feedXmlNameSpaces
:= io_feedXmlNameSpaces
|| v_attrTagName || '="'
|| DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.ITEM(v_nsAttrNamedNodeMap, i))
|| '" ';
END IF;
END LOOP;
END getNameSpaces;


PROCEDURE getFeedEntries(
i_feedType IN VARCHAR2,
i_feedDoc IN DBMS_XMLDOM.DomDocument,
i_feedXmlNameSpaces IN VARCHAR2,
o_feedTitle OUT NOCOPY VARCHAR2,
o_feedUrl OUT NOCOPY VARCHAR2,
o_feedEntryList OUT NOCOPY DBMS_XMLDOM.DomNodeList
)
IS
v_feedSourceXml XMLTYPE;
BEGIN
v_feedSourceXml := DBMS_XMLDOM.GETXMLTYPE(i_feedDoc);
CASE i_feedType
WHEN C_RSS THEN
o_feedEntryList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, 'item');
o_feedTitle := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/rss/channel/title/text()',
i_feedXmlNameSpaces
).GETSTRINGVAL();
o_feedUrl := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/rss/channel/link/text()',
i_feedXmlNameSpaces
).GETSTRINGVAL();

WHEN C_RDF THEN
o_feedEntryList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, 'item');
o_feedTitle := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/rdf:RDF/channel/title/text()',
i_feedXmlNameSpaces
).GETSTRINGVAL();
o_feedUrl := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/rdf:RDF/channel/link/text()',
i_feedXmlNameSpaces
).GETSTRINGVAL();

WHEN C_ATOM THEN
o_feedEntryList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(i_feedDoc, 'entry');
o_feedTitle := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/feed/title/text()',
i_feedXmlNameSpaces
).GETSTRINGVAL();
o_feedUrl := XMLTYPE.EXTRACT(
v_feedSourceXml,
'/feed/link[@type="text/html"]/@href',
i_feedXmlNameSpaces
).GETSTRINGVAL();

END CASE;
END getFeedEntries;


PROCEDURE drawFeedEntry(
i_feedEntry IN FeedEntryType
)
IS
BEGIN
HTP.TABLEROWOPEN();
HTP.TABLEDATA(
'<a href="'
|| i_feedEntry.link
|| '" style="color:#FF0000" target="_blank">'
|| i_feedEntry.title || ' -- 続きを読む... '
|| '</a>' || TO_CHAR(i_feedEntry.published,'yyyy-mm-dd hh24:mi')

);
HTP.TABLEROWCLOSE();
END drawFeedEntry;


PROCEDURE drawFeedEntries(
i_feedType IN VARCHAR2,
i_feedTitle IN VARCHAR2,
i_feedUrl IN VARCHAR2,
i_feedEntryList IN DBMS_XMLDOM.DomNodeList
)
IS
v_feedEntry FeedEntryType;
v_emptyFeedEntry FeedEntryType;
v_itemNode DBMS_XMLDOM.DomNode;
v_childnode DBMS_XMLDOM.DomNode;
v_feedItemFields DBMS_XMLDOM.DomNodeList;
v_attrNamedNodeMap DBMS_XMLDOM.DomNamedNodeMap;
v_childNodeText VARCHAR2(32767);
BEGIN
HTP.TABLEOPEN();
HTP.TABLEROWOPEN();
HTP.TABLEHEADER(
'<a href="'
|| i_feedUrl
|| '" style="color:#000000" target="_blank">'
|| i_feedTitle
|| '</a>'
|| ' - ' || dbms_xmldom.getlength(i_feedEntryList)|| ' articles.'
);
HTP.TABLEROWCLOSE();

v_feedEntry := v_emptyFeedEntry;
FOR i IN 1..DBMS_XMLDOM.GETLENGTH(i_feedEntryList) LOOP
v_itemNode := DBMS_XMLDOM.ITEM(i_feedEntryList, i-1);
v_feedItemFields := DBMS_XMLDOM.GETCHILDNODES(v_itemNode);

FOR j IN 1..DBMS_XMLDOM.GETLENGTH(v_feedItemFields) LOOP
v_childnode := DBMS_XMLDOM.ITEM(v_feedItemFields, j-1);
v_childNodeText := DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.GETFIRSTCHILD(v_childnode)
);

CASE DBMS_XMLDOM.GETNODENAME(v_childnode)

WHEN 'title' THEN
v_feedEntry.title := v_childNodeText;


WHEN 'link' THEN
IF i_feedType = C_ATOM THEN
-- ATOM
v_attrNamedNodeMap := DBMS_XMLDOM.GETATTRIBUTES(v_childnode);
IF DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.GETNAMEDITEM(v_attrNamedNodeMap, 'type')
) = 'text/html'
THEN
v_feedEntry.link :=
DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.GETNAMEDITEM(v_attrNamedNodeMap, 'href')
);
END IF;

ELSE
-- RSS/RDF
v_feedEntry.link := v_childNodeText;
END IF;


-- RSS 0.9x and RSS 2.0
WHEN 'pubDate' THEN
v_feedEntry.published
:= RFC822_DateStrToTimestampLTZ(v_childNodeText);

-- ATOM 1.0
WHEN 'published' THEN
v_feedEntry.published
:= RFC3339_DateStrToTimestampLTZ(v_childNodeText);

-- RSS/RDF 1.0 , RSS 2.0
WHEN 'dc:date' THEN
v_feedEntry.published
:= RFC3339_DateStrToTimestampLTZ(v_childNodeText);

-- ATOM 0.3
WHEN 'issued' THEN
v_feedEntry.published
:= RFC3339_DateStrToTimestampLTZ(v_childNodeText);

ELSE
NULL; -- nop
END CASE;
END LOOP;

drawFeedEntry(v_feedEntry);
END LOOP;
HTP.TABLECLOSE();
END drawFeedEntries;
--
--
--****************************************************************************
-- Main
--****************************************************************************
BEGIN

v_feedXmlUrl := i_feedXmlUrl;
IF v_feedXmlUrl IS NULL THEN
RAISE_APPLICATION_ERROR(-20003, 'FEEDのURLを指定してください。');
END IF;


getFeedSource(
i_feedXmlUrl => v_feedXmlUrl,
io_feedSourceClob => v_feedSourceClob
);

v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSECLOB(v_myParser, v_feedSourceClob);
v_feedDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);

v_rootElementTagName
:= DBMS_XMLDOM.GETTAGNAME(DBMS_XMLDOM.GETDOCUMENTELEMENT(v_feedDoc));

-- v_feedVersion
-- := DBMS_XMLDOM.GETVALUE(
-- DBMS_XMLDOM.GETATTRIBUTENODE(
-- DBMS_XMLDOM.GETDOCUMENTELEMENT(v_feedDoc),
-- C_ATTR_NAME_VERSION
-- )
-- );

getNameSpaces(
i_feedType => v_rootElementTagname,
i_feedDoc => v_feedDoc,
io_feedXmlNameSpaces => v_nsAttrXmlNameSpaces
);

getFeedEntries(
i_feedType => v_rootElementTagname,
i_feedDoc => v_feedDoc,
i_feedXmlNameSpaces => v_nsAttrXmlNameSpaces,
o_feedTitle => v_feedTitle,
o_feedUrl => v_feedUrl,
o_feedEntryList => v_feedEntryList
);

drawFeedEntries(
i_feedType => v_rootElementTagName,
i_feedTitle => v_feedTitle,
i_feedUrl => v_feedUrl,
i_feedEntryList => v_feedEntryList
);

DBMS_LOB.FREETEMPORARY(v_feedSourceClob);
DBMS_XMLDOM.FREEDOCUMENT(v_feedDoc);
DBMS_XMLPARSER.FREEPARSER(v_myParser);

EXCEPTION
WHEN OTHERS THEN
IF v_feedSourceClob IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(v_feedSourceClob);
END IF;
DBMS_XMLDOM.FREEDOCUMENT(v_feedDoc);
DBMS_XMLPARSER.FREEPARSER(v_myParser);
HTP.TABLEOPEN();
HTP.TABLEROWOPEN();
HTP.TABLEHEADER('RSS Reader error:'||SQLERRM());
HTP.TABLEROWCLOSE();
HTP.TABLECLOSE();
END RSS_READER;
/
show errors
/




まだまだ、早いか?! などと思っていると、あっという間に、クリスマスモードに突入しちゃうんですよね!。
聞いている曲:Take 6 - We wish you a merry christmas

| | コメント (0) | トラックバック (0)

2006年10月29日 (日)

Mac De PL/SQL RSS Reader #26

RSS Readerの続き。APEX 2.0に組み込んだRss Readerのレイアウトを変えてみた 

Hide and Show リージョンを3行2列にレイアウトしてみた。設定はこんな感じ。
Img7 Img6 

リージョンに埋め込んだコードはこんな感じ。PL/SQLブロックしか実行できないので、beginブロック内でrss_readerプロシージャを呼び出している。
Img8


実行するとこうなる。Hide and Showリージョンなのでリージョンを折り畳む事ができる。
Img2_1 Img3_1 Img4 Img5

ひとまず、こんなところで。。

| | コメント (0) | トラックバック (0)

2006年10月23日 (月)

Mac De PL/SQL RSS Reader #25

RSS Readerの続き。適当にAPEX 2.0に組み込み、一覧にしてみた。

以下の通り、大雑把に作ってみたが、それなりね。APEX (HTML DB)に慣れる必要あり。。。。
R1 R2jpg R3

| | コメント (0) | トラックバック (0)

2006年10月21日 (土)

Mac De PL/SQL RSS Reader #24

RSS Readerの続き。ドラフト版でのテストログの続き。(その6/6)

ATOM 1.0のFEEDをテストした結果。

---------------------- PROMPT ATOM 1.0
begin...
====================
Radical Imagination -from 鎌倉 with Love - 15 articles:
http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/
====================
TITLE: 由比ヶ浜秋景-3
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/3.html
Published on: 2006-10-11 19:48
—————————————-
TITLE: 老母のテラコッタ人形新作
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_58.html
Published on: 2006-10-10 00:23
—————————————-
TITLE: 地方のロードサイド風景
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_57.html
Published on: 2006-10-09 00:55
—————————————-
TITLE: 由比ヶ浜3頭会談
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_56.html
Published on: 2006-10-08 18:30
—————————————-
TITLE: 由比ヶ浜秋景-2
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/2_9.html
Published on: 2006-10-07 19:36
—————————————-
TITLE: 由比ヶ浜秋景-1
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_55.html
Published on: 2006-10-07 15:10
—————————————-
TITLE: 『ドリームボックス-殺されていくペットたち』
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_54.html
Published on: 2006-10-06 13:35
—————————————-
TITLE: 『Maria Full of Grace』(『そして、ひと粒のひかり』)
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/maria_full_of_grace.html
Published on: 2006-10-05 03:06
—————————————-
TITLE: ラ・ジュルネ(鎌倉由比ガ浜)-20 いぶりがっこ
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/20_1.html
Published on: 2006-10-04 05:03
—————————————-
TITLE: 恩師・尾崎康先生
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_53.html
Published on: 2006-10-03 13:52
—————————————-
TITLE: 朝の光
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/10/post_52.html
Published on: 2006-10-01 22:34
—————————————-
TITLE: 長谷秋色-2 曼珠沙華
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/09/2.html
Published on: 2006-09-30 00:19
—————————————-
TITLE: 今朝のおはよう-40 由比ガ浜文様
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/09/post_51.html
Published on: 2006-09-29 22:53
—————————————-
TITLE: なかむら庵(鎌倉小町)
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/09/post_50.html
Published on: 2006-09-29 21:10
—————————————-
TITLE: まっさらMac
URL : http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/2006/09/mac.html
Published on: 2006-09-29 19:46
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。

GLASSCATFISH> spo off


特に問題もないので、OracleのAPEXに組み込みテストしてみる予定である。
そういえば、最近、米salesforce が、新プログラミング言語 「Apex」を発表というニュースもあり、APEX だけで検索してしまうと、いろいろとヒットしてしまう・・・・・。(^^;;

尚、コードを少々変更すれば、Oracle Portalの DBポートレット化することも難しくないと思うのだが、その環境がいまは無い。。。


クラシックも聞くんです(ただし、ピアノだけ、しかも、大映テレビのドラマで使われた曲だけ)
赤い激流
少女に何が起こったか

フジ子・へミング - 練習曲 第12番 ハ短調 作品10の12《革命》 フジ子・へミング - ラ・カンパネラ 1973 - 練習曲 第12番 ハ短調 作品10の12《革命》
フジ子・ヘミング - ラ・カンパネラ フジ子・ヘミング - 奇蹟のカンパネラ - ラ・カンパネラ (パガニーニによる大練習曲 S.141-3) [リスト]
フジ子・ヘミング - ポロネーズ第6番《英雄》 イングリット・フジコ・ヘミング - ピアノ名曲集 - ポロネーズ第6番《英雄》

今日は、美味しい空気とワインを楽しみに。。。。。どこに行ったか? 詳しくは、以下。
メガ放談
今日のゴハン

| | コメント (0) | トラックバック (0)

2006年10月20日 (金)

Mac De PL/SQL RSS Reader #23

RSS Readerの続き。ドラフト版でのテストログの続き。(その5/6)

ATOM 0.3のFEEDをテストした結果。

---------------------- PROMPT ATOM 0.3
begin...
====================
今日のゴハン - 10 articles:
http://atsu-log.way-nifty.com/today_s_menu/
====================
TITLE: 長崎堂カステラ
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_7031.html
Published on: 2006-10-11 23:46
—————————————-
TITLE: 豚汁
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_3239.html
Published on: 2006-10-11 23:36
—————————————-
TITLE: ポテトサラダ
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_e144.html
Published on: 2006-10-11 23:31
—————————————-
TITLE: TAKAGIのプリン、、、
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/takagi_71f8.html
Published on: 2006-10-10 22:24
—————————————-
TITLE: フンギビアンコ Part2
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/part2_21d3.html
Published on: 2006-10-10 22:20
—————————————-
TITLE: きのこ & アーティチョークのホットサンドウィッチ
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/__bbee.html
Published on: 2006-10-10 22:12
—————————————-
TITLE: 茶豆梅ご飯
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_cb33.html
Published on: 2006-10-10 22:04
—————————————-
TITLE: はっぴーばーすでー・ははちゃん!
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_f02c.html
Published on: 2006-10-09 23:07
—————————————-
TITLE: La vie Equiseのお総菜パン
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/la_vie_equise_0de3.html
Published on: 2006-10-09 20:36
—————————————-
TITLE: 納豆の揚げ包み焼き
URL : http://atsu-log.way-nifty.com/today_s_menu/2006/10/post_66d1.html
Published on: 2006-10-09 09:56
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。


テストログ、ATOM 1.0へ続く。


iTMS-J、いろんなアーティストの曲がまだまだないと思っていると、The Theなんかがあったり。。。
聞いている曲:The The - NakedSelf - Swine Fever The The - NakedSelf - Swine Fever

| | コメント (0) | トラックバック (0)

2006年10月19日 (木)

Mac De PL/SQL RSS Reader #22

RSS Readerの続き。ドラフト版でのテストログの続き。(その4/6)

RSS 2.0のFEEDをテストした結果。

---------------------- PROMPT RSS 2.0
begin...
====================
Life is a trip of looking for myself ! - 15 articles:
http://miwa2006.exblog.jp
====================
TITLE: Aji & Mic -3
URL : http://miwa2006.exblog.jp/4694707
Published on: 2006-10-08 18:51
—————————————-
TITLE: 手作りごはん
URL : http://miwa2006.exblog.jp/4694041
Published on: 2006-10-08 16:17
—————————————-
TITLE: 造形の美
URL : http://miwa2006.exblog.jp/4686673
Published on: 2006-10-07 01:24
—————————————-
TITLE: 街づくりー2
URL : http://miwa2006.exblog.jp/4672126
Published on: 2006-10-04 15:48
—————————————-
TITLE: Aji & Mic -2
URL : http://miwa2006.exblog.jp/4657697
Published on: 2006-10-01 23:32
—————————————-
TITLE: 野菜収穫
URL : http://miwa2006.exblog.jp/4647062
Published on: 2006-09-30 01:29
—————————————-
TITLE: 街づくり−1
URL : http://miwa2006.exblog.jp/4641071
Published on: 2006-09-29 00:04
—————————————-
TITLE: Aji & Mic -1
URL : http://miwa2006.exblog.jp/4626283
Published on: 2006-09-26 14:16
—————————————
TITLE: 自由が丘
URL : http://miwa2006.exblog.jp/4625821
Published on: 2006-09-26 11:55
—————————————-
TITLE: 増山理人「中南米ニカラグア・スラムの子どもたちと過ごした2年間の記憶」講演会
URL : http://miwa2006.exblog.jp/4601697
Published on: 2006-09-22 11:48
—————————————-
TITLE: Love! dessert
URL : http://miwa2006.exblog.jp/4600028
Published on: 2006-09-22 00:39
—————————————-
TITLE: 愛すべきタマゴサンド
URL : http://miwa2006.exblog.jp/4568432
Published on: 2006-09-16 23:45
—————————————-
TITLE: 料理してますよ。
URL : http://miwa2006.exblog.jp/4559138
Published on: 2006-09-15 11:25
—————————————-
TITLE: レンバイ
URL : http://miwa2006.exblog.jp/4395219
Published on: 2006-08-23 10:28
—————————————-
TITLE: Mic夏バテ?
URL : http://miwa2006.exblog.jp/4387154
Published on: 2006-08-22 10:47
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。

テストログ、ATOM 0.3へ続く。


日本のバンドだけど、いいねぇ。ちょいとラテン入ってる?!
聞いている曲:ピラミッド − ピラミッド ピラミッド - ピラミッド

| | コメント (0) | トラックバック (0)

2006年10月18日 (水)

Mac De PL/SQL RSS Reader #21

RSS Readerの続き。ドラフト版でのテストログの続き。(その3/6)

RDF (RSS 1.0) のFEEDをテストした結果。
RSS 0.91で登場したmegawattさんのブログなのだが、RDFでは記事の公開日が入っている。

---------------------- PROMPT RDF
begin...
====================
メガ放談 - 16 articles:
http://megawatt.blogdns.net/blog
====================
TITLE: アレルギーフリーな猫
URL : http://megawatt.blogdns.net/blog/304
Published on: 2006-10-11 16:42
—————————————-
TITLE: 猫は段ボールがお好き
URL : http://megawatt.blogdns.net/blog/303
Published on: 2006-10-10 11:16
—————————————-
TITLE: オクトーバーフェストに行ってきた
URL : http://megawatt.blogdns.net/blog/302
Published on: 2006-10-08 22:37
—————————————-
TITLE: オクトーバーフェストに行ってくる
URL : http://megawatt.blogdns.net/blog/301
Published on: 2006-10-07 22:30
—————————————-
TITLE: Old People
URL : http://megawatt.blogdns.net/blog/300
Published on: 2006-10-07 00:08
—————————————-
TITLE: ラップ音≠rap sounds
URL : http://megawatt.blogdns.net/blog/299
Published on: 2006-10-03 09:51
—————————————-
TITLE: 猫のための写真講座/2006年度前期・6
URL : http://megawatt.blogdns.net/blog/298
Published on: 2006-10-01 12:41
—————————————-
TITLE: 傷つきたくないからコミュニケーションしないという意見がある
URL : http://megawatt.blogdns.net/blog/297
Published on: 2006-09-28 13:23
—————————————-
TITLE: 英会話の日々
URL : http://megawatt.blogdns.net/blog/296
Published on: 2006-09-26 11:55
—————————————-
TITLE: コミュニケーション能力の減衰を食い止めるには
URL : http://megawatt.blogdns.net/blog/295
Published on: 2006-09-21 19:23
—————————————-
TITLE: くどかれました!?
URL : http://megawatt.blogdns.net/blog/294
Published on: 2006-09-19 21:43
—————————————-
TITLE: 大手町・日本工業倶楽部
URL : http://megawatt.blogdns.net/blog/293
Published on: 2006-09-18 12:59
—————————————-
TITLE: 役目を終える日
URL : http://megawatt.blogdns.net/blog/292
Published on: 2006-09-16 22:13
—————————————-
TITLE: 左向け〜
URL : http://megawatt.blogdns.net/blog/291
Published on: 2006-09-15 09:07
—————————————-
TITLE: 新しいiPod shuffleは買い、かなあ
URL : http://megawatt.blogdns.net/blog/290
Published on: 2006-09-14 16:15
—————————————-
TITLE: びーの枕
URL : http://megawatt.blogdns.net/blog/289
Published on: 2006-09-11 22:39
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。

テストログ、RSS 2.0へ続く。


そう言えば、小曽根真さんのBluenote Tokyoでのライブは、話も楽しい。
聞いている曲:小曽根真トリオ − Real 小曽根 真トリオ - Real - ダンス・オン・ザ・ビーチ

| | コメント (0) | トラックバック (0)

2006年10月17日 (火)

Mac De PL/SQL RSS Reader #20

RSS Readerの続き。ドラフト版でのテストログの続き。 (その2/6)。

RSS 0.92のFEEDをテストした結果(これも公開日が省略されている)

---------------------- PROMPT RSS 0.92
begin...
====================
AMIS Technology blog - 10 articles:
http://technology.amis.nl/blog
====================
TITLE: Rule based in Oracle 10g
URL : http://technology.amis.nl/blog/?p=1354
—————————————-
TITLE: Putting Analytical Functions to good use - find tables with multiple
foreign keys to the same referenced table
URL : http://technology.amis.nl/blog/?p=1353
—————————————-
TITLE: Extract Domain Definitions from Oracle Designer for use in JHeadstart
URL : http://technology.amis.nl/blog/?p=1352
—————————————-
TITLE: JHeadstart 10.1.3 Evaluation Copy available! - Everybody can now try out
JHeadstart for ADF Faces
URL : http://technology.amis.nl/blog/?p=1351
—————————————-
TITLE: SUSE support for next release of Oracle
URL : http://technology.amis.nl/blog/?p=1350
—————————————-
TITLE: JHeadstart 10.1.3 - Generating InputTextHyperlink items -
a generic custom generator template
URL : http://technology.amis.nl/blog/?p=1349
—————————————-
TITLE: ADF Faces: The InputTextHyperlink Component
URL : http://technology.amis.nl/blog/?p=1348
—————————————-
TITLE: Oracle BPEL PM 10.1.3 - Sending an Email to multiple recipients
URL : http://technology.amis.nl/blog/?p=1347
—————————————-
TITLE: Steve Muench publishes tutorial for JHeadstart 10.1.3 for ADF Faces
URL : http://technology.amis.nl/blog/?p=1346
—————————————-
TITLE: Unit testing with XFire ? How to test your SOAP server with a WSDL file
URL : http://technology.amis.nl/blog/?p=1345
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。


テストログ、RDF (RSS 1.0)へ続く。


ボコーダーで「ド・モ・ア・リ・ガ・ト・ミ・ス・タ・ー・ロ・ボ・ッ・ト」というところ、懐かしいですね。 思い切って、ボコーダーを使うという今時の勇気あるミュージシャン居ないかねぇ。(意外と、ウケたりして・・・)
聞いている曲: Styx - Styx Greatest Hits - Mr. RobotStyx - Styx: Greatest Hits - Mr. Roboto

| | コメント (0) | トラックバック (0)

2006年10月16日 (月)

Mac De PL/SQL RSS Reader #19

RSS Readerの続き。課題をクリアしたドラフト版でのテスト結果。
尚、ログが長いので、今回から、6回に分けて公開していく。(そんなに引っ張るなよ〜という声が遠くでするが・・・マイペース。)

テスト用のスクリプトは以下。

GLASSCATFISH> set serveroutput on
GLASSCATFISH> !cat rss_reader.sql
PROMPT -----------------------
PROMPT RSS 0.91
execute rss_reader('http://megawatt.blogdns.net/blog/rdf91_xml');
PROMPT -----------------------
PROMPT RSS 0.92
execute rss_reader('http://technology.amis.nl/blog/?feed=rss');
PROMPT -----------------------
PROMPT RDF
execute rss_reader('http://megawatt.blogdns.net/blog/rdf10_xml');
PROMPT -----------------------
PROMPT RSS 2.0
execute rss_reader('http://miwa2006.exblog.jp/index.xml');
PROMPT -----------------------
PROMPT ATOM 0.3
execute rss_reader('http://atsu-log.way-nifty.com/today_s_menu/atom.xml');
PROMPT -----------------------
PROMPT ATOM 1.0
execute rss_reader('http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/atom.xml');

RSS 0.91のFEEDをテストした結果。(公開日が省略されている)

GLASSCATFISH> @rss_reader
---------------------- PROMPT RSS 0.91
begin...
====================
メガ放談 - 16 articles:
http://megawatt.blogdns.net/blog
====================
TITLE: アレルギーフリーな猫
URL : http://megawatt.blogdns.net/blog/304
—————————————-
TITLE: 猫は段ボールがお好き
URL : http://megawatt.blogdns.net/blog/303
—————————————-
TITLE: オクトーバーフェストに行ってきた
URL : http://megawatt.blogdns.net/blog/302
—————————————-
TITLE: オクトーバーフェストに行ってくる
URL : http://megawatt.blogdns.net/blog/301
—————————————-
TITLE: Old People
URL : http://megawatt.blogdns.net/blog/300
—————————————-
TITLE: ラップ音≠rap sounds
URL : http://megawatt.blogdns.net/blog/299
—————————————-
TITLE: 猫のための写真講座/2006年度前期・6
URL : http://megawatt.blogdns.net/blog/298
—————————————-
TITLE: 傷つきたくないからコミュニケーションしないという意見がある
URL : http://megawatt.blogdns.net/blog/297
—————————————-
TITLE: 英会話の日々
URL : http://megawatt.blogdns.net/blog/296
—————————————-
TITLE: コミュニケーション能力の減衰を食い止めるには
URL : http://megawatt.blogdns.net/blog/295
—————————————-
TITLE: くどかれました!?
URL : http://megawatt.blogdns.net/blog/294
—————————————-
TITLE: 大手町・日本工業倶楽部
URL : http://megawatt.blogdns.net/blog/293
—————————————-
TITLE: 役目を終える日
URL : http://megawatt.blogdns.net/blog/292
—————————————-
TITLE: 左向け〜
URL : http://megawatt.blogdns.net/blog/291
—————————————-
TITLE: 新しいiPod shuffleは買い、かなあ
URL : http://megawatt.blogdns.net/blog/290
—————————————-
TITLE: びーの枕
URL : http://megawatt.blogdns.net/blog/289
—————————————-
...End

PL/SQLプロシージャが正常に完了しました。

テストログ、RSS 0.92へつづく。


今週から、Bluenote Tokyoで Candy Dulferのライブですね。ファンキーなサックスを楽しむのもいいかも。(そういえば、Candy Dulferのライブに行ったのはもう2年前くらいだったか? 昨年のMarcus Miller、今年のDave Koz Dave Koz - The Dance のライブの次に面白しいライブでした。)今年も楽しませてくれることでしょう。

| | コメント (0) | トラックバック (0)

2006年10月14日 (土)

Mac De PL/SQL RSS Reader #18

RSS Readerの続き。問題点の回避方法。

以下は、各FEEDのルート要素を示したものだが、違いがお分かりだろうか?

<rss version="0.92">

<rss version="0.91">

<rss version="2.0"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:admin="http://webns.net/mvcb/"
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:admin="http://webns.net/mvcb/"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:cc="http://web.resource.org/cc/"
xmlns="http://purl.org/rss/1.0/">

<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:admin="http://webns.net/mvcb/"
xmlns="http://purl.org/rss/1.0/">

<feed version="0.3"
 xmlns="http://purl.org/atom/ns#"
 xmlns:dc="http://purl.org/dc/elements/1.1/">

<feed xmlns="http://www.w3.org/2005/Atom">

もう、気付きましたよね?! そう!。 違いは、Namespaceが宣言されている点なのである。
しかも、同じ RDFでも微妙に異なる場合もある。ということで、ORA-30625というエラーの原因は、Namespaceを指定すれば解決できそうである。

残りのORA-31011については、解析に失敗していことから、おそらく、文字化けが影響しているものと想像できる。(以前にも似たようなことがあったが文字化けを回避することで解決した。

それらを踏まえてテスト用のコードを修正(前回のコードに比べると可成りコード量が増えます)し再度、確認してみると、

RSS 2.0ーー(前回はこんなエラーであった。

GLASSCATFISH> l
1 declare
2 v_req UTL_HTTP.REQ;
3 v_resp UTL_HTTP.RESP;
4 v_source VARCHAR2(1024);
5 v_tempSourceClob CLOB;
6 v_myParser DBMS_XMLPARSER.Parser;
7 v_rssDoc DBMS_XMLDOM.DomDocument;
8 v_uri httpUriType;
9 v_xml xmlType;
10 c_namespace CONSTANT VARCHAR2(500) :=
11 'xmlns:dc="http://purl.org/dc/elements/1.1/" '
12 ||'xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" '
13 ||'xmlns:admin="http://webns.net/mvcb/" '
14 ||'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"';
15 begin
16 v_req := UTL_HTTP.BEGIN_REQUEST('http://miwa2006.exblog.jp/index.xml');
17 UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
18 UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
19 v_resp := UTL_HTTP.GET_RESPONSE(v_req);
20 DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
21 BEGIN
22 LOOP
23 UTL_HTTP.READ_LINE(v_resp, v_source, true);
24 v_source := v_source || UTL_TCP.CRLF;
25 DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
26 END LOOP;
27 EXCEPTION
28 WHEN UTL_HTTP.END_OF_BODY THEN
29 UTL_HTTP.END_RESPONSE(v_resp);
30 END;
31 v_myParser := DBMS_XMLPARSER.NEWPARSER();
32 DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
33 v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
34 v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
35 dbms_output.put_line(
36 XmlType.extract(
37 v_xml, '/rss/channel/title/text()', c_namespace
38 ).getStringVal()
39 );
40 dbms_output.put_line(
41 XmlType.extract(
42 v_xml, '/rss/channel/link/text()', c_namespace
43 ).getStringVal()
44 );
45* end;
GLASSCATFISH> /
Life is a trip of looking for myself !
http://miwa2006.exblog.jp

PL/SQLプロシージャが正常に完了しました。

RDFーー(前回はこのようなエラーであった。

GLASSCATFISH> l
1 declare
2 v_req UTL_HTTP.REQ;
3 v_resp UTL_HTTP.RESP;
4 v_source VARCHAR2(1024);
5 v_tempSourceClob CLOB;
6 v_myParser DBMS_XMLPARSER.Parser;
7 v_rssDoc DBMS_XMLDOM.DomDocument;
8 v_uri httpUriType;
9 v_xml xmlType;
10 c_namespace CONSTANT VARCHAR2(500) :=
11 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" '
12 ||'xmlns:dc="http://purl.org/dc/elements/1.1/" '
13 ||'xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" '
14 ||'xmlns:admin="http://webns.net/mvcb/" '
15 ||'xmlns:content="http://purl.org/rss/1.0/modules/content/" '
16 ||'xmlns:cc="http://web.resource.org/cc/" '
17 ||'xmlns="http://purl.org/rss/1.0/"';
18 begin
19 v_req := UTL_HTTP.BEGIN_REQUEST(
20 'http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/index.rdf'
21 );
22 UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
23 UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
24 v_resp := UTL_HTTP.GET_RESPONSE(v_req);
25 DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
26 BEGIN
27 LOOP
28 UTL_HTTP.READ_LINE(v_resp, v_source, true);
29 v_source := v_source || UTL_TCP.CRLF;
30 DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
31 END LOOP;
32 EXCEPTION
33 WHEN UTL_HTTP.END_OF_BODY THEN
34 UTL_HTTP.END_RESPONSE(v_resp);
35 END;
36 v_myParser := DBMS_XMLPARSER.NEWPARSER();
37 DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
38 v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
39 v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
40 dbms_output.put_line(
41 XmlType.extract(
42 v_xml, '/rdf:RDF/channel/title/text()', c_namespace
43 ).getStringVal()
44 );
45 dbms_output.put_line(
46 XmlType.extract(
47 v_xml, '/rdf:RDF/channel/link/text()', c_namespace
48 ).getStringVal()
49 );
50* end;
GLASSCATFISH> /
Mac De Oracle
http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/

PL/SQLプロシージャが正常に完了しました。

GLASSCATFISH> l
1 declare
2 v_req UTL_HTTP.REQ;
3 v_resp UTL_HTTP.RESP;
4 v_source VARCHAR2(1024);
5 v_tempSourceClob CLOB;
6 v_myParser DBMS_XMLPARSER.Parser;
7 v_rssDoc DBMS_XMLDOM.DomDocument;
8 v_uri httpUriType;
9 v_xml xmlType;
10 c_namespace CONSTANT VARCHAR2(500) :=
11 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" '
12 ||'xmlns:dc="http://purl.org/dc/elements/1.1/" '
13 ||'xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" '
14 ||'xmlns:admin="http://webns.net/mvcb/" '
15 ||'xmlns="http://purl.org/rss/1.0/"';
16 begin
17 v_req := UTL_HTTP.BEGIN_REQUEST(
18 'http://megawatt.blogdns.net/blog/rdf10_xml'
19 );
20 UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
21 UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
22 v_resp := UTL_HTTP.GET_RESPONSE(v_req);
23 DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
24 BEGIN
25 LOOP
26 UTL_HTTP.READ_LINE(v_resp, v_source, true);
27 v_source := v_source || UTL_TCP.CRLF;
28 DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
29 END LOOP;
30 EXCEPTION
31 WHEN UTL_HTTP.END_OF_BODY THEN
32 UTL_HTTP.END_RESPONSE(v_resp);
33 END;
34 v_myParser := DBMS_XMLPARSER.NEWPARSER();
35 DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
36 v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
37 v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
38 dbms_output.put_line(
39 XmlType.extract(
40 v_xml, '/rdf:RDF/channel/title/text()', c_namespace
41 ).getStringVal()
42 );
43 dbms_output.put_line(
44 XmlType.extract(
45 v_xml, '/rdf:RDF/channel/link/text()', c_namespace
46 ).getStringVal()
47 );
48* end;
GLASSCATFISH> /
メガ放談
http://megawatt.blogdns.net/blog

PL/SQLプロシージャが正常に完了しました。

最後にATOMーー(前回はこのようなエラーであった

GLASSCATFISH> l
1 declare
2 v_req UTL_HTTP.REQ;
3 v_resp UTL_HTTP.RESP;
4 v_source VARCHAR2(1024);
5 v_tempSourceClob CLOB;
6 v_myParser DBMS_XMLPARSER.Parser;
7 v_rssDoc DBMS_XMLDOM.DomDocument;
8 v_uri httpUriType;
9 v_xml xmlType;
10 c_namespace CONSTANT VARCHAR2(500) :=
11 'xmlns="http://purl.org/atom/ns#" '
12 ||'xmlns:dc="http://purl.org/dc/elements/1.1/"';
13 begin
14 v_req := UTL_HTTP.BEGIN_REQUEST(
15 'http://atsu-log.way-nifty.com/today_s_menu/atom.xml'
16 );
17 UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
18 UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
19 v_resp := UTL_HTTP.GET_RESPONSE(v_req);
20 DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
21 BEGIN
22 LOOP
23 UTL_HTTP.READ_LINE(v_resp, v_source, true);
24 v_source := v_source || UTL_TCP.CRLF;
25 DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
26 END LOOP;
27 EXCEPTION
28 WHEN UTL_HTTP.END_OF_BODY THEN
29 UTL_HTTP.END_RESPONSE(v_resp);
30 END;
31 v_myParser := DBMS_XMLPARSER.NEWPARSER();
32 DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
33 v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
34 v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
35 dbms_output.put_line(
36 XmlType.extract(
37 v_xml, '/feed/title/text()', c_namespace
38 ).getStringVal()
39 );
40 dbms_output.put_line(
41 XmlType.extract(
42 v_xml, '/feed/link[@type="text/html"]/@href', c_namespace
43 ).getStringVal()
44 );
45* end;
GLASSCATFISH> /
今日のゴハン
http://atsu-log.way-nifty.com/today_s_menu/

PL/SQLプロシージャが正常に完了しました。

GLASSCATFISH>
GLASSCATFISH> l
1 declare
2 v_req UTL_HTTP.REQ;
3 v_resp UTL_HTTP.RESP;
4 v_source VARCHAR2(1024);
5 v_tempSourceClob CLOB;
6 v_myParser DBMS_XMLPARSER.Parser;
7 v_rssDoc DBMS_XMLDOM.DomDocument;
8 v_uri httpUriType;
9 v_xml xmlType;
10 c_namespace CONSTANT VARCHAR2(500) :=
11 'xmlns="http://www.w3.org/2005/Atom"';
12 begin
13 v_req := UTL_HTTP.BEGIN_REQUEST(
14 'http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/atom.xml'
15 );
16 UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1;');
17 UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
18 v_resp := UTL_HTTP.GET_RESPONSE(v_req);
19 DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
20 BEGIN
21 LOOP
22 UTL_HTTP.READ_LINE(v_resp, v_source, true);
23 v_source := v_source || UTL_TCP.CRLF;
24 DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
25 END LOOP;
26 EXCEPTION
27 WHEN UTL_HTTP.END_OF_BODY THEN
28 UTL_HTTP.END_RESPONSE(v_resp);
29 END;
30 v_myParser := DBMS_XMLPARSER.NEWPARSER();
31 DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
32 v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
33 v_xml := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
34 dbms_output.put_line(
35 XmlType.extract(
36 v_xml, '/feed/title/text()', c_namespace
37 ).getStringVal()
38 );
39 dbms_output.put_line(
40 XmlType.extract(
41 v_xml, '/feed/link[@type="text/html"]/@href', c_namespace
42 ).getStringVal()
43 );
44* end;
GLASSCATFISH> /
Radical Imagination -from 鎌倉 with Love
http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/

PL/SQLプロシージャが正常に完了しました。

GLASSCATFISH>

ということで、全て解決!!。




ほんとうに曲数が少ないのは iTMSの抱える課題だ。ということで、今回もAmazonへ

聞いている曲:Candy Dulfer - ベスト・オブ・キャンディ・ダルファー

| | コメント (0) | トラックバック (0)

2006年10月13日 (金)

Mac De PL/SQL RSS Reader #17

RSS Readerの続きです。
さて、RSSリーダーを作る上でもう一つクリアしておきたい課題がある。
それは、各記事のタイトルとURL、公開日以外に、各FEEDのタイトルとURLを取得すること。

BLOGに関して、それぞれの記事のタイトルとURL以外に、BLOGのタイトルとURLも表示したいと考えている。
作成中のRSSリーダーでは、DOMを利用していので、そのBLOGのタイトルとURLもDOMをトラバースして取得することも可能なのだが、ロジックが複雑になるため、BLOGのタイトルとURLに関しては、XPATHを利用して取り出すことにした。

当初、DBMS_XMLPARSER.PARSE(URL)を利用しようとしていたが、URL指定でパースした場合にマルチバイト文字で文字化けが発生したため、UTL_HTTPパッケージDBMS_XMLPARSER.PARSECLOB(CLOB)を使用して回避している。XPATHを利用しBLOGタイトルとURIの取得テストでは、DBMS_XMLPARSER.PARSE(URL)同様に文字化けするのだが、HttpUriType型を利用してXML(XmlType型)を取り出し、XPATHでBLOGタイトルとURLを取得することにした。
HttpUriType型と、XmlType型の2つはどちらもオブジェクト型である。詳細は、マニュアル「PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス」のXmlTypeHttpUriType参照のこと。

以下は、RSS 0.92 の FEEDである「AMIS Technorogy blog」のタイトルとURLをXPATHを利用して取り出したもの。シングルバイトなので文字化けは起こらない。楽でいいね〜。マルチバイト文字が含まれていても文字化けしなくなれば、この方法が利用できるようになるので楽なのだが、Oracleさんなんとかして。。。

GLASSCATFISH> set serveroutput on
GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://technology.amis.nl/blog/?feed=rss');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/rss/channel/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/rss/channel/link/text()').getStringVal());
9* end;
GLASSCATFISH> /
AMIS Technology blog
http://technology.amis.nl/blog

PL/SQLプロシージャが正常に完了しました。

GLASSCATFISH>

ところが、友人のmegawattさんの「メガ放談」(RSS 0.91) のタイトルとURLをXPATHを利用して取り出すと、タイトルは見事に文字化けする。DBMS_XMLPARSER.PARSE(URL)を利用した場合と同じく文字化けするが、取り出せることは取り出せる。文字化けの回避方法はあるのでとりあえずこのままテスト続行!。

GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://megawatt.blogdns.net/blog/rdf91_xml');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/rss/channel/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/rss/channel/link/text()').getStringVal());
9* end;
GLASSCATFISH> /
a?!a?¬a??e≪?
http://megawatt.blogdns.net/blog

PL/SQLプロシージャが正常に完了しました。

3つ目は、RSS 2.0なのだが、RSS 0.9xとは異なりエラーとなる。何故?
幸か不幸か、今回は、RSS 0.9x以外のFEEDフォーマットにも対応しなければならない。

GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://miwa2006.exblog.jp/index.xml');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/rss/channel/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/rss/channel/link/text()').getStringVal());
9* end;
GLASSCATFISH> /
declare
*
行1でエラーが発生しました。:
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00225: 要素の終了タグ"item"が開始タグ"title"と一致しません
Error at line 94
中にエラーが発生しました
ORA-06512: "SYS.XMLTYPE", 行5
ORA-06512: "SYS.HTTPURITYPE", 行97
ORA-06512: 行6


GLASSCATFISH>

つづいて、RDF (RSS 1.0)を試す。どちらも、RDFなのだが上手くいかない。しかも、エラーメッセージがそれぞれ異なる。なぜ?? 

GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://discus-hamburg.cocolog-nifty.com/mac_de_oracle/index.rdf');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/rdf:RDF/channel/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/rdf:RDF/channel/link/text()').getStringVal());
9* end;
GLASSCATFISH> /
declare
*
行1でエラーが発生しました。:
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00225: 要素の終了タグ"channel"が開始タグ"description"と一致しません
Error at line 42
中にエラーが発生しました
ORA-06512: "SYS.XMLTYPE", 行5
ORA-06512: "SYS.HTTPURITYPE", 行97
ORA-06512: 行6


GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://megawatt.blogdns.net/blog/rdf10_xml');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/rdf:RDF/channel/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/rdf:RDF/channel/link/text()').getStringVal());
9* end;
GLASSCATFISH> /
declare
*
行1でエラーが発生しました。:
ORA-30625: NULL SELF引数のメソッド・ディスパッチは使用できません
ORA-06512: 行7


GLASSCATFISH>


最後にATOM。結果は、RSS 2.0、RDF、ATOMは撃沈である。ここでも、エラー内容がそれぞれ異なる。
この方法では、上手くいったのは、RSS 0.9xのみ。 どうする。。 (><)。
GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://atsu-log.way-nifty.com/today_s_menu/atom.xml');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/feed/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/feed/link[@type="text/html"]/@href').getStringVal());
9* end;
GLASSCATFISH> /
declare
*
行1でエラーが発生しました。:
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00225: 要素の終了タグ"a"が開始タグ"p"と一致しません
Error at line 30
中にエラーが発生しました
ORA-06512: "SYS.XMLTYPE", 行5
ORA-06512: "SYS.HTTPURITYPE", 行97
ORA-06512: 行6

GLASSCATFISH> l
1 declare
2 v_uri httpUriType;
3 v_xml xmlType;
4 begin
5 v_uri := HttpUriType.createUri('http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/atom.xml');
6 v_xml := v_uri.getXML();
7 dbms_output.put_line(v_xml.extract('/feed/title/text()').getStringVal());
8 dbms_output.put_line(v_xml.extract('/feed/link[@type="text/html"]/@href').getStringVal());
9* end;
GLASSCATFISH> /
declare
*
行1でエラーが発生しました。:
ORA-30625: NULL SELF引数のメソッド・ディスパッチは使用できません
ORA-06512: 行7


GLASSCATFISH>

これらの解決方法は????

エラーメッセージもいろいろ。上記のコードを眺めていても原因は全く浮かばない。

視点を変え、各FEEDのXMLソースを眺めると、RSS 0.9xとRSS2.0、RDF、ATOMのXMLには異なる点があるのみ気付く。それが何か分かりますか? このエラー原因の一なのである。
http://technology.amis.nl/blog/?feed=rss
http://megawatt.blogdns.net/blog/rdf91_xml
http://miwa2006.exblog.jp/index.xml
http://megawatt.blogdns.net/blog/rdf10_xml
http://atsu-log.way-nifty.com/today_s_menu/atom.xml
http://www.kaminoge-design.tamabi.ac.jp/faculty/takami/atom.xml


今日はここまで、次回はこれらの回避方法。



聞いている曲:え〜〜と、iTMSにはこれもありませんでした。。Gloria Estefan & Miami Sound Machine - 1.2.3

| | コメント (0) | トラックバック (0)

2006年10月12日 (木)

Mac De PL/SQL RSS Reader #16

前回のつづき。rfc3339の日付/日時フォーマット対応ストアドプロシージャのソースコードは以下。。

create or replace FUNCTION RFC3339_DateStrToTimeStampLTZ
(
i_dateTimeString IN VARCHAR2
)
RETURN TIMESTAMP WITH LOCAL TIME ZONE
AS
v_tempTimeStampTz TIMESTAMP WITH LOCAL TIME ZONE := NULL;
v_dateTimeString VARCHAR2(50) := NULL;
v_timeStampTzFormat VARCHAR2(40) := NULL;
c_nls_date_language CONSTANT VARCHAR2(40) := 'NLS_DATE_LANGUAGE=AMERICAN';
BEGIN
v_dateTimeString := REGEXP_REPLACE(
REGEXP_REPLACE(
UPPER(i_dateTimeString),
'T', NULL, 1, 1
),
'Z$', 'UTC'
);

IF v_dateTimeString IS NULL THEN
RETURN NULL;
END IF;


v_timeStampTzFormat := 'RRRR-MM-DD';

IF LENGTH(v_dateTimeString) >= 10 THEN

IF REGEXP_INSTR(v_dateTimeString , '([0-9]{2}:){2}[0-9]{2}\.?') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI:SSXFF';
END IF;

IF REGEXP_INSTR(v_dateTimeString, '(\+|\-)[0-9]{2}:[0-9]{2}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZH:TZM';
ELSIF REGEXP_INSTR(v_dateTimeString, 'UTC$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZR';
END IF;
END IF;

v_tempTimeStampTz := TO_TIMESTAMP_TZ(
v_dateTimeString,
v_timeStampTzFormat,
c_nls_date_language
);

RETURN v_tempTimeStampTz;

EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(
-20002,
'RFC3339_DateStrToTimeStampLTZ():' || SQLERRM()
);
END;
/
前々回も書いたように、入力される文字列はrfc3339日付/日時フォーマットを前提としているため、入力書式の厳密なチェックなどは行っていない。
聞いている曲:
やはり、80sにはすばらしい曲、というか記憶に残る曲が多いよね。 まぁ、このAvalonに関しては、日産のCMで使われたりしたので最近の曲? という方も多いのだけれど。。。
Roxy Music - Avalon - The Space Between Roxy Music - Avalon - The Space Between

| | コメント (0) | トラックバック (0)

2006年10月11日 (水)

Mac De PL/SQL RSS Reader #15

前回のつづき。簡単なテスト。

GLASSCATFISH> !cat rfc3339_func_test.sql
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02.25Z') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02Z') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02+09:00') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02-09:00') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02.25-09:00') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13T18:30:02.25+09:00') from dual;
select rfc3339_datestrtotimestampltz('2003-12-13') from dual;

GLASSCATFISH> @rfc3339_func_test

RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02.25Z')
---------------------------------------------------------------------------
03-12-14 03:30:02.250000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02Z')
---------------------------------------------------------------------------
03-12-14 03:30:02.000000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02+09:00')
---------------------------------------------------------------------------
03-12-13 18:30:02.000000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02-09:00')
---------------------------------------------------------------------------
03-12-14 12:30:02.000000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02.25-09:00')
---------------------------------------------------------------------------
03-12-14 12:30:02.250000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13T18:30:02.25+09:00')
---------------------------------------------------------------------------
03-12-13 18:30:02.250000000


RFC3339_DATESTRTOTIMESTAMPLTZ('2003-12-13')
---------------------------------------------------------------------------
03-12-13 00:00:00.000000000

GLASSCATFISH>

rfc822よりはシンプルね。

今日はここまで。次回はソースコードを載せる予定。



聞いている曲:iTMS Japanの曲の少なさはまだまだ改善されず。。。まあ、Tribute Albumも悪くないんですが、やはり、オリジナルも聞きたいわけで。。。iTMS Japanに無いものはAmazonか。。
Sade Tribute Band - Smooth Sax Tribute To Sade Sade Tribute Band - Smooth Sax Tribute To Sade - Smooth Operator



| | コメント (0) | トラックバック (0)

2006年10月10日 (火)

Mac De PL/SQL RSS Reader #14

前回につづき、今回は、rfc3339の日付/時間フォーマット向けに、暫定版として RFC3339_DateStrToTimeStampLTZ()というストアドプロシージャを作ってみた。この関数も、rfc3339日付/時間フォーマットを文字列として入力し、TIMESTAMP WITH LOCAL TIME ZONE型で返すようにした。

尚、rfc3339で規定されている time-offset の "Z"は、ストアドファンクション内部で "UTC"に変換して扱うことにした。

また、入力する文字列もrfc3339の日付/時間フォーマットであることを前提とし、 RFC3339_DateStrToTimeStampLTZ()ファンクション内部ではフォーマットの厳密な等は行わない。(但し、オラクルのTO_TIMESTAMP_TZ()関数では、オラクルの日付/時間書式に対するチェックは行われる。)


次回は、簡単なテストとソースコードを載せる予定。


秋、おいしいワインの新酒が楽しみな季節になってきました。今年のできはどうなんだろう? などど思いながら、私のお気に入り、高畠ワイナリーのブログを見ると、、、「予想以上」というタイトル!。 しかし、ワインの話ではなく、昨日まで開催さてていた、恒例の「秋の収穫祭」の来場者の話題でした。。。(^^;;

ところで、高畠ワイナリーさん主催のワインセミナーがあったと記憶しているが、最近はどうなんだろう?。ホームページを見ても書いていないので、時間が取れそうなら確認してみようかと。

以前(といっても、もう7年も前だが)、私も参加したことがある。高畠ワイナリーで生産しているワインをテイスティングしてワインの楽しみ方を知るというもの(とは言っても、入門レベルだけど、これが結構楽しい)

その時に貰ったセミナーの終了証がこれ。(ちなみにワインセミナーは、ワイナリー内で行われていたので、当日は、新幹線で日帰りした記憶が・・・・・。結構、飲む事になるので、車では絶対行けませんよ。)

Takahata_wine_certified

奥さんのブログ「今日のゴハン」でもなんどか書いてましたね。

| | コメント (0) | トラックバック (0)

2006年10月 9日 (月)

Mac De PL/SQL RSS Reader #13

前回の続き。ストアドファンクションrfc822_dateStrToTimestampLTZ()のソースコードは以下の通り。

CREATE OR REPLACE FUNCTION RFC822_DateStrToTimeStampLTZ
(
i_dateTimeString IN VARCHAR2
)
RETURN TIMESTAMP WITH LOCAL TIME ZONE
AS
v_tempTimeStampTz TIMESTAMP WITH LOCAL TIME ZONE := NULL;
v_dateTimeString VARCHAR2(50) := NULL;
v_timeStampTzFormat VARCHAR2(40) := NULL;
c_nls_date_language CONSTANT VARCHAR2(40) := 'NLS_DATE_LANGUAGE=AMERICAN';
BEGIN
v_dateTimeString := UPPER(i_dateTimeString);
IF v_dateTimeString IS NULL THEN
RETURN NULL;
END IF;

IF REGEXP_INSTR(v_dateTimeString, '^[A-Z]{3}\, ') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'DY, ';
END IF;

v_timeStampTzFormat := v_timeStampTzFormat || 'DD MON RRRR';

IF REGEXP_INSTR(v_dateTimeString, '[0-9]{2}:[0-9]{2}:[0-9]{2}') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI:SS ';
ELSIF REGEXP_INSTR(v_dateTimeString, '[0-9]{2}:[0-9]{2}') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'HH24:MI ';
END IF;

IF REGEXP_INSTR(v_dateTimeString, ' (\+|\-)[0-9]{4}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZHTZM';
ELSIF REGEXP_INSTR(v_dateTimeString, ':[0-9]{2}$') = 0
AND REGEXP_INSTR(v_dateTImeString, '[0-9]{2} [A-Z]{3} [0-9]{2,4}$') = 0
AND REGEXP_INSTR(v_dateTImeString, ' [A-Z]{1,3}$') >= 1 THEN
v_timeStampTzFormat := v_timeStampTzFormat || 'TZR';
END IF;

v_tempTimeStampTz := TO_TIMESTAMP_TZ(
v_dateTimeString,
v_timeStampTzFormat,
c_nls_date_language
);

RETURN v_tempTimeStampTz;

EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(
-20001,
'RFC822_DateStrToTimeStampLTZ():' || SQLERRM()
);
END;
/

というように、日付/時間文字列を一旦、TO_TIMESTAMP_TZ()関数でTIMESTAMP WITH TIME ZONE型に変換する。この時点でタイムゾーンリージョンが指定されていれば、夏時間も考慮され変換される。最終的に、TIMESTAMP WITH LOCAL TIME ZONE型で返すようにした。(尚、入力される日付/日時文字列が、RFC822形式であることを前提にしているため文字列妥当性などのチェックは厳密は行っていない。)

・・・・ファンクション名は変えたほうがいいか・・・・



聞いている曲:今日もSmooth Jazzで。
Warren Hill - Popjazz - Toronto Warren Hill - Popjazz - Toronto

| | コメント (0) | トラックバック (0)

2006年10月 8日 (日)

Mac De PL/SQL RSS Reader #12

PL/SQL RSS Readerの続きです。では、早速、rfc822_dateStrToTimestampLTZ()のテストから、

GLASSCATFISH> !cat rfc822_func_test.sql
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 GMT') from dual;
select rfc822_datestrtotimestampltz('07 Sep 2002 00:00:01 GMT') from dual;
select rfc822_datestrtotimestampltz('07 Sep 02 00:00:01 GMT') from dual;
select rfc822_datestrtotimestampltz('07 Sep 02 00:00 GMT') from dual;
select rfc822_datestrtotimestampltz('07 Sep 02') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 02 00:00:01 +0900') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 02 00:00:01 -0900') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 EST') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 CST') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 MST') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 PST') from dual;
select rfc822_datestrtotimestampltz('Sun, 8 Oct 2006 07:00:00 +0900') from dual;
select rfc822_datestrtotimestampltz('Sat, 7 Oct 2006 22:00:00 GMT') from dual;
PROMPT 夏時間の確認
select rfc822_datestrtotimestampltz('7 Oct 2006 18:00:00 EST') from dual;
select rfc822_datestrtotimestampltz('7 Oct 2006 18:00:00 -0500') from dual;
select rfc822_datestrtotimestampltz('7 Oct 2006 18:00:00 -0400') from dual;
select rfc822_datestrtotimestampltz('31 Oct 2006 22:00:00 EST') from dual;
select rfc822_datestrtotimestampltz('31 Oct 2006 22:00:00 -0500') from dual;
select rfc822_datestrtotimestampltz('31 Oct 2006 22:00:00 -0400') from dual;
PROMPT オラクルのタイムゾーンリージョンに無いコード
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 EDT') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 CDT') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 MDT') from dual;
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 PDT') from dual;
--
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 UT') from dual;


GLASSCATFISH> @rfc822_func_test

RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP200200:00:01GMT')
---------------------------------------------------------------------------
02-09-07 09:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('07SEP200200:00:01GMT')
---------------------------------------------------------------------------
02-09-07 09:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('07SEP0200:00:01GMT')
---------------------------------------------------------------------------
02-09-07 09:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('07SEP0200:00GMT')
---------------------------------------------------------------------------
02-09-07 09:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('07SEP02')
---------------------------------------------------------------------------
02-09-07 00:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP0200:00:01+0900')
---------------------------------------------------------------------------
02-09-07 00:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP0200:00:01-0900')
---------------------------------------------------------------------------
02-09-07 18:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP200200:00:01EST')
---------------------------------------------------------------------------
02-09-07 13:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP200200:00:01CST')
---------------------------------------------------------------------------
02-09-07 14:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP200200:00:01MST')
---------------------------------------------------------------------------
02-09-07 15:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,07SEP200200:00:01PST')
---------------------------------------------------------------------------
02-09-07 16:00:01.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SUN,8OCT200607:00:00+0900')
---------------------------------------------------------------------------
06-10-08 07:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('SAT,7OCT200622:00:00GMT')
---------------------------------------------------------------------------
06-10-08 07:00:00.000000000

夏時間の確認

RFC822_DATESTRTOTIMESTAMPLTZ('7OCT200618:00:00EST')
---------------------------------------------------------------------------
06-10-08 07:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('7OCT200618:00:00-0500')
---------------------------------------------------------------------------
06-10-08 08:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('7OCT200618:00:00-0400')
---------------------------------------------------------------------------
06-10-08 07:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('31OCT200622:00:00EST')
---------------------------------------------------------------------------
06-11-01 12:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('31OCT200622:00:00-0500')
---------------------------------------------------------------------------
06-11-01 12:00:00.000000000


RFC822_DATESTRTOTIMESTAMPLTZ('31OCT200622:00:00-0400')
---------------------------------------------------------------------------
06-11-01 11:00:00.000000000

オラクルのタイムゾーンリージョンに無いコード
select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 EDT') from dual
*
行1でエラーが発生しました。:
ORA-20001: RFC822_DateStrToTimeStampLTZ():ORA-01882:
タイムゾーンのリージョンが見つかりません。
ORA-06512: "GLASSCATFISH.RFC822_DATESTRTOTIMESTAMPLTZ", 行48


select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 CDT') from dual
*
行1でエラーが発生しました。:
ORA-20001: RFC822_DateStrToTimeStampLTZ():ORA-01882:
タイムゾーンのリージョンが見つかりません。
ORA-06512: "GLASSCATFISH.RFC822_DATESTRTOTIMESTAMPLTZ", 行48v

select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 MDT') from dual
*
行1でエラーが発生しました。:
ORA-20001: RFC822_DateStrToTimeStampLTZ():ORA-01882:
タイムゾーンのリージョンが見つかりません。
ORA-06512: "GLASSCATFISH.RFC822_DATESTRTOTIMESTAMPLTZ", 行48


select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 PDT') from dual
*
行1でエラーが発生しました。:
ORA-20001: RFC822_DateStrToTimeStampLTZ():ORA-01882:
タイムゾーンのリージョンが見つかりません。
ORA-06512: "GLASSCATFISH.RFC822_DATESTRTOTIMESTAMPLTZ", 行48


select rfc822_datestrtotimestampltz('Sat, 07 Sep 2002 00:00:01 UT') from dual
*
行1でエラーが発生しました。:
ORA-20001: RFC822_DateStrToTimeStampLTZ():ORA-01882:
タイムゾーンのリージョンが見つかりません。
ORA-06512: "GLASSCATFISH.RFC822_DATESTRTOTIMESTAMPLTZ", 行48


GLASSCATFISH>

と、このような感じになる。夏時間は自動計算されているようだ。
ということは・・・、"EDT"/"CDT"/"MDT"/"PDT"は単純に"EST"/"CST"/"MST"/"PST"に置換するだけで対応できるかも!?

テストのログが長くなってしまったので、今日はここまで。ストアドファンクションのソースコードは次回。



いろいろと行事があって、少々疲れ気味。。。やはりこんなときは、Smooth Jazz....
ということで、今日も Internet Radio SmoothJazz.com

| | コメント (0) | トラックバック (0)

2006年10月 7日 (土)

Mac De PL/SQL RSS Reader #11

PL/SQLで RSS Readerの続きです。

feedの日付/時間は、rfc822または、rfc3339に準拠ということだった。
今回は、元のタイムゾーンは重要ではないので、timestamp with local time zone型に変換して持つことにした。

まず、暫定だがrfc822向けに、rfc822_dateStrToTimestampLTZ()というストアドファンクションを作成した。
rfc822形式の日時文字列をOracle10g の Timestamp with local time zone型に変換するストアドファンクションである。

尚、rfc822のタイムゾーンとして、

     zone        =  "UT"  / "GMT"

/ "EST" / "EDT"
/ "CST" / "CDT"
/ "MST" / "MDT"
/ "PST" / "PDT"
/ 1ALPHA

/ ( ("+" / "-") 4DIGIT )

と規定されているが、"UT"及び、夏時間(*DT)、英字1文字以外についてのみ実装した。(Oracle10gのto_timestamp_tz()関数で指定できるタイムゾーンリージョン "GMT"/"EST"/"CST"/"MST"/"PST" だけに対応した。"UT"、夏時間、英字1文字、または、上記、以外のタイムゾーンが設定されているような状況があれば、その時に考えることに。ちなみに、私が購読しているblogのfeedでは、"GMT"しか利用されていないのも理由の一つである。)

Oracle10gで指定できるタイムゾーンリージョンは以下のようにして確認できる。詳細は、「マニュアル「Oracle10 database SQLクイック・リファレンス 10g」を参照のこと

SYS> select
2 unique tzname
3 from
4 v$timezone_names
5 where
6 tzname in (
7 'UT','GMT','EST','EDT','CST','CDT','MST','MDT','PST','PDT'
8 )
9 or length(tzname)=1;


TZNAME
------------