OS X版のsdcliを実行するには実行権を付与する必要があります。sdcliは以下のパスにあります。かなり深いところにあります!
(OS X版は以下深いところにあるので、SQLDeveloperのアイコン上で右クリック>コンテクストメニュー>パッケージの内容を表示から辿ってパスを探してもいいですし、以下のパス直接コピペでも行けます。)
Oracle SQL Developer Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
format input=<入力ファイルまたはディレクトリ> output=<出力ファイルまたはディレクトリ> 成功しました。 discus-mother:˜ oracle$
以下のようなSQL文を整形してみます。
discus-mother:˜ oracle$ cat sample_unformated.sql select a.id,a.name,b.location,b.phone_no from foo a innter join bar b on a.id = b.id order by a.name;
意外と地味な感じの処理終了メッセージですが、整形できたようです。整形結果を確認!
discus-mother:˜ oracle$ sdcli format input=sample_unformated.sql output=sample_formated.sql
Oracle SQL Developer Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
成功しました。 discus-mother:˜ oracle$
いいですね〜 :) 最後の改行がないのですは、ご愛嬌ということで.
discus-mother:˜ oracle$ cat sample_formated.sql SELECT a.id, a.name, b.location, b.phone_no FROM foo a innter JOIN bar b ON a.id = b.id ORDER BY a.name;discus-mother:˜ oracle$ discus-mother:˜ oracle$
guppy:datamodeler discus$ ./datamodeler.sh & [1] 891 guppy:datamodeler discus$ Oracle SQL Developer Data Modeler Copyright (c) 1997, 2009, Oracle and/or its affiliates.All rights reserved.
java.lang.UnsupportedClassVersionError: Bad version number in .class file at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:620) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) at java.net.URLClassLoader.access$100(URLClassLoader.java:56) at java.net.URLClassLoader$1.run(URLClassLoader.java:195) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) Exception in thread "main" ll
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;
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;
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
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> /
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;
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;
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> 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;
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;
尚、今回は、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
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;
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;
create or replace PROCEDURE multiLevelCollections AS TYPE NestedTableType IS TABLE OF empType; TYPE StrAssociativeArrayType IS TABLE OF NestedTableType INDEX BY VARCHAR2(50);
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;
# ============================================================================ # 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>
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=>'アップロード');
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('-> ' || 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;
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;
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=>'アップロード');
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('-> ' || 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
・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
# ============================================================================ # 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>
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している画面のスナップショット。
ちなみに、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.
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).
PROCEDURE close_bfile ( i_bfile IN OUT NOCOPY BFILE ) IS BEGIN IF DBMS_LOB.ISOPEN(i_bfile) = 1 THEN DBMS_LOB.CLOSE(i_bfile); END IF; END close_bfile;
PROCEDURE write_blob_to_file ( i_directory_name IN VARCHAR2, i_file_name IN VARCHAR2, i_src_blob IN OUT NOCOPY BLOB ) IS v_file UTL_FILE.FILE_TYPE; BEGIN v_file := UTL_FILE.FOPEN( UPPER(i_directory_name), i_file_name, 'wb', 32767 );
PROCEDURE close_bfile ( i_bfile IN OUT NOCOPY BFILE ) IS BEGIN IF DBMS_LOB.ISOPEN(i_bfile) = 1 THEN DBMS_LOB.CLOSE(i_bfile); END IF; END close_bfile;
PROCEDURE write_blob_to_file ( i_directory_name IN VARCHAR2, i_file_name IN VARCHAR2, i_src_blob IN OUT NOCOPY BLOB ) IS v_file UTL_FILE.FILE_TYPE; BEGIN v_file := UTL_FILE.FOPEN( UPPER(i_directory_name), i_file_name, 'wb', 32767 );
CREATE OR REPLACE PROCEDURE RSS_FEED_READER ( i_url IN VARCHAR2 ) AS --============ TYPEs/VARIABLEs =============================================== TYPE rss_type IS RECORD ( title VARCHAR2(2000), link VARCHAR2(200), pubDate VARCHAR2(200), category VARCHAR2(500), description VARCHAR2(4000) ); v_rss_item rss_type; v_rss_empty_item rss_type; -- v_rss_item初期化用
--========== Internal PROCEDUREs/FUNCTIONs =================================== -- --**************************************************************************** --* VARCHAR2の文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ --* --* NOTE: --* Oracle10g R2では、DBMS_OUTPUT.PUT_LINEプロシージャの255文字制限がないため、 --* 255文字毎に分割出力する必要はなくなる --**************************************************************************** PROCEDURE println ( i_text IN VARCHAR2 ) IS v_src VARCHAR2(32767); v_tempStr VARCHAR2(32767); BEGIN v_src := i_text; IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1); v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF)); ELSE v_tempStr := v_src; END IF;
WHILE v_tempStr IS NOT NULL LOOP IF LENGTH(v_tempStr)> 255 THEN FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255)); END LOOP; ELSE DBMS_OUTPUT.PUT_LINE(v_tempStr); END IF;
IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1); v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF)); ELSE EXIT; END IF; END LOOP;
EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error Occured : println(VARCHAR2) internal procedure.'); DBMS_OUTPUT.PUT_LINE(sqlerrm()); RAISE; END println;
PROCEDURE report_rss_item(p_rss_item IN rss_type) IS BEGIN println('TITLE: '||p_rss_item.title); println('URL : '||p_rss_item.link);
IF p_rss_item.pubDate IS NOT NULL THEN println('Published on: '||p_rss_item.pubDate); END IF;
IF p_rss_item.category IS NOT NULL THEN println('Category: '||p_rss_item.category); END IF;
IF p_rss_item.description IS NOT NULL THEN println('=='); println('Summary: '||p_rss_item.description); END IF;
println('—————————————-'); println(' ');
EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error occured : report_rss_item internal procedure'); DBMS_OUTPUT.PUT_LINE(sqlerrm()); RAISE; END report_rss_item;
--**************************************************************************** --* Main procedure --**************************************************************************** BEGIN DBMS_OUTPUT.ENABLE(200000); println('begin...');
v_url := i_url; IF v_url IS NULL THEN RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。'); END IF;
FOR i IN 1..DBMS_XMLDOM.GETLENGTH(v_rssEntryList) LOOP v_itemNode := DBMS_XMLDOM.ITEM(v_rssEntryList, i-1); v_rssItemFields := DBMS_XMLDOM.GETCHILDNODES(v_itemNode);
FOR j IN 1..DBMS_XMLDOM.GETLENGTH(v_rssItemFields) LOOP v_childnode := DBMS_XMLDOM.ITEM(v_rssItemFields, j-1); v_childNodeText := DBMS_XMLDOM.GETNODEVALUE( DBMS_XMLDOM.GETFIRSTCHILD(v_childnode) );
CASE DBMS_XMLDOM.GETNODENAME(v_childnode) WHEN 'title' THEN v_rss_item.title := v_childNodeText;
WHEN 'link' THEN v_rss_item.link := v_childNodeText;
WHEN 'published' THEN v_rss_item.pubDate := v_childNodeText;
WHEN 'category' THEN v_rss_item.category := v_childNodeText;
WHEN 'description' THEN v_rss_item.description := v_childNodeText;
CREATE OR REPLACE PROCEDURE RSS_FEED_READER ( i_url IN VARCHAR2 ) AS --============ TYPEs/VARIABLEs =============================================== TYPE rss_type IS RECORD ( title VARCHAR2(2000), link VARCHAR2(200), pubDate VARCHAR2(200), category VARCHAR2(500), description VARCHAR2(4000) ); v_rss_item rss_type; v_rss_empty_item rss_type; -- v_rss_item初期化用
--========== Internal PROCEDUREs/FUNCTIONs =================================== -- --**************************************************************************** --* VARCHAR2の文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ --* --* NOTE: --* Oracle10g R2では、DBMS_OUTPUT.PUT_LINEプロシージャの255文字制限が緩和され32767文字まで出力できるようになるためがないため、 --* 255文字毎に分割出力する必要はなくなるなぁ。 --**************************************************************************** PROCEDURE println ( i_text IN VARCHAR2 ) IS v_src VARCHAR2(32767); v_tempStr VARCHAR2(32767); BEGIN v_src := i_text; IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1); v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF)); ELSE v_tempStr := v_src; END IF;
WHILE v_tempStr IS NOT NULL LOOP IF LENGTH(v_tempStr)> 255 THEN FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255)); END LOOP; ELSE DBMS_OUTPUT.PUT_LINE(v_tempStr); END IF;
IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1); v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF)); ELSE EXIT; END IF; END LOOP;
EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error Occured : println(VARCHAR2) internal procedure.'); DBMS_OUTPUT.PUT_LINE(sqlerrm()); RAISE; END println;
--**************************************************************************** --* XMLTYPEに格納されたXMLソースをプリントする。 --* (Oracle10g R1だと、255文字毎の分割プリントは必要かも。。。未実装) --* --* NOTE: --* Oracle10g R2では、DBMS_OUTPUT.PUT_LINEプロシージャの255文字制限がないため、 --* 255文字毎に分割出力する必要はなくなる32767文字毎の分割出力でもOK. --**************************************************************************** PROCEDURE xml_println ( i_text IN XMLTYPE ) IS v_str LONG; BEGIN v_str := i_text.EXTRACT('/*').GETSTRINGVAL(); WHILE(v_str IS NOT NULL) LOOP DBMS_OUTPUT.PUB_LINE(SUBSTR(v_str, 1, INSTR(v_str, CHR(10)) - 1)); v_str := SUBSTR(v_str, INSTR(v_str, CHR(10)) + 1); END LOOP;
EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error Occured : xml_println(XMLTYPE) internal procedure.'); DBMS_OUTPUT.PUT_LINE(sqlerrm()); RAISE; END xml_println;
--**************************************************************************** --* Main Procedure --**************************************************************************** BEGIN DBMS_OUTPUT.ENABLE(200000); println('begin...');
v_url := i_url; IF v_url IS NULL THEN RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。'); END IF;
EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error Occured : main procedure.'); DBMS_OUTPUT.PUT_LINE(sqlerrm()); RAISE;
END RSS_FEED_READER;
また、前述のようにした事で、Mac De Oracleなどで発生してたココログのATOM配信フォーマットのパースエラーも消えた!?(やはり文字化けが影響していたようだ。)
以下に、Mac De OracleのATOMを読み込んだOracle SQL Developer 1.0 for MacOSXのスナップショットを示す。
RSS Readerの実験に利用するBlogは、私の友人であるmegawattさんのサイトを利用させて頂いた。(自分のブログである、Mac De OracleのRSSを利用していないのだが、理由は後日!)
と書いたが、当初、私のブログ(Mac De Oracle)で試そうと思ったのだが、何故、利用しなかったのか書いておく。
ココログは、RSSフォーマットではなく、Atom配信フォーマット。これはXMLのフォーマットが異なるだけなので、利用しなかった理由ではない。問題は、ココログのATOM配信フォーマットをDBMS_XMLPARSERパッケージのParserでパースすると、パースエラーが発生するためだ。
以下は、Oracle10g R1 EE for MacOSX ServerのDBMS_XMLPARSERパッケージを利用してパース後、XMLDOMからRSSソースを取り出しリストした結果である。文字の化け方から想像すると、UTF-8をISO Latin 1としてエンコードしているのかもしれない。
尚、すべての操作はOracle SQL Developer 1.0を利用して行った。(便利なのだがMacOSXだと、debuggerの動作がかなり遅いかも。。実際にはdebuggerを起動しなくても試せるので問題は無かったのだが。。)
CREATE OR REPLACE PROCEDURE RSS_FEED_READER ( i_url IN VARCHAR2 ) AS --============ TYPEs/VARIABLEs =============================================== TYPE rss_type IS RECORD ( title VARCHAR2(2000), link VARCHAR2(200), pubDate VARCHAR2(200), category VARCHAR2(500), description VARCHAR2(4000) ); v_rss_item rss_type; v_rss_empty_item rss_type; -- v_rss_item初期化用
v_url VARCHAR2(32767);
-- XML PARSER v_myParser DBMS_XMLPARSER.Parser;
-- XMLDOM v_rssDoc DBMS_XMLDOM.DomDocument;
-- for UTL_HTTP v_req UTL_HTTP.REQ; v_resp UTL_HTTP.RESP; v_source VARCHAR2(1024);
--========== Internal PROCEDUREs/FUNCTIONs =================================== -- --**************************************************************************** --* VARCHAR2の文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ --**************************************************************************** -- PROCEDURE println ( i_text IN VARCHAR2 ) IS v_src VARCHAR2(32767); v_tempStr VARCHAR2(32767); BEGIN v_src := i_text; IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1); v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF)); ELSE v_tempStr := v_src; END IF;
WHILE v_tempStr IS NOT NULL LOOP IF LENGTH(v_tempStr)> 255 THEN FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255)); END LOOP; ELSE DBMS_OUTPUT.PUT_LINE(v_tempStr); END IF;
IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1); v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF)); ELSE EXIT; END IF; END LOOP;
EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE( 'println(VARCHAR2) internal procedure:' || sqlerrm() ); RAISE; END println;
--**************************************************************************** --* CLOBの文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ --**************************************************************************** -- PROCEDURE println ( i_text IN CLOB ) IS v_src CLOB; v_tempStr CLOB; BEGIN v_src := i_text; IF INSTR(v_src, UTL_TCP.CRLF) = 0 THEN v_src := REPLACE(v_src, '><', '>'||UTL_TCP.CRLF||'<'); END IF;
WHILE v_tempStr IS NOT NULL LOOP IF LENGTH(v_tempStr) > 255 THEN FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255)); END LOOP; ELSE DBMS_OUTPUT.PUT_LINE(v_tempStr); END IF; v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1); v_src := TRIM(LEADING UTL_TCP.CRLF FROM SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF))); END LOOP; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE( 'println(CLOB) internal procedure:' || sqlerrm() ); RAISE; END println;
--**************************************************************************** --* Main Procedure --**************************************************************************** BEGIN DBMS_OUTPUT.ENABLE(200000); println('begin...');
v_url := i_url; IF v_url IS NULL THEN RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。'); END IF;
==================
Boot Campが発表されたので、
そのうち、 "Mac の Windows De Oracle" なんてことになるかもと言った瞬間、妻からは、ん〜〜〜〜っ。
"Mac の Linux De Oracle" のほうがいいんじゃない? ですと、、、さすが、Slackware、Debian育ちの妻らしい答え。(^^;; (今は、Mac好きな妻になってますがね)
私としては、"Mac の MacOSX De Oracle" 路線で行くのは間違いないんですがね。
(と、その前に、 Mac/Intelは、まだうちには無いし。。。。)
-------------
その後、 Mac No Windows De Oracle の Noが、英語の Noに見えちゃうという妻の突っ込みがあり、"No -> の" に変更。
尚、マシンスペックは以下の通り、
MacOSX 10.4.6 : Apple PowerMac G5 Dual 2.7Ghz RAM:1GB
United Linux 1.0 (KDE) : Toshiba DynaBook SS SX/210LNLW PentiumM 1Ghz RAM:768MB
Windows XP Professional SP2 : AMD Dual AthronMP 2800+ RAM:1GB
最近のコメント