Oracle TriggersとCursorsを高速に学ぶ
トリガー
1. ユーザーアクションを記録するトリガーを作成する
dept_logデータテーブルを作成し、操作種別(挿入、変更、削除)情報と操作日時を格納する2つのフィールド(operation_tag varchar2(10),operation_time date)を定義します。そして、deptテーブル上のステートメントレベルトリガtri_deptは、deptテーブルに対するユーザ操作の情報をdept_tagテーブルに保存します。
ある部門がいつでもdeptテーブルから削除されると、このトリガは、その部門のすべての従業員をempテーブルから削除します。
-- Create the table
create table dept_log(
operate_tag varchar2(10),
operate_time date
);
create table dept(
dname varchar2(20),
dno number
);
-- Create a trigger
create or replace trigger tri_dept
before insert or update or delete
on dept
declare
v_tag varchar2(10);
begin
if inserting then
v_tag:='inserting';
elsif updating then
v_tag:='modify';
elsif deleting then
v_tag:='deleting';
end if;
insert into dept_log values(v_tag, sysdate);
end tri_dept;
/
2. ある部署が削除されたとき、その部署に所属するすべての従業員を削除するトリガーを作成します。
deptテーブルから部門が削除されるたびに、このトリガはempテーブルからその部門に属するすべての従業員を削除します。
注意:sysdba としてログインしているすべてのアカウントはトリガーを作成できないので、作成したユーザーで作成する必要があります。
-- Create the department table
create table dept(
deptno number not null,
dname varchar(20) not null
);
-- Create the employee table
create table emp(
emp_no number not null,
emp_name varchar(20) not null,
job varchar(20) not null,
sal number not null,
deptno number not null
);
--insert data
insert into dept values(10, 'department1');
insert into dept values(20, 'department2');
insert into emp values(1001, 'employee1', 'job1', 5000, 10);
insert into emp values(1002, 'employee2', 'job2', 7200, 10);
insert into emp values(1003, 'employee3', 'job3', 6000, 10);
insert into emp values(1004, 'employee4', 'job4', 5000, 20);
insert into emp values(1005, 'employee5', 'job5', 7000, 20);
-- Create a trigger
create or replace trigger del_dept
before delete on dept
for each row
begin
delete from emp where deptno = :old.deptno;
end;
/end
3. アカウントテーブルにレコードを挿入した後、myeventデータテーブルを更新するトリガーを作成します。
アカウントテーブルにデータを挿入した後、myeventテーブルにデータセットを挿入するTRIG_INSERTトリガーを作成(テーブル構造は作成されません...)。
create or replace trigger trig_insert
after insert
on account
begin
if inserting then
insert into myevent values(1, 'after insert');
end if;
end;
/
4. DBA IDにログインしたユーザーのユーザー名と時間を記録するトリガーを作成します。
DBAとしてデータベースにログインし、db_logというデータテーブルを作成して、ログインしたユーザーのユーザー名と時刻を記録します。
次に、データベース起動トリガーとデータベース停止トリガーをそれぞれ作成し、db_logデータテーブルにレコードを挿入して、ログインしたユーザーのユーザー名と操作時刻を保存します。
-- Create the table
create table db_log(
name varchar2(20),
rtime timestamp
);
-- Create a trigger to log user login
create or replace trigger trigger_startup
after startup
on database
begin
insert into db_log values('user', sysdate);
end;
/
-- Create a trigger to log the user out
create or replace trigger trigger_shutdown
before shutdown
on database
begin
insert into db_log values('xiuyan', sysdate);
end;
/
カーソル
次のトピックは、部署と従業員テーブルに基づいています。
-- Create the table
create table emp(
empno number,
ename varchar2(20),
job varchar2(20),
sal number,
deptno number);
create table dept(
deptno number,
dname varchar2(20),
loc varchar2(20));
-- insert data
insert into dept values(10,'account','new york');
insert into dept values(20,'salesman','chicago');
insert into dept values(30,'research','dallas');
insert into dept values(40,'operations','boston');
insert into emp values(1001,'mary','account',5000,10);
insert into emp values(2001,'smith','salesman',6000,20);
insert into emp values(3001,'kate','research',7000,30);
1. 暗黙のカーソルとfor文を使って、職種がセールスマンである社員の情報を取得し、次のように出力します。
begin
for emp_record in(select empno, ename, sal from emp where job='salesman')
loop
dbms_output.put('Employee number:'||emp_record.empno);
dbms_output.put('; employee name: '||emp_record.ename);
dbms_output.put_line('; Employee number: '||emp_record.sal);
end loop;
end;
/
2.従業員の給与が20%増加した場合、暗黙のカーソルを使用して給与が増加した従業員の数を出力します。
empテーブルのセールスマンの給料を20%上げ、暗黙のカーソルSQLの%ROWCOUNTプロパティを使用して、給料が上がった従業員の数を出力してください。
begin
update emp set sal=sal*(1+0.2) where job='salesman';
if sql%notfound then
dbms_output.put_line('No employees need an upward salary adjustment');
else
dbms_output.put_line('There are'|| sql%rowcount || 'employees who need an upward pay adjustment');
end if;
end;
/
3. 表示カーソルとfor文を使って、部署番号が30の社員の情報を取得し、次のように出力します。
declare
cursor cur_emp is
select * from emp where deptno = 30;
begin
for emp_record in cur_emp
loop
dbms_output.put('Employee number:' ||emp_record.empno);
dbms_output.put('; employee name: '||emp_record.ename);
dbms_output.put_line('; Employee job:'||emp_record.job);
end loop;
end;
/
4. 社員情報を取得するカーソルを宣言し、%FOUND属性で
指定された社員番号の社員情報を取得するカーソルを宣言し、カーソルの%FOUND属性を使って、指定された社員番号の社員情報が取得できたかどうかを判断します。
declare
v_ename varchar2(50);
v_job varchar2(50);
cursor cur_emp is
select ename, job from emp where empno = &empno;
begin
open cur_emp;
fetch cur_emp into v_ename, v_job;
if cur_emp%found then
dbms_output.put('Employee number:'||v_ename ||',job is:'||v_job );
else
dbms_output.put('No data record');
end if;
end;
/
5. データ転送を完了するためにカーソルを作成し、fruitテーブルのレコードのうち単価が10より大きいものをfruitageテーブルへ入れる
果物テーブルを作成し、データを挿入する
-- Create the fruit table
create table fruit(
f_id varchar2(10) not null,
f_name varchar2(255) not null,
f_price number (8,2) not null
);
--insert data
insert into fruit values ('a1', 'apple',5.2);
insert into fruit values ('b1','blackberry', 10.2);
insert into fruit values ('bs1','orange', 11.2);
insert into fruit values ('bs2','melon', 8.2);
insert into fruit values ('t1','banana', 10.3);
insert into fruit values ('t2','grape', 5.3);
insert into fruit values ('o2','coconut', 9.2);
テーブルfruitと同じフィールドを持つテーブルfruitageを以下の文で作成します。
create table fruitage as select * from fruit where 2=3;
-- If the condition after WHERE is true, the data is copied along with the table when it is copied.
-- No default will copy the data.
データ転送を完了するためにカーソルを作成し、果物テーブルのレコードのうち単価が10より大きいものをfruitageテーブルに入れる。
declare
v_id fruit.f_id %TYPE;
v_name fruit.f_name %TYPE;
v_price fruit.f_price %TYPE;
cursor frt_cur is
select f_id, f_name, f_price from fruit where f_price>10;
begin
open frt_cur;
loop
fetch frt_cur into v_id, v_name, v_price;
if frt_cur%found then
insert into fruitage values(v_id, v_name, v_price);
else
dbms_output.put_line('All data retrieved, total '||frt_cur%ROWCOUNT||'rows');
exit;
end if;
end loop;
close frt_cur;
end;
/
この記事は、Oracle Triggers and Cursorsに関するものです。Oracle Triggers and Cursorsの詳細については、Script Houseの過去の記事を検索するか、以下の記事を引き続き参照してください。
関連
-
オラクルはADGとDGのケースを詳細に区別している
-
SQLPlusコマンドの使い方の説明
-
[解決済み】ORA-30926:ソーステーブルの安定した行のセットを取得できません。
-
[解決済み] エラーを取得する - ORA-01858: 数値が期待される場所で非数値文字が見つかりました。
-
[解決済み】Oracle "SQL Error: Missing IN or OUT parameter at index:: 1" と表示されました。
-
[解決済み] ORA-12545: ターゲットホストまたはオブジェクトが Mac に存在しないため、接続に失敗しました - SQLPLUS
-
[解決済み] ORA-01799: 列がサブクエリに外部結合されていない可能性があります。
-
[解決済み] PLS-00382: 式が不正です。
-
[解決済み] オラクル ユーザーデータでConnect By Loop
-
[解決済み] ORA-01407:NULLに更新できません。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Oracle Databaseの失敗したオブジェクトの処理の詳細
-
オラクルユーザー作成プロセスの説明
-
オラクルのTO_DATEの使い方解説
-
[解決済み] エラー発生 - ORA-01858: 数値が期待される場所に非数値の文字が見つかりました。
-
[解決済み] Oracle の起動ができません - ORA-00845: MEMORY_TARGET はこのシステムでサポートされていません - しかし、メモリサイズは問題ないようです。
-
[解決済み] libclntsh.so.11.1: 共有オブジェクト・ファイルを開くことができません。
-
[解決済み] Oracleで変数を宣言して表示する方法
-
[解決済み] oracle pl/sql DBMS_LOCK エラー
-
[解決済み] ORA-01747:user.table.column, table.column, または column の指定が無効です。
-
[解決済み] ORA-04082: テーブルレベルのトリガーで NEW または OLD 参照は許可されません。