Works > 逆引きSQL比較 > ORACLE > その他
ORACLE
[ SQL ]
[ データベースの情報 ]
[ 手続き型言語 ]
[ その他 ]
■その他
SQL文を書いたファイルをバッチで実行するには? ▲TOP
ORACLE MSSQL SSA
hoge.sqlの実行結果をhoge.txtにログとして出力する処理をコマンドプロンプトから実行します。
hoge.sql
spool hoge.txt;
select sysdate from dual;
spool off;
exit;
>sqlplus uid/pwd@接続文字列 @hoge.sql
CSVファイルをインポートするには? ▲TOP
ORACLE MSSQL SSA
CSV形式のkemp.txtを読み込み、社員マスタKEMPにインポートします。
以下のようなコントロールファイル kemp.ctl を準備します。
kemp.ctlの内容
LOAD DATA
INFILE 'C:\kemp.txt'
INTO TABLE KEMP
APPEND
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(
EMPNO integer external,
EMPNM char,
JOB char,
DEPTNO integer external
)
SQL*Loader を使用してデータをインポートします。
>sqlldr usr/pwd@接続文字列 control=kemp.ctl log=kemp.log
CSVファイルにエクスポートするには? ▲TOP
ORACLE MSSQL SSA
社員マスタKEMPをCSV形式のkemp.txtにエクスポートします。
ORACLEにはCSVにエクスポートするツールはありません。
拙作
exp2csvを使っていただいてもよいのですが、SQL*Plus でエクスポートする例を以下に示します。
set heading off
set verify off
set feed off
set pause off
set echo off
set termout off
set pagesize 0
set linesize 100
spool kemp.txt;
select
EMPNO || ',' ||
EMPNM || ',' ||
JOB || ',' ||
DEPTNO
from kemp;
exit;
以下は、もう少し汎用的な例。
アンロード用のSQLを作成するためのスクリプトです。
作成したアンロード用SQLをWindows上で実行するには wc.exe が必要です。無くても問題はありません。
ただし、どの道、CSVに吐き出した時に、「テーブル内のレコード件数=テキストの行数」である事を確認する必要がありますから、
入れておいてもよいでしょう。
VARCHAR2の項目に CRLF や LF が格納されていれば、当然件数が違うはずですから。
この例では、アンロード用のSQLを吐き出して終わりですが、最後のundefの前に@@で呼び出せば、
もちろんそのまま実行できます。
(まあ、でも一回は精査しますよね)
unload.sql
prompt カンマ区切りテキストにアンロードする
accept table_name prompt 'アンロードするテーブル名は? :'
accept owner prompt 'アンロードするテーブルの所有者は? :'
select sum(DATA_LENGTH) "類推されるデータ長"
from all_tab_columns
where table_name = upper('&table_name')
and owner = upper('&owner');
accept rec_len prompt 'アンロード時のデータ長は?(上記より多めに) :'
set heading off
set verify off
set feed off
set pause off
set echo off
set trims on
set termout off
set pagesize 0
define delim = ','
col dummy noprint
col a newline
spool &table_name.2csv.sql
---- UNLOAD START ----
prompt ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';;
prompt set verify off
prompt set feed off
prompt set heading off
prompt set pagesize 0
prompt prompt ********************************
prompt prompt &table_name UNLOAD
prompt select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') || ' START' from dual;;
prompt set pause off
prompt set echo off
prompt set trims on
prompt set termout off
prompt set linesize &rec_len
prompt spool &table_name..csv
prompt select
select decode(column_id,1,'','''&delim''||') ||
column_name || '||'
from all_tab_columns
where table_name = upper('&table_name')
and owner = upper('&owner')
order by column_id
/
prompt ''
prompt from &owner..&table_name;;
prompt spool off
prompt set termout on
prompt select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') || ' END' from dual;;
prompt prompt ********************************
prompt prompt rows of &owner..&table_name
prompt select count(*) from &owner..&table_name;;
prompt prompt lines of &table_name..csv
prompt ho wc -l &table_name..csv
prompt prompt ********************************
prompt set pagesize 14
prompt set heading on
prompt exit;;
---- UNLOAD END ----
spool off
set heading on
set termout on
set linesize 200
set pagesize 24
set feed on
prompt ***************************************
prompt File '&table_name.2csv.sql' Created.
prompt ***************************************
--@@&table_name.2csv.sql
undef table_name
undef owner
undef rec_len
バッチでエラーをハンドリングするには? ▲TOP
ORACLE MSSQL
どちらかと言うと、DOSのコマンドレベルの話ですが。
hoge.sqlの結果を受け、呼び出し側のバッチ処理でエラーをハンドリングします。
(WindowsOSの場合)
hoge.sql
--後続のコマンドが失敗した場合SQL*PlusをExitする
WHENEVER SQLERROR EXIT SQL.SQLCODE
--ORACLEでエラーになる構文
select getdate();
exit;
hoge.bat
@echo off
sqlplus misc/misc @hoge.sql
set myerror=%errorlevel%
echo;
echo;
if not %myerror% == 0 (
REM エラー処理
echo バッチ処理でエラーが発生しました:%myerror%
) else (
echo バッチ処理が完了しました
)
>hoge
を実行する。
ログインダイアログなしで接続するには? ▲TOP
ORACLE MSSQL SSA
接続時に、ログインダイアログを出さない方法です。
言うまでもありませんが『そのマシン自体にパスワードを残す』と言う点に留意する必要があります。
sqlplus であれ、sqlplusw であれ、この場合の引数は同じです。
GUI(?)の SQL*Plus については、ショートカットのプロパティのリンク先を
[パス]SQLPLUSW.EXE uid/pwd@接続文字列
のようにすれば、ダイアログを出さずに接続する事ができます。
特定のディレクトリのスクリプトを実行できるようにするには? ▲TOP
ORACLE MSSQL SSA
これもどちらかと言うと、WindowsOSの使い方の話ではあります。
単純に、SQL*Plus のショートカットのプロパティの作業フォルダのパスを、任意のディレクトリにしておけばOK。
ORACLEの場合、これ以外に環境変数のSQLPATHを指定する事で、複数のディレクトリからスクリプトファイルを実行できます。
WindowsOSであれば、レジストリの
\HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE
の下のどこかにSQLPATHがあるはずです。
初期値として、"..\Oracle\...\dbs" と云った感じのデータが入っているので、
これに以下のように追加します。
C:\Orant\dbs
↓
C:\Orant\dbs;C:\sqlscripts
バッチファイルの場合であれば、SQL*Plusをコールする前に、
バッチ上で、環境変数を以下のように変更しておきます。
この場合、レジストリを触らなくて済むので、
客先の環境で移行処理を行う時など、私はいつもこの方法です。
set SQLPATH=C:\Orant\dbs;C:\sqlscripts
指定した複数ディレクトリに同名のスクリプトが存在する可能性に留意してください。
優先順位は、カレントディレクトリ(作業フォルダ)>バッチ環境変数>レジストリの順です。
外部のデータベースに接続するには?(異機種間接続) ▲TOP
ORACLE MSSQL
他の外部データベースに接続する方法
オラクルから他の外部データベース(Sybase、MS SQLServer、IBMのDB2など)に直接接続するためには、
Transparent Gateway と言う高価なオプションを購入する必要がありました。相手が汎用機であれ、
オフコンであれ、UNIXであれ、PCであれ、です。
しかし、8iから追加された標準機能である Oracle Generic Connectivity(以下OGC)を使用すると、
ODBC、もしくは OLEDB 接続が可能であれば、オラクルからの異機種間接続が比較的簡単に行えます。
他のRDBMSをデータベースリンクを介してマッピングする事ができます。
OGC には ODBC と OLEDB の2種類あります。
ここでは、ODBCを例に、他のデータベースにORACLEから接続する例を挙げます。
(1) init.ora の設定
GLOBAL_NAMES を false にする
(DBリンク使用時のFAQですな)
(2) Oracle Generic Connectivity が入っているか Universal Installer で確認
(3) select * from SYS.HS_FDS_CLASS を実行し検索可能か確認
テーブルがない場合、ORACLE_HOME\RDBMS\ADMIN\caths.sqlをsysユーザーで実行
(4) ODBC の設定
ex.
接続データベース:SQL Server 2000
データソース名:hsodbctest
(とりあえずサクッとOS認証で)
(5) tnsnames.ora の設定
※接続文字列とデータソース名は必ずしも同じではない
hsodbc =
(DESCRIPTION =
(ADDRESS=(PROTOCOL=tcp)(HOST=<host_name>)(PORT=<port>))
(CONNECT_DATA=(SID=hsodbc))
(HS=OK)
)
(6) listener.ora の設定
(SID_DESC=
(SID_NAME=hsodbc)
(ORACLE_HOME = <oracle_home>)
(PROGRAM=hsodbc)
)
(7) ORCALE_HOME\HS\ADMIN\inithsodbc.ora の設定
※ここは必ずデータソース名でなくてはいけない
↓
HS_FDS_CONNECT_INFO = hsodbctest
HS_FDS_TRACE_LEVEL = 1
HS_FDS_TRACE_FILE_NAME = C:\Oracle\admin\<sid>\udump\HS.trc
(8) データベースリンクを作成
create database link hsodbc using 'hsodbc';
(9) SQL文実行
select * from kemp@hsodbc;
■インプレッション
私の環境では、ORACLE、MSSQLともにローカルで、繋がるまでに、7~8秒かかりました。
ODBC接続なので、テキストやエクセルファイルをODBCで直接読んで、ORACLE側にINSERTとか色々使えるかもしれません。(ハマらなければだが)
参考資料
・オラクルのマニュアル「Oracle8i 分散システム リリース8.1 」
・http://otn.oracle.com/products/oracle9i/datasheets/gateways/gateway_rel2_ds.html
・http://otn.oracle.com/products/discoverer/pdf/4i_generic_connectivity.pdf
・http://www.atinet.com/files/adk_docs/Generic%20Connectivity%20Using%20ODBC%20Unix.pdf
それと、これは余談ですが、異機種間ではなく、単純に SQL*Plus から特定のODBCデータソースに接続する方法と言うのもあります。ニッチ・チップスと謳っているからには、これも是非やりたいんだけど、成功した事ないっす。
[追記]↑これは8.0までの機能っぽいですね。
WindowsクライアントでHELPコマンド ▲TOP
サーバーが Solaris や HP で、SYSTEM.HELP が作成されていれば、Windows 側の
SQL*Plus から使えます。
-- help.sql
-- Usage :
-- SQL> @help
--
accept target prompt 表示したいヘルプトピック(前方一致):
set hea off;
set pagesize 0;
SELECT INFO FROM SYSTEM.HELP WHERE TOPIC LIKE UPPER('&target%') ORDER BY TOPIC, SEQ;
set hea on;
set pagesize 24;
undef target;
パスワードマスク ▲TOP
CONNECTコマンドだとパスワードが見えるのがヤダ、と言う人に
-- conn.sql
-- Usage :
-- SQL> @conn
--
accept uid prompt ユーザー名を入力:
accept pwd prompt パスワードを入力: HIDE
accept con prompt 接続文字列を入力:
connect &uid/&pwd@&con;
SQL*Plusのプロンプトから別ウィンドウでSQL*Plusを開く ▲TOP
※R7.3なら plus33w , R8.0なら plus80w
-- new+.sql
-- Usage :
-- SQL> @new+
--
show user;
accept uid prompt ユーザー名を入力:
accept pwd prompt パスワードを入力: HIDE
accept con prompt 接続文字列を入力:
ho start sqlplusw &uid/&pwd@&con;
クリアスクリーン ▲TOP
特に意味はないんですが。
-- cls.sql
-- Usage :
-- SQL> @cls
--
CLEAR SCR;
カレントディレクトリ表示(エクスプローラ) ▲TOP
カレントディレクトリを開く(Windows用)
パスを移動してなければ \oraxx\bin が開くでしょう。
-- bin.sql
-- Usage :
-- SQL> @bin
--
ho start explorer .
カレントディレクトリ表示(DOSプロンプト) ▲TOP
カレントディレクトリをDOSプロンプトで開く(Windows用)
パスを移動してなければ \oraxx\bin が開くでしょう。
-- binl.sql
-- Usage :
-- SQL> @binl
--
ho start command
拡張EDIT(任意のエディタでスクリプトを非同期に開く) ▲TOP
拡張EDIT(Windows用)
任意のエディタを使用するには _EDITOR変数を変更します。
私は フリー版EMEDITOR を愛用しているので
SQL> define_editor="C:\Program Files\EmEditor\EMEDITOR.EXE"
とすれば EDITコマンドで EMEDITOR が起動します。毎回同じエディタにするなら、
login.sql などに書いておけばよいでしょう。まあ、ここまでは FAQ です。
しかし、この状態のまま
SQL> ed 新規スクリプトファイル
と実行すると EMEDITOR のエラーになってしまうので、私は以下のようなスクリプト
で EDITコマンドを代替しています。拡張子.SQL はあらかじめ EMEDITOR
で開けるようにしておきます。EDITコマンドで開いた時と違い非同期なので、
使い勝手も良好。
-- ed.sql
-- Usage :
-- SQL> @ed スクリプトファイル名(拡張子不要)
--
-- ※新規ファイルでもOK
--
undef &1;
ho if not exist &1..sql type nul> &1..sql
ho start &1..sql
拡張DESCコマンド(INDEXの有無を表示) ▲TOP
-- desc.sql
-- INDEXの有無(PK / not PK)を表示
-- Usage :
-- SQL> @desc テーブル名
--
col 列名 format a26
col null format a4
col データ型 format a13
col "index(PK)" format a9
col "index(Not PK)" format a13
select
tc.column_name "列名",
decode(nvl(tc.data_scale,0),0, --小数点なしか
--小数点なし→整数か
decode(tc.data_type,'NUMBER',
--整数
tc.data_type || '(' || ltrim(to_char(tc.data_precision)) || ')',
--整数以外→VARCHAR2か
decode(tc.data_type,'VARCHAR2',
--VARCHAR2
tc.data_type || '(' || ltrim(to_char(tc.data_length)) || ')',
--VARCHAR2以外→CHARか
decode(tc.data_type,'CHAR',
--CHAR
tc.data_type || '(' || ltrim(to_char(tc.data_length)) || ')',
--それ以外
tc.data_type
)
)
),
--小数点あり
tc.data_type || '(' || ltrim(to_char(tc.data_precision)) || ',' || ltrim(to_char(tc.data_scale)) || ')'
) "データ型",
decode(tc.nullable,'Y',' ','No') "Null",
decode(mod(v.v_isPrim,2),1,'○',null) "index(PK)",
decode(greatest(nvl(v.v_isPrim,0),1),1,null,'○') "index(Not PK)"
from user_tab_columns tc,
(
select ic.column_name as v_column_name,
sum(decode (ic.index_name,c.constraint_name,1,2)) as v_isPrim
from user_ind_columns ic, user_constraints c, user_indexes i
where ic.table_name = c.table_name (+)
and ic.index_name = i.index_name (+)
and 'P' = c.constraint_type (+)
and c.status = 'ENABLED'
and ic.table_name = upper('&&1')
and c.table_name (+) = upper('&&1')
group by ic.column_name
) v
where tc.table_name = upper('&&1')
and tc.column_name = v.v_column_name (+)
order by tc.column_id
;
パラメータ渡しバッチ ▲TOP
コマンドラインの SQL*Plus のヘルプ( plusxx -h )を見ると、
開始ファイルの後に、任意のパラメータが指定できる事になっています。
これは、ホスト変数 &1 ~ &n として扱われます。つまり、
-- param.sql
spool param.txt;
select name from tbl
where col1 = '&1'
and col2 = '&2';
spool off;
exit;
こんなSQLを用意して、次の様なバッチファイルを作れば、
条件に該当するリストを取得できます。
※R7.3なら plus33 , R8.0なら plus80
param.bat
-----------------------------------------------------
sqlplus -s usr/pwd@con @param aaa bbb
start param.txt
スプールしたファイル名に実行時の日付を使う ▲TOP
COLUMNコマンドを使って可能です。
COLUMN system_date NEW_VALUE TIMESTAMP
SELECT to_char(sysdate,'YYYYMMDD') system_date FROM DUAL;
--時分秒まで持つ場合
--SELECT to_char(sysdate,'YYYYMMDDHH24MISS') system_date FROM DUAL;
--本日のLOGファイルをスプールする
spool filename&&TIMESTAMP..log
--ここ以降は、ログを取りたい何かの処理を書く
begin
dbms_output.put_line(to_char(sysdate,'yyyy-mm-dd') || 'の処理');
end;
/
--またはSQLスクリプトの実行
@@hoge
spool off;
以前はこんな泥臭い事やってました。
-- todayspool.sql
set heading off;
set verify off;
set feed off;
set linesize 200;
set pause off;
set echo off;
set termout off;
set pagesize 0;
set trims on;
set verify off;
set serveroutput on size 1000000;
--本日のLOGファイルを作成するためのスクリプトを作成する
spool makeTodayLog.sql
begin
dbms_output.put_line('spool ' || to_char(sysdate,'yyyymmdd') || '.log');
--時分秒まで持つ場合
--dbms_output.put_line('spool ' || to_char(sysdate,'yyyymmdd_hh24miss') || '.log');
end;
/
spool off;
set heading on;
set feed on;
--set echo on; --この辺はご自由に
set termout on;
set pagesize 24;
--本日のLOGファイルをスプールする
@makeTodayLog.sql
--ここ以降は、ログを取りたい何かの処理を書く
begin
dbms_output.put_line(to_char(sysdate,'yyyy-mm-dd') || 'の処理');
end;
/
--またはSQLスクリプトの実行
@@hoge
spool off;
exit;
このページの先頭へ
ORACLE
[ SQL ]
[ データベースの情報 ]
[ 手続き型言語 ]
[ その他 ]
Works > 逆引きSQL比較 > ORACLE > その他