2012年12月24日月曜日
株式会社ノアテックを設立しました
情報システムをご利用になるお客様の立場に立ち、企画・提案から運用・保守まで一貫したソリューションをご提供する。
これまでに育ってきた技術力を一層高め、常に情報リテラシーを磨き、顧客満足度を重視しながら、より良いシステム開発とソリューションの提供に全力を尽くして、可能な限りの社会貢献を果たして参ります。
よろしくお願いします。
株式会社ノアテック
www.noah-tec.com
これまでに育ってきた技術力を一層高め、常に情報リテラシーを磨き、顧客満足度を重視しながら、より良いシステム開発とソリューションの提供に全力を尽くして、可能な限りの社会貢献を果たして参ります。
よろしくお願いします。
株式会社ノアテック
www.noah-tec.com
柠檬的错觉
1.爱是世界上最甜蜜的痛,痛是为了得到世界上最甜蜜的爱.
2.其实不想写,其实不想回忆,其实我希望永远记不起. 但痛苦一天天积累,希望一天天枯萎. 脑海里浮现着但丁的神曲, 总以为那是很久远的过去,没想到那竟是熟悉的回忆. 总以为那是很漂渺的唏嘘,想不到也有现实的异域.
3.在爱的路上潇洒的我,遇到了比我更潇洒的你. 我像潇洒的风,你像潇洒的雨. 风雨之中,我发现自己潇洒地爱上了你.
4.我把你放在一滴泪里,幻想千年以后化成琥珀. 我不敢低头,怕那滴眼泪滴落,碎了千年的梦.
5.梦醒之后,注定要启程,单薄的身影,沉重的脚步,都取代来时那轻盈的步伐. 让我离开这虚假的天空,深深的脚印刻印下你给的伤痕累累. 红肿的双眼,颤抖的双肩,都证实着伤寂的泪水. 但愿他能酿一杯涩酒,在每一个想你的深夜品尝.
6.孤独,这是为自由付出的代价. 潇洒,这是孤独的外衣. 7.人生若只如初见,春风扑面桃花艳. 人生若只如初见,何事秋风悲画扇.
2.其实不想写,其实不想回忆,其实我希望永远记不起. 但痛苦一天天积累,希望一天天枯萎. 脑海里浮现着但丁的神曲, 总以为那是很久远的过去,没想到那竟是熟悉的回忆. 总以为那是很漂渺的唏嘘,想不到也有现实的异域.
3.在爱的路上潇洒的我,遇到了比我更潇洒的你. 我像潇洒的风,你像潇洒的雨. 风雨之中,我发现自己潇洒地爱上了你.
4.我把你放在一滴泪里,幻想千年以后化成琥珀. 我不敢低头,怕那滴眼泪滴落,碎了千年的梦.
5.梦醒之后,注定要启程,单薄的身影,沉重的脚步,都取代来时那轻盈的步伐. 让我离开这虚假的天空,深深的脚印刻印下你给的伤痕累累. 红肿的双眼,颤抖的双肩,都证实着伤寂的泪水. 但愿他能酿一杯涩酒,在每一个想你的深夜品尝.
6.孤独,这是为自由付出的代价. 潇洒,这是孤独的外衣. 7.人生若只如初见,春风扑面桃花艳. 人生若只如初见,何事秋风悲画扇.
PL/SQL 勉強ノート
1.
declare
type empno_array is table of varchar2(3);
tep empno_array := empno_array('E01','E02','E03','E04','E05');
begin
-- 配列の最後の要素を削除
tep.trim;
for ep_cnt in 1..tep.count loop
dbms_output.put_line('ep1:' || tep(ep_cnt));
end loop;
-- 配列の最後の要素を2つ削除
tep.trim(2);
for ep_cnt in 1..tep.count loop
dbms_output.put_line('ep2:' || tep(ep_cnt));
end loop;
end;
declare
type empno_array is table of varchar2(3);
tep empno_array := empno_array('E01','E02','E03','E04','E05');
begin
-- 配列の最後の要素を削除
tep.trim;
for ep_cnt in 1..tep.count loop
dbms_output.put_line('ep1:' || tep(ep_cnt));
end loop;
-- 配列の最後の要素を2つ削除
tep.trim(2);
for ep_cnt in 1..tep.count loop
dbms_output.put_line('ep2:' || tep(ep_cnt));
end loop;
end;
Oracle PL/SQL
目次
はじめに
対象者
コメント
構造
コーディング規約
ハローワールド
データ形式
演算子
制御構造
データ処理
エラー処理
関数
API
デバック
sqlplusを使って、Helloworldから始まり、データ形式、制御構造、関数の書き方などをサラっと学習します。
今後、オラクル社のリファレンスで学習できるようにするのが目的です。
参考資料には、オラクル社へのマニュアル・リンクを用意しました。
入門書に書いてある例えなどはありません。
言語習得に必要な部分のみしか書きませんので、sqlplusでサンプルを実行しながら学習してください。
PL/SQLと他の言語を比較してポイントとなる部分は赤 マークしています。
対象者
Oracleをこれから始める方。
コメント
コメントの書き方は二つあります。
-- 1行のコメントはハイフン(-)2つです。
/*
複数行のコメントはC言語などのように
スラッシュ、アスタリスクです。
*/
構造
下記の構造をPL/SQLブロックという
Begin End;のみ必須
入れ子で書くこと(=ネストブロック)も可能
サンプル
Declare
-- 宣言
Begin
-- 処理
Exception
-- エラー処理
End;
ネストブロック
Declare
Begin
Declare
-- 宣言
Begin
-- 処理
Exception
-- エラー処理
End;
Exception
End;
declare
tmp_data number := 0;
begin
/* nest block */
declare
tmp_data number;
begin
select 1/0 into tmp_data from dual;
exception
when ZERO_DIVIDE then
tmp_data :=SQLCODE;
insert into test_tbl values (tmp_data, 'testok');
commit;
end;
exception
when others then
null;
end;
/
コーディング規約
コーディング規約はない。
ハローワールド
サンプルテーブル
SQL> desc test_tbl
名前 NULL? 型
---- ----- ----------------------------
COL1 NUMBER
COL2 VARCHAR2(8)
hello.sql作成
hello.sqlで以下のPL/SQLプログラムを保存。
declare
test_var date;
begin
select sysdate into test_var from dual;
end;
/
解説
文はセミコロン(;)で終了
ブロックの最後にスラッシュ(/)が必要
大文字、小文字は関係ない
実行
SQL> @hello.sql
PL/SQLプロシージャが正常に完了しました。
データ形式
データ型(スカラー型・プリミティブ型)
NUMBER 符号付整数、固定小数点数、浮動小数点数
BINARY_INTEGER NUMBER型よりメモリ領域が少ない
PLS_INTEGER NUMBER型より早い
CHAR
VARCHAR2
LONG 互換性のためにあるLOB型を推奨
LONGROW 互換性のためにあるLOB型を推奨
NCHAR
NVARCHAR2
RAW 互換性のためにあるLOB型を推奨
UROWID ROWID
BOOLEAN TRUE | FALSE | NULL
DATE
BFILE
BLOB
CLOB
NCLOB
データ定義
変数名、データ型の順番で定義
文はセミコロン(;)で終了
初期値は:=で 指定
NOT NULL制約が可能
定数の定義はCONST
変数定義(=データ定義)
変数名 型
test_number number(10);
test_string varchar2(100);
jpn_tax number(5,2) := 1.05;
test_number2 number(3) := 10 not null;
test_date date := sysdate;
MAX_VALUE const number := 1.05;
属性定義
PL/SQLでは、テーブル定義からデータ型を参照することが出来る。
サンプルのテーブル
create table emp_tbl (
empid number,
emp_name varchar2(20)
)
/
属性定義の仕方
declare
test_no emp_tbl.empid%type;
begin
end;
/
解説
emp_tblテーブルのempidカラムのデータ型を%typeで 取得できるのでテーブル定義が変更してもPL/SQLの実装を修正する必要がなくなる。
索引付き表(スカラー型の配列)
type 索 引付き表型名 is table of スカラー型 index by binary_integer;
declare
type test_array is table of hoge_table.fuga_txt%type index by binary_integer;
test_variable test_array;
cursor c_hoge is select hoge_id,fuga_txt from hoge_table;
begin
for wk_cursor in c_hoge loop
test_variable(wk_cursor.hoge_id) := wk_cursor.fuga_txt;
end loop;
end;
/
show errors;
レコード
type レコード型名 is record (列名 データ型, 列名 データ型, ...);
declare
-- CAUTION!!
-- A user execute this program on sqlplus who must input command that 'set
serveroutput on'.
--
-- definition
type t_rec is record (
id_record test_record_tbl.id_record%type,
record_name test_record_tbl.record_name%type
);
-- declaretion
wk_val t_rec;
cursor c_sample is select id_record, record_name from test_record_tbl;
begin
open c_sample;
loop
fetch c_sample into wk_val;
dbms_output.put_line(wk_val.record_name);
exit when c_sample%notfound;
end loop;
dbms_output.put_line('end loop');
close c_sample;
end;
/
show errors;
レコードの索引付き表(二次元配列)
type レコード型名 is record (列名 データ型, 列名 データ型, ...);
type レコードの索引付き表型名 is table of レコード型名 index by binary_integer;
declare
-- the generic program language say multi-dimensional array.
-- existed samle function is 'varray' object.
-- 1. define record
type r_sample is record (
id_record test_record_tbl.id_record%type,
record_name test_record_tbl.record_name%type
);
-- 2. define arrray
type idx_ is table of r_sample index by binary_integer;
-- 3. declaration
dimen_ary idx_;
cursor c_tmp is select id_record, record_name from test_record_tbl;
begin
for wk_emp in c_tmp loop
dimen_ary(wk_emp.id_record) := wk_emp;
end loop;
end;
/
show errors;
演算子
= ==ではないので注意
!=
<> != と同意
>
<
<=
>=
IN
NOT IN
BETWEEN x AND y
NOT BETWEEN x AND y
LIKE
NOT LIKE
IS NULL
IS NOT NULL
PL/SQLは、NULL は何と比較してもNULLである。
制御構造
分岐
if文
if 条件1 then
-- 処理
elsif 条件2 then
-- 処理
end if;
declare
test_var number := 1;
begin
if test_var = 1 then
null; -- null は何もしない時に記述
elsif test_var = 2 then
null;
end if;
end;
/
反復
for文
for カウンタ in min...max [reverse] loop
end loop;
以下の例は、グローバルなtest_var変数とfor文中のtest_var変数2つを定義している。
for文中のカウンタであるtest_var変数は暗黙で定義しているので型を書いたりしていない。
サンプルのテーブル定義
create table test_tbl (col1 number);
declare
test_var number := 100;
begin
for test_var in 1..10 loop -- ローカルとしてtest_var変数を暗黙定義.
insert into test_tbl values (test_var);
end loop;
insert into test_tbl values (test_var);
commit;
end;
/
前判定反復
while文
while 条件 loop
end loop;
declare
test_var number := 100;
begin
while test_var <= 110 loop
insert into test_tbl values (test_var);
test_var := test_var + 1; -- インクリメント演算は出来ない
end loop;
commit;
end;
/
後判定反復
loop文
loop
end loop;
PL/SQLではC言語のように、while文を反復の最後に設定できないのでif文とloop文で行う。
declare
test_var number := 100;
begin
loop
-- 処理を書く.
-- 後判定
if test_var = 100 then
exit; -- loopを抜ける
end if;
end loop;
end;
/
if文を利用してexitするのは、exit when文を使えば1 行に出来る。
declare
test_var number := 100;
begin
loop
exit when test_var = 100;
end loop;
end;
/
データ処理
select into文
select into文は、1レコードの取得しか出来ません。
複数のレコードの場合はカーソルを使います。
select カラム名 into 変数 from テーブル [where 検索条件など]
declare
test_var date;
begin
-- dual表はテストなどダミーで使う表.
select sysdate into test_var from dual;
end;
/
カーソル
select文の結果セット(データ集合)に対して、1レコードづつ処理していく時に利用する。
PL/SQLのカーソルは戻る事が出来ない。(Javaのjava.sql.ResultSetなどは戻る事が可能)
カーソル作成手順
カーソル型の定義
カーソル用の変数定義
オープン
フェッチ(fetch)(定義した変数にデータを格納する事)
データ存在チェック
処理
クローズ
SQL> desc test_tbl
名前 NULL? 型
---- ----- --------------
COL1 NUMBER
COL2 VARCHAR2(8)
declare
/* カーソル型の定義 */
cursor c_test is select col1, col2 from test_tbl;
/* カーソル用の変数定義 */
c_test_val c_test%rowtype;
begin
open c_test;
loop
fetch c_test into c_test_val;
exit when c_test%notfound;
end loop;
close c_test;
end;
/
解説
%rowtypeでcol1の型(NUMBER)とcol2の型 (VARCHAR2(8))を取得している。%notfoundで存在チェック
カーソルforループ
for レコード型変数名 in カーソル loop
end loop;
カーソルfor loop でレコード型変数名をforスコープ内に出来る。
declare
/* cursor definition */
cursor c_test is select col1, col2 from test_tbl;
begin
for c_test_val in c_test loop
exit when c_test%notfound;
end loop;
end;
/
エラー処理
例外処理と通知
exceptionブロックに例外処理を書く
バインド変数で外部に通知する
PL/SQLではexceptionからbeginには復旧できない
例外をハンドリングしてexceptionブロックが正常に終了するとエラーがなかったようになる。
このサンプルは、sqlplusで実行するとエラーが出ます。各自、情報収集して解決してください。
declare
cursor c_tmp is select col1, col2 from test_tbl;
tmp_val c_tmp%rowtype;
begin
open c_tmp;
loop
fetch c_tmp into tmp_val;
exit when c_tmp%notfound;
end loop;
close c_tmp
:status := '0'; /* bind variable */
exception
when others then
if c_tmp%isopen then
close c_tmp;
end if;
:status := '1';
end;
/
解説
when others thenは、C言語ではswitch文の defalt句、Javaではjava.lang.Exception
サンプル2
declare
tmp_date date;
begin
insert into test_tbl values (111, 'test');
select sysdate into tmp_date from dual where 1=2;
commit;
exception
when others then
commit;
end;
/
実行結果
SQL> @test9.sql
PL/SQLプロシージャが正常に完了しました。
解説
例外処理(exception)を書いているので正常終了になる
例外ハンドラ
例外一覧
例外名 ORA-XXX SQLCODE 条件
ACCESS_INTO_NULL 6530 -6530 初期化していないオブジェクト(アトミックNULL)の属性に代入した時
COLLECTION_IS_NULL 6531 -6531
CURSOR_ALREADY_OPEN 6511 -6511
DUP_VAL_ON_INDEX 1 -1 UNIQUE索引に重複(Duplicate)データを格納した時
INVALID_CURSOR 1001 -1001 不正カーソル処理時
INVALID_NUMBER 1722 -1722 文字列から数値の置換に失敗した時
LOGIN_DENIED 1017 -1017 ログイン失敗時
NO_DATA_FOUND 1403 +100
NOT_LOGGED_ON 1012 -1012 Oracleに接続していないプログラムがデータベースコールを発行した時
PROGRAM_ERROR 6501 -6501 PL/SQL内部に問題点がある時
ROWTYPE_MISMATCH 6504 -6504
SELF_IS_NULL 30625 -30625
STORAGE_ERROR 6500 -6500 メモリ関連エラー時
SUBSCRIPT_BEYOND_COUNT 6533 -6533 コレクションの要素数より大きいインデックスでアクセスした時
SUBSCRIPT_OUTSIDE_LIMIT 6532 -6532 有効範囲外で表、varrayなどにアクセスした時
SYS_INVALID_ROWID 1410 -1410
TIMEOUT_ON_RESOURCE 51 -51
TOO_MANY_ROWS 1422 -1422 select into文が複数行を返した時
VALUE_ERROR 6502 -6502 算術、変換、切り捨て、サイズ制約などのエラー時
ZERO_DIVIDE 1476 -1476
when 例外名 then
declare
tmp_data number;
begin
select 1/0 into tmp_data from dual;
exception
when ZERO_DIVIDE then
tmp_data := 10;
end;
/
declare
tmp_data number;
begin
select col1 into tmp_data from test_tbl;
exception
when no_data_found or too_many_rows then
null;
end;
/
declare
tmp_data number := 0;
begin
select 1/0 into tmp_data from dual;
exception
when no_data_found then
null;
when too_many_rows then
null;
when zero_divide then
null;
when others then
null;
end;
/
エラーメッセージ取得
SQLCODE関数とSQLERRM(ERRor-Message)関数を利用
SQLCODEとSQLERRMは必ず変数に代入し なければならない。
declare
tmp_id number;
tmp_data test_tbl.col2%type := '';
error_msg varchar2(2000);
begin
select 1/0 into tmp_data from dual;
exception
when others then
if SQLCODE = -1476 then
tmp_id := SQLCODE;
insert into test_tbl values(tmp_id, 'test ok');
commit;
else
tmp_id := SQLCODE;
error_msg := SQLERRM;
insert into test_tbl values(tmp_id, tmp_data);
commit;
end if;
end;
/
関数
関数の種類
Function
戻り値が1つ
Procedure
戻り値が複数
構文
Function構文
Function 名前 [ ([引数名 [IN | OUT | INOUT]? データ型 [default デフォルト値]? ]* ) ]
Return データ型 is [宣言部]
Begin
[実行部]
[Exception]
End;
Procedure構文
Procedure 名前[ ([引数名 [IN | OUT | INOUT]? データ型 [default デフォルト値]? ]* ) ] is [宣言部]
Begin
[実行部]
[Exception]
End;
プロシージャのサンプル
declare
procedure test_pcd( tmp_num IN number, tmp_str IN varchar2 ) is
begin
insert into test_tbl values (tmp_num, tmp_str);
end;
begin
test_pcd(99,'99');
commit;
end;
/
function, procedureでは、引数でデータサイズなどの制約をつけられない。
declare
procedure sample1(var in varchar2(20)) is
begin
end;
begin
end;
/
show errors;
SQL> @test04.sql
procedure sample1(var in varchar2(20)) is
*
行2でエラーが発生しました。:
ORA-06550: 行2、列36:
PLS-00103: 記号"("が見つかりました。 次のうちの1つが入るとき:
:= . ) , @ % default character
記号":=" は続行のために"("に代わりました。
ORA-06550: 行4、列3:
PLS-00103: 記号"END"が見つかりました。 次のうちの1つが入るとき:
begin case declare exit for goto if loop mod null pragma
raise return select update while with
制約をつけたい場合は、subtypeを使う
subtype データ名 is データ型
declare
subtype myVChar is varchar2(20);
procedure sample1(var in myVChar) is
begin
null;
end;
begin
null;
end;
/
show errors;
共通ライブラリ化の方法
PL/SQLでは、共通ライブラリ化することを、ストアドプロ グラムと呼ぶ
他の言語では、一般的にファイルとしてライブラリとするが、PL/SQLはデータベース内に格納する
データベーススキーマのオブジェクトであるので実行権限(Execute権限)が必要
PL/SQLをコンパイルしたコードをPコードと 呼ぶ
作成時にコンパイルしているため、解析フェーズが省略される分、パフォーマンスが良い
ユーザに関係なく、システム表領域に作成される
種類 概要
ストアドプロシージャ 1つのプロシージャをライブラリ化
ストアドファンクション 1つのファンクションをライブラリ化
データベーストリガ イベントハンドラ
パッケージ 上記をまとめる。
ストアド化
create or replace
procedure test_pcd(
tmp_num IN number,
tmp_str IN varchar2
) is
begin
insert into test_tbl values (tmp_num, tmp_str);
commit;
end;
/
show errors;
パッケージ作成
仕様部と本体部を作成する。
仕様部が外部インタフェースになる。
仕様部と本体部は1つのファイルに纏めても、分割しても良い
仕様部を最初にコンパイルしなければならない。
仕様部
create or replace package パッケージ名 is
...
end パッケージ名;
create or replace package sample_package is
procedure sample1(wk_col1 in number);
function sample2(wk_col2 in varchar2) return varchar2;
end sample_package;
/
show errors;
本体部
create or replace package body パッ ケージ名 is
...
end パッケージ名;
create or replace package body sample_package is
procedure sample1(wk_col1 in number) is
begin
insert into test_tbl values (wk_col1, 'package');
commit;
end;
function sample2(wk_col2 in varchar2) return varchar2 is
begin
insert into test_tbl values ('11', wk_col2);
commit;
return '0';
end;
end sample_package;
/
show errors;
作ったものをテストするプログラム
declare
wk_str varchar2(100);
function test_fnc(wk_col1 in number) return number is
begin
return 0;
end;
begin
sample_package.sample1(1);
wk_str := sample_package.sample2('1');
end;
/
show errors;
解説
パッケージもオブジェクトなので、ピリオドを利用して呼び出す。 適当なファイル名をつけて実行してみてください。
トリガー
ユーザはトリガーが起動した事は分からない
DMLの前後などに設定する。
プログラムでよくあるイベントハンドラである。
トリガーは引数を持たない。
注意点
トリガーは、自動起動するため、開発者はその存在を忘れる可能性がある。 運用後の保守、デバック等が複雑になる傾向があるので、基本的にはトリガー機能を使わず、代案がない場合に利用するように心がける事
トリガーの管理
alter triger トリガー名 [enable | disable]
user_triggers
create or replace trigger トリガー名 before
[insert | update | delete] or on テーブル名
declare
begin
end;
/
create or replace trigger sample_trigger before
insert or update or delete on test_tbl
declare
begin
insert into trigger_log values (99,'trger go');
end;
/
実行
SQL> insert into test_tbl values (1, '111');
1行が作成されました。
結果
SQL> select * from trigger_log;
COL1 COL2
---------- ----------------
99 trger go
API(Application Program Interface)
Oracle9i PLSQL パッケージ・プロシージャおよびタイプ・リファレンス リリース2(9.2)がAPIのドキュメントになる。 sysユーザ権限でdesc standardを実行すれば、 standardと呼ばれる、標準APIが分かる。 以下でソースコードが読める。
select text from user_source where name= 'STANDARD';
デバック
プログラムに空白行を含めない。
PL/SQLでは、空白行は実行時に1行として含めない。つまり空白行は実行時に削除 する。 そのため、エ ラー時の行番がエディタ上の行番号とづれてしまう。 エディタでの開発の場合は、プログラムに空白行を含めない方が効率がよい。
user_errors表をつかう。
PL/SQLでは、ストアドプログラムは、プログラムにエラーが存在しても、取り合え ずデータベースに登録する。どこにエラーがあるか判断するには、user_errors表を確認する。
user_source表をつかう。
コンパイルした結果とソースコードをこの表に記録しているので、デバック時に役立つ
show errorsコマンド
user_errors表を確認するのは、手間が掛かるのでソースコードの最終行に show errorsコマンドを書いておく事でデバックが簡単になる。
他の言語よりコンパイルのサイクルを短くする。
PL/SQLをエディタで開発する場合は、ソースコードを全て記述してからコンパイル するのではなく少しコーディングしたら直ぐにコンパイルするように心がける事。PL/SQLの開発環境は粗悪なので非常に有効である。
はじめに
対象者
コメント
構造
コーディング規約
ハローワールド
データ形式
演算子
制御構造
データ処理
エラー処理
関数
API
デバック
sqlplusを使って、Helloworldから始まり、データ形式、制御構造、関数の書き方などをサラっと学習します。
今後、オラクル社のリファレンスで学習できるようにするのが目的です。
参考資料には、オラクル社へのマニュアル・リンクを用意しました。
入門書に書いてある例えなどはありません。
言語習得に必要な部分のみしか書きませんので、sqlplusでサンプルを実行しながら学習してください。
PL/SQLと他の言語を比較してポイントとなる部分は赤 マークしています。
対象者
Oracleをこれから始める方。
コメント
コメントの書き方は二つあります。
-- 1行のコメントはハイフン(-)2つです。
/*
複数行のコメントはC言語などのように
スラッシュ、アスタリスクです。
*/
構造
下記の構造をPL/SQLブロックという
Begin End;のみ必須
入れ子で書くこと(=ネストブロック)も可能
サンプル
Declare
-- 宣言
Begin
-- 処理
Exception
-- エラー処理
End;
ネストブロック
Declare
Begin
Declare
-- 宣言
Begin
-- 処理
Exception
-- エラー処理
End;
Exception
End;
declare
tmp_data number := 0;
begin
/* nest block */
declare
tmp_data number;
begin
select 1/0 into tmp_data from dual;
exception
when ZERO_DIVIDE then
tmp_data :=SQLCODE;
insert into test_tbl values (tmp_data, 'testok');
commit;
end;
exception
when others then
null;
end;
/
コーディング規約
コーディング規約はない。
ハローワールド
サンプルテーブル
SQL> desc test_tbl
名前 NULL? 型
---- ----- ----------------------------
COL1 NUMBER
COL2 VARCHAR2(8)
hello.sql作成
hello.sqlで以下のPL/SQLプログラムを保存。
declare
test_var date;
begin
select sysdate into test_var from dual;
end;
/
解説
文はセミコロン(;)で終了
ブロックの最後にスラッシュ(/)が必要
大文字、小文字は関係ない
実行
SQL> @hello.sql
PL/SQLプロシージャが正常に完了しました。
データ形式
データ型(スカラー型・プリミティブ型)
NUMBER 符号付整数、固定小数点数、浮動小数点数
BINARY_INTEGER NUMBER型よりメモリ領域が少ない
PLS_INTEGER NUMBER型より早い
CHAR
VARCHAR2
LONG 互換性のためにあるLOB型を推奨
LONGROW 互換性のためにあるLOB型を推奨
NCHAR
NVARCHAR2
RAW 互換性のためにあるLOB型を推奨
UROWID ROWID
BOOLEAN TRUE | FALSE | NULL
DATE
BFILE
BLOB
CLOB
NCLOB
データ定義
変数名、データ型の順番で定義
文はセミコロン(;)で終了
初期値は:=で 指定
NOT NULL制約が可能
定数の定義はCONST
変数定義(=データ定義)
変数名 型
test_number number(10);
test_string varchar2(100);
jpn_tax number(5,2) := 1.05;
test_number2 number(3) := 10 not null;
test_date date := sysdate;
MAX_VALUE const number := 1.05;
属性定義
PL/SQLでは、テーブル定義からデータ型を参照することが出来る。
サンプルのテーブル
create table emp_tbl (
empid number,
emp_name varchar2(20)
)
/
属性定義の仕方
declare
test_no emp_tbl.empid%type;
begin
end;
/
解説
emp_tblテーブルのempidカラムのデータ型を%typeで 取得できるのでテーブル定義が変更してもPL/SQLの実装を修正する必要がなくなる。
索引付き表(スカラー型の配列)
type 索 引付き表型名 is table of スカラー型 index by binary_integer;
declare
type test_array is table of hoge_table.fuga_txt%type index by binary_integer;
test_variable test_array;
cursor c_hoge is select hoge_id,fuga_txt from hoge_table;
begin
for wk_cursor in c_hoge loop
test_variable(wk_cursor.hoge_id) := wk_cursor.fuga_txt;
end loop;
end;
/
show errors;
レコード
type レコード型名 is record (列名 データ型, 列名 データ型, ...);
declare
-- CAUTION!!
-- A user execute this program on sqlplus who must input command that 'set
serveroutput on'.
--
-- definition
type t_rec is record (
id_record test_record_tbl.id_record%type,
record_name test_record_tbl.record_name%type
);
-- declaretion
wk_val t_rec;
cursor c_sample is select id_record, record_name from test_record_tbl;
begin
open c_sample;
loop
fetch c_sample into wk_val;
dbms_output.put_line(wk_val.record_name);
exit when c_sample%notfound;
end loop;
dbms_output.put_line('end loop');
close c_sample;
end;
/
show errors;
レコードの索引付き表(二次元配列)
type レコード型名 is record (列名 データ型, 列名 データ型, ...);
type レコードの索引付き表型名 is table of レコード型名 index by binary_integer;
declare
-- the generic program language say multi-dimensional array.
-- existed samle function is 'varray' object.
-- 1. define record
type r_sample is record (
id_record test_record_tbl.id_record%type,
record_name test_record_tbl.record_name%type
);
-- 2. define arrray
type idx_ is table of r_sample index by binary_integer;
-- 3. declaration
dimen_ary idx_;
cursor c_tmp is select id_record, record_name from test_record_tbl;
begin
for wk_emp in c_tmp loop
dimen_ary(wk_emp.id_record) := wk_emp;
end loop;
end;
/
show errors;
演算子
= ==ではないので注意
!=
<> != と同意
>
<
<=
>=
IN
NOT IN
BETWEEN x AND y
NOT BETWEEN x AND y
LIKE
NOT LIKE
IS NULL
IS NOT NULL
PL/SQLは、NULL は何と比較してもNULLである。
制御構造
分岐
if文
if 条件1 then
-- 処理
elsif 条件2 then
-- 処理
end if;
declare
test_var number := 1;
begin
if test_var = 1 then
null; -- null は何もしない時に記述
elsif test_var = 2 then
null;
end if;
end;
/
反復
for文
for カウンタ in min...max [reverse] loop
end loop;
以下の例は、グローバルなtest_var変数とfor文中のtest_var変数2つを定義している。
for文中のカウンタであるtest_var変数は暗黙で定義しているので型を書いたりしていない。
サンプルのテーブル定義
create table test_tbl (col1 number);
declare
test_var number := 100;
begin
for test_var in 1..10 loop -- ローカルとしてtest_var変数を暗黙定義.
insert into test_tbl values (test_var);
end loop;
insert into test_tbl values (test_var);
commit;
end;
/
前判定反復
while文
while 条件 loop
end loop;
declare
test_var number := 100;
begin
while test_var <= 110 loop
insert into test_tbl values (test_var);
test_var := test_var + 1; -- インクリメント演算は出来ない
end loop;
commit;
end;
/
後判定反復
loop文
loop
end loop;
PL/SQLではC言語のように、while文を反復の最後に設定できないのでif文とloop文で行う。
declare
test_var number := 100;
begin
loop
-- 処理を書く.
-- 後判定
if test_var = 100 then
exit; -- loopを抜ける
end if;
end loop;
end;
/
if文を利用してexitするのは、exit when文を使えば1 行に出来る。
declare
test_var number := 100;
begin
loop
exit when test_var = 100;
end loop;
end;
/
データ処理
select into文
select into文は、1レコードの取得しか出来ません。
複数のレコードの場合はカーソルを使います。
select カラム名 into 変数 from テーブル [where 検索条件など]
declare
test_var date;
begin
-- dual表はテストなどダミーで使う表.
select sysdate into test_var from dual;
end;
/
カーソル
select文の結果セット(データ集合)に対して、1レコードづつ処理していく時に利用する。
PL/SQLのカーソルは戻る事が出来ない。(Javaのjava.sql.ResultSetなどは戻る事が可能)
カーソル作成手順
カーソル型の定義
カーソル用の変数定義
オープン
フェッチ(fetch)(定義した変数にデータを格納する事)
データ存在チェック
処理
クローズ
SQL> desc test_tbl
名前 NULL? 型
---- ----- --------------
COL1 NUMBER
COL2 VARCHAR2(8)
declare
/* カーソル型の定義 */
cursor c_test is select col1, col2 from test_tbl;
/* カーソル用の変数定義 */
c_test_val c_test%rowtype;
begin
open c_test;
loop
fetch c_test into c_test_val;
exit when c_test%notfound;
end loop;
close c_test;
end;
/
解説
%rowtypeでcol1の型(NUMBER)とcol2の型 (VARCHAR2(8))を取得している。%notfoundで存在チェック
カーソルforループ
for レコード型変数名 in カーソル loop
end loop;
カーソルfor loop でレコード型変数名をforスコープ内に出来る。
declare
/* cursor definition */
cursor c_test is select col1, col2 from test_tbl;
begin
for c_test_val in c_test loop
exit when c_test%notfound;
end loop;
end;
/
エラー処理
例外処理と通知
exceptionブロックに例外処理を書く
バインド変数で外部に通知する
PL/SQLではexceptionからbeginには復旧できない
例外をハンドリングしてexceptionブロックが正常に終了するとエラーがなかったようになる。
このサンプルは、sqlplusで実行するとエラーが出ます。各自、情報収集して解決してください。
declare
cursor c_tmp is select col1, col2 from test_tbl;
tmp_val c_tmp%rowtype;
begin
open c_tmp;
loop
fetch c_tmp into tmp_val;
exit when c_tmp%notfound;
end loop;
close c_tmp
:status := '0'; /* bind variable */
exception
when others then
if c_tmp%isopen then
close c_tmp;
end if;
:status := '1';
end;
/
解説
when others thenは、C言語ではswitch文の defalt句、Javaではjava.lang.Exception
サンプル2
declare
tmp_date date;
begin
insert into test_tbl values (111, 'test');
select sysdate into tmp_date from dual where 1=2;
commit;
exception
when others then
commit;
end;
/
実行結果
SQL> @test9.sql
PL/SQLプロシージャが正常に完了しました。
解説
例外処理(exception)を書いているので正常終了になる
例外ハンドラ
例外一覧
例外名 ORA-XXX SQLCODE 条件
ACCESS_INTO_NULL 6530 -6530 初期化していないオブジェクト(アトミックNULL)の属性に代入した時
COLLECTION_IS_NULL 6531 -6531
CURSOR_ALREADY_OPEN 6511 -6511
DUP_VAL_ON_INDEX 1 -1 UNIQUE索引に重複(Duplicate)データを格納した時
INVALID_CURSOR 1001 -1001 不正カーソル処理時
INVALID_NUMBER 1722 -1722 文字列から数値の置換に失敗した時
LOGIN_DENIED 1017 -1017 ログイン失敗時
NO_DATA_FOUND 1403 +100
NOT_LOGGED_ON 1012 -1012 Oracleに接続していないプログラムがデータベースコールを発行した時
PROGRAM_ERROR 6501 -6501 PL/SQL内部に問題点がある時
ROWTYPE_MISMATCH 6504 -6504
SELF_IS_NULL 30625 -30625
STORAGE_ERROR 6500 -6500 メモリ関連エラー時
SUBSCRIPT_BEYOND_COUNT 6533 -6533 コレクションの要素数より大きいインデックスでアクセスした時
SUBSCRIPT_OUTSIDE_LIMIT 6532 -6532 有効範囲外で表、varrayなどにアクセスした時
SYS_INVALID_ROWID 1410 -1410
TIMEOUT_ON_RESOURCE 51 -51
TOO_MANY_ROWS 1422 -1422 select into文が複数行を返した時
VALUE_ERROR 6502 -6502 算術、変換、切り捨て、サイズ制約などのエラー時
ZERO_DIVIDE 1476 -1476
when 例外名 then
declare
tmp_data number;
begin
select 1/0 into tmp_data from dual;
exception
when ZERO_DIVIDE then
tmp_data := 10;
end;
/
declare
tmp_data number;
begin
select col1 into tmp_data from test_tbl;
exception
when no_data_found or too_many_rows then
null;
end;
/
declare
tmp_data number := 0;
begin
select 1/0 into tmp_data from dual;
exception
when no_data_found then
null;
when too_many_rows then
null;
when zero_divide then
null;
when others then
null;
end;
/
エラーメッセージ取得
SQLCODE関数とSQLERRM(ERRor-Message)関数を利用
SQLCODEとSQLERRMは必ず変数に代入し なければならない。
declare
tmp_id number;
tmp_data test_tbl.col2%type := '';
error_msg varchar2(2000);
begin
select 1/0 into tmp_data from dual;
exception
when others then
if SQLCODE = -1476 then
tmp_id := SQLCODE;
insert into test_tbl values(tmp_id, 'test ok');
commit;
else
tmp_id := SQLCODE;
error_msg := SQLERRM;
insert into test_tbl values(tmp_id, tmp_data);
commit;
end if;
end;
/
関数
関数の種類
Function
戻り値が1つ
Procedure
戻り値が複数
構文
Function構文
Function 名前 [ ([引数名 [IN | OUT | INOUT]? データ型 [default デフォルト値]? ]* ) ]
Return データ型 is [宣言部]
Begin
[実行部]
[Exception]
End;
Procedure構文
Procedure 名前[ ([引数名 [IN | OUT | INOUT]? データ型 [default デフォルト値]? ]* ) ] is [宣言部]
Begin
[実行部]
[Exception]
End;
プロシージャのサンプル
declare
procedure test_pcd( tmp_num IN number, tmp_str IN varchar2 ) is
begin
insert into test_tbl values (tmp_num, tmp_str);
end;
begin
test_pcd(99,'99');
commit;
end;
/
function, procedureでは、引数でデータサイズなどの制約をつけられない。
declare
procedure sample1(var in varchar2(20)) is
begin
end;
begin
end;
/
show errors;
SQL> @test04.sql
procedure sample1(var in varchar2(20)) is
*
行2でエラーが発生しました。:
ORA-06550: 行2、列36:
PLS-00103: 記号"("が見つかりました。 次のうちの1つが入るとき:
:= . ) , @ % default character
記号":=" は続行のために"("に代わりました。
ORA-06550: 行4、列3:
PLS-00103: 記号"END"が見つかりました。 次のうちの1つが入るとき:
begin case declare exit for goto if loop mod null pragma
raise return select update while with
制約をつけたい場合は、subtypeを使う
subtype データ名 is データ型
declare
subtype myVChar is varchar2(20);
procedure sample1(var in myVChar) is
begin
null;
end;
begin
null;
end;
/
show errors;
共通ライブラリ化の方法
PL/SQLでは、共通ライブラリ化することを、ストアドプロ グラムと呼ぶ
他の言語では、一般的にファイルとしてライブラリとするが、PL/SQLはデータベース内に格納する
データベーススキーマのオブジェクトであるので実行権限(Execute権限)が必要
PL/SQLをコンパイルしたコードをPコードと 呼ぶ
作成時にコンパイルしているため、解析フェーズが省略される分、パフォーマンスが良い
ユーザに関係なく、システム表領域に作成される
種類 概要
ストアドプロシージャ 1つのプロシージャをライブラリ化
ストアドファンクション 1つのファンクションをライブラリ化
データベーストリガ イベントハンドラ
パッケージ 上記をまとめる。
ストアド化
create or replace
procedure test_pcd(
tmp_num IN number,
tmp_str IN varchar2
) is
begin
insert into test_tbl values (tmp_num, tmp_str);
commit;
end;
/
show errors;
パッケージ作成
仕様部と本体部を作成する。
仕様部が外部インタフェースになる。
仕様部と本体部は1つのファイルに纏めても、分割しても良い
仕様部を最初にコンパイルしなければならない。
仕様部
create or replace package パッケージ名 is
...
end パッケージ名;
create or replace package sample_package is
procedure sample1(wk_col1 in number);
function sample2(wk_col2 in varchar2) return varchar2;
end sample_package;
/
show errors;
本体部
create or replace package body パッ ケージ名 is
...
end パッケージ名;
create or replace package body sample_package is
procedure sample1(wk_col1 in number) is
begin
insert into test_tbl values (wk_col1, 'package');
commit;
end;
function sample2(wk_col2 in varchar2) return varchar2 is
begin
insert into test_tbl values ('11', wk_col2);
commit;
return '0';
end;
end sample_package;
/
show errors;
作ったものをテストするプログラム
declare
wk_str varchar2(100);
function test_fnc(wk_col1 in number) return number is
begin
return 0;
end;
begin
sample_package.sample1(1);
wk_str := sample_package.sample2('1');
end;
/
show errors;
解説
パッケージもオブジェクトなので、ピリオドを利用して呼び出す。 適当なファイル名をつけて実行してみてください。
トリガー
ユーザはトリガーが起動した事は分からない
DMLの前後などに設定する。
プログラムでよくあるイベントハンドラである。
トリガーは引数を持たない。
注意点
トリガーは、自動起動するため、開発者はその存在を忘れる可能性がある。 運用後の保守、デバック等が複雑になる傾向があるので、基本的にはトリガー機能を使わず、代案がない場合に利用するように心がける事
トリガーの管理
alter triger トリガー名 [enable | disable]
user_triggers
create or replace trigger トリガー名 before
[insert | update | delete] or on テーブル名
declare
begin
end;
/
create or replace trigger sample_trigger before
insert or update or delete on test_tbl
declare
begin
insert into trigger_log values (99,'trger go');
end;
/
実行
SQL> insert into test_tbl values (1, '111');
1行が作成されました。
結果
SQL> select * from trigger_log;
COL1 COL2
---------- ----------------
99 trger go
API(Application Program Interface)
Oracle9i PLSQL パッケージ・プロシージャおよびタイプ・リファレンス リリース2(9.2)がAPIのドキュメントになる。 sysユーザ権限でdesc standardを実行すれば、 standardと呼ばれる、標準APIが分かる。 以下でソースコードが読める。
select text from user_source where name= 'STANDARD';
デバック
プログラムに空白行を含めない。
PL/SQLでは、空白行は実行時に1行として含めない。つまり空白行は実行時に削除 する。 そのため、エ ラー時の行番がエディタ上の行番号とづれてしまう。 エディタでの開発の場合は、プログラムに空白行を含めない方が効率がよい。
user_errors表をつかう。
PL/SQLでは、ストアドプログラムは、プログラムにエラーが存在しても、取り合え ずデータベースに登録する。どこにエラーがあるか判断するには、user_errors表を確認する。
user_source表をつかう。
コンパイルした結果とソースコードをこの表に記録しているので、デバック時に役立つ
show errorsコマンド
user_errors表を確認するのは、手間が掛かるのでソースコードの最終行に show errorsコマンドを書いておく事でデバックが簡単になる。
他の言語よりコンパイルのサイクルを短くする。
PL/SQLをエディタで開発する場合は、ソースコードを全て記述してからコンパイル するのではなく少しコーディングしたら直ぐにコンパイルするように心がける事。PL/SQLの開発環境は粗悪なので非常に有効である。
2012年7月7日土曜日
ブランドアイ
ブランドアイ
http://www.branday.com
欢迎大家光临BRANDay宝爱伊(株式会社)ブランドアイ
我们将为大家带来最新的国际名牌二手名牌包包,手表和首饰等的销售。
我们的公司已经在日本开业9年了,在日本大阪有较高知名度,
希望更多中国华人的顾客也能用低廉的价格购买到真正的名牌商品。
★★2012年7月夏季大折扣活动!!!\(⌒∇⌒)/★★
★★难波店全商品★★ ❤❤20%OFF❤❤
2012-6-28 17:53 上传下载附件 (70.77 KB)
大家抓紧时间和机会,
用最低廉的价格买到喜欢的奢侈品,
我们帮你完成这样的心愿(●>v<●)
恭候您的光临喔!!
↓↓↓
宝爱伊 难波店(大阪市中央区)
大阪府大阪市中央区千日前1-8-13 位于大阪中心最繁华的商业街的难波店,是我们的人气商店呢!
销售和收购同时进行中,敬请光临!
【营业时间】 AM11:00 ~ PM8:00 【定休日】 年中无休
【咨询电话】 06-6212-3133(中文对应可)
宝爱伊的网址:http://www.branday.com/cn/ (中文)
❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤★❤
主要品牌:
ルイ・ヴィトン 路易·威登
エルメス 爱马仕
シャネル 香奈儿
グッチ 古琦
コーチ 蔻驰
ディオール 迪奥
プラダ 普拉达
カルティエ 卡地亚
ブルガリ 宝格丽
バレンシアガ 巴黎世家
クロエ 克洛伊
ミュウミュウ 缪缪
バリー 巴利
ボッテガ・ヴェネタ 宝嘉
フェンディ 芬迪
セリーヌ 赛琳
タグ・ホイヤー 豪雅
ロレックス 劳力士
オメガ 欧米茄
销售&收购店地址:
宝爱伊 难波店(大阪市中央区)2011年10月开业
大阪府大阪市中央区千日前1-8-13 位于大阪中心最繁华的商业街的难波店,是我们的人气商店呢!
销售和收购同时进行中,敬请光临!
【营业时间】 AM11:00 ~ PM8:00 【定休日】 年中无休
【咨询电话】 06-6212-3133(中文对应可)
宝爱伊的网址:http://www.branday.com/cn/ (中文)
其他收购店地址:
难波店收购中心(大阪市中央区)2011年7月开业
大阪市中央区難波1-4-6 ミフネ難波ビル9F JR/地铁各线なんば駅步行即到。
【营业时间】 AM10:30 ~ PM7:00
【定休日】 星期日・日本国定假日
【咨询电话】 06-6214-2277(中文对应可)
梅田本店&收购专门店 2007年4月重新装修开业
大阪市北区中崎西2-2-1東梅田八千代ビル1階
【营业时间】 AM10:30 ~ PM7:00
【定休日】 星期日・日本国定假日
【咨询电话】 06-6362-0002
西九条駅前店(大阪市此花区) 2009年10月开业
大阪府大阪市此花区西九条1-32-16 サローネ西九条1F JR・阪神『西九条駅』徒步即到。
【营业时间】 AM10:30 ~ PM7:00
【定休日】 星期日・日本国定假日
【咨询电话】 06-6147-0007
2009年12月29日火曜日
主成分分析法图像处理
1.主成分的一般定义
设有随机变量X1,X2,…,Xp, 其样本均数记为 ,,…, ,样本标准差记为S1,S2,…,Sp。首先作标准化变换
我们有如下的定义:
(1) 若C1=a11x1+a12x2+ … +a1pxp, ,且使 Var(C1)最大,则称C1为第一主成分;
(2) 若C2=a21x1+a22x2+…+a2pxp, ,(a21,a22,…,a2p)垂直于(a11,a12,…,a1p),且使Var(C2)最大,则称C2为第二主成分;
(3) 类似地,可有第三、四、五…主成分,至多有p个。
2.主成分的性质
主成分C1,C2,…,Cp具有如下几个性质:
(1) 主成分间互不相关,即对任意i和j,Ci 和Cj的相关系数
Corr(Ci,Cj)=0 i ¹ j
(2) 组合系数(ai1,ai2,…,aip)构成的向量为单位向量,
(3) 各主成分的方差是依次递减的, 即
Var(C1)≥Var(C2)≥…≥Var(Cp)
(4) 总方差不增不减, 即
Var(C1)+Var(C2)+ … +Var(Cp)
=Var(x1)+Var(x2)+ … +Var(xp)
=p
这一性质说明,主成分是原变量的线性组合,是对原变量信息的一种改组,主成分不增加总信息量,也不减少总信息量。
(5) 主成分和原变量的相关系数 Corr(Ci,xj)=aij =aij
(6) 令X1,X2,…,Xp的相关矩阵为R, (ai1,ai2,…,aip)则是相关矩阵R的第i个特征向量(eigenvector)。而且,特征值li就是第i主成分的方差, 即
Var(Ci)= li
其中li为相关矩阵R的第i个特征值(eigenvalue)
l1≥l2≥…≥lp≥0
3.主成分的数目的选取
前已指出,设有p个随机变量,便有p个主成分。由于总方差不增不减,C1,C2等前几个综合变量的方差较大,而Cp,Cp-1等后几个综合变量的方差较小, 严格说来,只有前几个综合变量才称得上主(要)成份,后几个综合变量实为“次”(要)成份。实践中总是保留前几个,忽略后几个。
保留多少个主成分取决于保留部分的累积方差在方差总和中所占百分比(即累计贡献率),它标志着前几个主成分概括信息之多寡。实践中,粗略规定一个百分比便可决定保留几个主成分;如果多留一个主成分,累积方差增加无几,便不再多留。
4.主成分回归
主成分分析本身往往并不是目的,而是达到目的的一种手段。因此,它多用在大型研究项目的某个中间环节。例如,把它用在多重回归中,便产生了主成分回归。另外,它还可以用于聚类、判别分析等。
在多重回归曾指出,当自变量间高度相关时,某些回归参数的估计值极不稳定,甚至出现有悖常理、难以解释的情形。这时,可先采用主成分分析产生若干主成分,它们必定会将相关性较强的变量综合在同一个主成分中,而不同的主成分又是互相独立的。只要多保留几个主成分,原变量的信息不致过多损失。然后,以这些主成分为自变量进行多重回归就不会再出现共线性的困扰。如果原有p个自变量X1,X2,…,Xp,那么,采用全部p个主成分所作回归完全等价于直接对原变量的回归;采用一部分主成分所作回归虽不完全等价于对原变量的回归,但往往能摆脱某些虚假信息,而出现较合理的结果。
5.主成分分析与图像处理
在研究主成分分析方法基本原理的基础上,用MATLAB软件编写了的主成分分析代码用于神经元结构信息的MOST图片处理的程序,并 MATLB软件对图像进行分析,并对处理结果作比较分析。最后证明图像作主成分分析取得了较好的效果,具有一定的可靠性和实用性。
关于MOST图片的一些信息:MOST图片不适合用主成分分析除噪,去除非神经元的冗余信息,因为主成分分析的精髓在于变换和降维,需要有一个特征向量,变换提取出主成分,而MOST数据为灰度图,一个像素用一个0~255的数字表示,且一个位置只有一幅图像,特征向量为一维,无所谓提取,降维。但当把小块图片区域取出,所有像素点灰度构成一个特征向量,则这个向量维度很高(100*100的图片就是10'000维),但可以考虑用PCA提取主成分,降维,再用SVM,ANN等算法识别小块区域中是否有神经元,实现自动分割。
这里是采用记录CSD过程的图片集为例,应用Salwa Saleh编写的matlab代码,使用PCA方法处理后,得到了表现CSD扩散过程的图片。
6.使用PCA算法处理CSD图片集
(1)、材料:在小鼠发生CSD现象的时候,使用内源信号光学成像(OISI)技术,记录到的时间序列图片集
(2)、使用Salwa Saleh的matlab代码,运行程序,得到如下结果:
图一、PCA方法处理得到的一些成分。
图二、PCA方法处理后,与原始图片相减,得到的CSD扩散过程。
由处理结果可见,PCA方法提取出的主成份,清晰地表现出了CSD扩散过程。
附:Salwa Saleh的matlab代码源码
function [psi,a,ev]=pca(f,N)
% [psi,a,ev]=pca(f,N)
%
% Principal Component Analysis using by the Snapshot Method. (Sirovich, 1987)
% Use SVD instead if (# of images) > (# of pixels/image).
%
% MODEL: f = a * diag(sqrt(ev)) * psi'
%
% INPUT:
% f = matrix of images. (individual images are row vectors)
% N = the number of eigenpairs to compute. [default ALL]
%
% OUTPUT:
% psi = column vectors of spatial principal components.
% a = comumn vectors of temporal principal components.
% ev = PCA eigenvalues in descending order.
if size(f,1) > size(f,2)
disp('ERROR: The number of images exceeds the number of pixels/iamge.')
disp(' Consider using SVD instead.')
warning off; return;
end
disp('Forming the correlation matrix ...');
cor = f*f'; % the pixel-correlation matrix.
if nargin<2 % If N is not specified, compute all eigenpairs.
N=size(f,1);
end;
disp('Diagonalizing ...')
[a,ev]=eig(cor); % compute the temporal eigenvectors/values.
[ev,ind]=sort(diag(ev)); % sort in ascending magnitude.
ev=flipud(ev); % switch from ascending to descending.
a=a(:,flipud(ind)); % order the temporal eigenvectors accordingly.
disp('Calculating PCA eigenvectors ...')
a=a(:,1:N);
psi=f'*a*diag(ev(1:N).^-0.5); % compute the spatial eigenvectors.
参考文献:
[1]Salwa Saleh,Shangbin Chen,Dong Chen,Qingming Luo,Using Principal Component Analysis to Detect the
Wavefront of Cortical Spreading Depression
[2]Lu Chen(2007)“主元分析(PCA)理论分析及应用”
http://www.cad.zju.edu.cn/home/chenlu/pca.htm
[3]Jonathon Shlens.(2005)“A Tutorial on Principal Component Analysis”
http://www.snl.salk.edu/~shlens/pub/notes/pca.pdf
[4]aizaixiyuanqian1985提供(2008)“pca方法实现详细步骤”
http://www.pudn.com/downloads102/sourcecode/math/detail417142.html
[4]“[人脸识别Step2]对人脸图片作PCA降维”
http://www.sw-china.org/forum/simple/index.php?t40.html
设有随机变量X1,X2,…,Xp, 其样本均数记为 ,,…, ,样本标准差记为S1,S2,…,Sp。首先作标准化变换
我们有如下的定义:
(1) 若C1=a11x1+a12x2+ … +a1pxp, ,且使 Var(C1)最大,则称C1为第一主成分;
(2) 若C2=a21x1+a22x2+…+a2pxp, ,(a21,a22,…,a2p)垂直于(a11,a12,…,a1p),且使Var(C2)最大,则称C2为第二主成分;
(3) 类似地,可有第三、四、五…主成分,至多有p个。
2.主成分的性质
主成分C1,C2,…,Cp具有如下几个性质:
(1) 主成分间互不相关,即对任意i和j,Ci 和Cj的相关系数
Corr(Ci,Cj)=0 i ¹ j
(2) 组合系数(ai1,ai2,…,aip)构成的向量为单位向量,
(3) 各主成分的方差是依次递减的, 即
Var(C1)≥Var(C2)≥…≥Var(Cp)
(4) 总方差不增不减, 即
Var(C1)+Var(C2)+ … +Var(Cp)
=Var(x1)+Var(x2)+ … +Var(xp)
=p
这一性质说明,主成分是原变量的线性组合,是对原变量信息的一种改组,主成分不增加总信息量,也不减少总信息量。
(5) 主成分和原变量的相关系数 Corr(Ci,xj)=aij =aij
(6) 令X1,X2,…,Xp的相关矩阵为R, (ai1,ai2,…,aip)则是相关矩阵R的第i个特征向量(eigenvector)。而且,特征值li就是第i主成分的方差, 即
Var(Ci)= li
其中li为相关矩阵R的第i个特征值(eigenvalue)
l1≥l2≥…≥lp≥0
3.主成分的数目的选取
前已指出,设有p个随机变量,便有p个主成分。由于总方差不增不减,C1,C2等前几个综合变量的方差较大,而Cp,Cp-1等后几个综合变量的方差较小, 严格说来,只有前几个综合变量才称得上主(要)成份,后几个综合变量实为“次”(要)成份。实践中总是保留前几个,忽略后几个。
保留多少个主成分取决于保留部分的累积方差在方差总和中所占百分比(即累计贡献率),它标志着前几个主成分概括信息之多寡。实践中,粗略规定一个百分比便可决定保留几个主成分;如果多留一个主成分,累积方差增加无几,便不再多留。
4.主成分回归
主成分分析本身往往并不是目的,而是达到目的的一种手段。因此,它多用在大型研究项目的某个中间环节。例如,把它用在多重回归中,便产生了主成分回归。另外,它还可以用于聚类、判别分析等。
在多重回归曾指出,当自变量间高度相关时,某些回归参数的估计值极不稳定,甚至出现有悖常理、难以解释的情形。这时,可先采用主成分分析产生若干主成分,它们必定会将相关性较强的变量综合在同一个主成分中,而不同的主成分又是互相独立的。只要多保留几个主成分,原变量的信息不致过多损失。然后,以这些主成分为自变量进行多重回归就不会再出现共线性的困扰。如果原有p个自变量X1,X2,…,Xp,那么,采用全部p个主成分所作回归完全等价于直接对原变量的回归;采用一部分主成分所作回归虽不完全等价于对原变量的回归,但往往能摆脱某些虚假信息,而出现较合理的结果。
5.主成分分析与图像处理
在研究主成分分析方法基本原理的基础上,用MATLAB软件编写了的主成分分析代码用于神经元结构信息的MOST图片处理的程序,并 MATLB软件对图像进行分析,并对处理结果作比较分析。最后证明图像作主成分分析取得了较好的效果,具有一定的可靠性和实用性。
关于MOST图片的一些信息:MOST图片不适合用主成分分析除噪,去除非神经元的冗余信息,因为主成分分析的精髓在于变换和降维,需要有一个特征向量,变换提取出主成分,而MOST数据为灰度图,一个像素用一个0~255的数字表示,且一个位置只有一幅图像,特征向量为一维,无所谓提取,降维。但当把小块图片区域取出,所有像素点灰度构成一个特征向量,则这个向量维度很高(100*100的图片就是10'000维),但可以考虑用PCA提取主成分,降维,再用SVM,ANN等算法识别小块区域中是否有神经元,实现自动分割。
这里是采用记录CSD过程的图片集为例,应用Salwa Saleh编写的matlab代码,使用PCA方法处理后,得到了表现CSD扩散过程的图片。
6.使用PCA算法处理CSD图片集
(1)、材料:在小鼠发生CSD现象的时候,使用内源信号光学成像(OISI)技术,记录到的时间序列图片集
(2)、使用Salwa Saleh的matlab代码,运行程序,得到如下结果:
图一、PCA方法处理得到的一些成分。
图二、PCA方法处理后,与原始图片相减,得到的CSD扩散过程。
由处理结果可见,PCA方法提取出的主成份,清晰地表现出了CSD扩散过程。
附:Salwa Saleh的matlab代码源码
function [psi,a,ev]=pca(f,N)
% [psi,a,ev]=pca(f,N)
%
% Principal Component Analysis using by the Snapshot Method. (Sirovich, 1987)
% Use SVD instead if (# of images) > (# of pixels/image).
%
% MODEL: f = a * diag(sqrt(ev)) * psi'
%
% INPUT:
% f = matrix of images. (individual images are row vectors)
% N = the number of eigenpairs to compute. [default ALL]
%
% OUTPUT:
% psi = column vectors of spatial principal components.
% a = comumn vectors of temporal principal components.
% ev = PCA eigenvalues in descending order.
if size(f,1) > size(f,2)
disp('ERROR: The number of images exceeds the number of pixels/iamge.')
disp(' Consider using SVD instead.')
warning off; return;
end
disp('Forming the correlation matrix ...');
cor = f*f'; % the pixel-correlation matrix.
if nargin<2 % If N is not specified, compute all eigenpairs.
N=size(f,1);
end;
disp('Diagonalizing ...')
[a,ev]=eig(cor); % compute the temporal eigenvectors/values.
[ev,ind]=sort(diag(ev)); % sort in ascending magnitude.
ev=flipud(ev); % switch from ascending to descending.
a=a(:,flipud(ind)); % order the temporal eigenvectors accordingly.
disp('Calculating PCA eigenvectors ...')
a=a(:,1:N);
psi=f'*a*diag(ev(1:N).^-0.5); % compute the spatial eigenvectors.
参考文献:
[1]Salwa Saleh,Shangbin Chen,Dong Chen,Qingming Luo,Using Principal Component Analysis to Detect the
Wavefront of Cortical Spreading Depression
[2]Lu Chen(2007)“主元分析(PCA)理论分析及应用”
http://www.cad.zju.edu.cn/home/chenlu/pca.htm
[3]Jonathon Shlens.(2005)“A Tutorial on Principal Component Analysis”
http://www.snl.salk.edu/~shlens/pub/notes/pca.pdf
[4]aizaixiyuanqian1985提供(2008)“pca方法实现详细步骤”
http://www.pudn.com/downloads102/sourcecode/math/detail417142.html
[4]“[人脸识别Step2]对人脸图片作PCA降维”
http://www.sw-china.org/forum/simple/index.php?t40.html
登録:
投稿 (Atom)