PL/pgSQL�ϥȥꥬ�ץ��������������˻��ѤǤ��ޤ��� �ȥꥬ�ץ���������ϡ�CREATE FUNCTION���ޥ�ɤ�Ȥäơ�trigger�Ȥ�������ͤη�����ä������Τʤ��ؿ��Ȥ��ƺ�������ޤ��� ���δؿ��ϡ����Ȥ���CREATE TRIGGER�ˤư��������ΤȤ��Ƥ����Ȥ��Ƥ⡢����������ʤ���Τ�������ʤ���Фʤ�ޤ��� �ȥꥬ�ΰ����ϡ���Ҥ����̤ꡢTG_ARGV��ͳ���Ϥ���ޤ���
PL/pgSQL�ؿ����ȥꥬ�Ȥ��ƸƤӽФ��줿��硢�����Ĥ����ü���ѿ�����ưŪ�˺Ǿ�̥�٥�Υ֥��å��Ǻ�������ޤ��� ������ʲ��˼����ޤ���
RECORD�ǡ������� �����ѿ��Ϲԥ�٥�Υȥꥬ�Ǥ�INSERT/UPDATE���ˤ�äƹ������줿���������ǡ����١����ιԤ��ݻ����ޤ��� �����ѿ���ʸ��٥�Υȥꥬ�Ǥ�NULL�Ǥ���
RECORD�ǡ������� �����ѿ��ϡ��ԥ�٥�Υȥꥬ�Ǥ�UPDATE/DELETE���ˤ�äƹ�����������Υǡ����١����ιԤ��ݻ����ޤ��� �����ѿ���ʸ��٥�Υȥꥬ�Ǥ�NULL�Ǥ���
name�ǡ������� �ºݤ�ȯ�Ԥ��줿�ȥꥬ��̾��������ѿ���
text�ǡ������� �ȥꥬ������˰�¸����BEFORE�ޤ���AFTER�Ȥ���ʸ����
text�ǡ������� �ȥꥬ������˰�¸����ROW�ޤ���STATEMENT�Ȥ���ʸ����
text�ǡ������� �ȥꥬ��ȯ�Ԥ���������INSERT��UPDATE�ޤ���DELETE�Ȥ���ʸ����
oid�ǡ������� ���Υȥꥬ�θƤӽФ����ˤʤ�ơ��֥�Υ��֥�������ID��
name�ǡ������� ���Υȥꥬ�θƤӽФ����ˤʤ�ơ��֥��̾���� ���褳����ѻߤ��줽���Ǥ��� �����TG_TABLE_NAME����Ѥ��Ƥ���������
name�ǡ������� ���Υȥꥬ�θƤӽФ����ˤʤ�ơ��֥��̾����
name�ǡ������� ���Υȥꥬ�θƤӽФ����ˤʤ�ơ��֥�Υ�������̾��
integer���� CREATE TRIGGERʸ�ˤ�����ȥꥬ�ץ����������Ϳ����������ο���
text�������� CREATE TRIGGERʸ�Ǥΰ����� ���Υ���ǥå�����0����Ϥޤ�ޤ��� ̵���ʥ���ǥå�����0̤����tg_nargs�ʾ�ˤϡ�NULL�ͤȤ�����̤ˤʤ�ޤ���
�ȥꥬ�ؿ���NULL�ޤ��ϡ��ȥꥬ��ȯ�Ը��ˤʤä��ơ��֥�ι�¤�����Τ˻��ä��쥳����/�Ԥ��֤��ʤ���Фʤ�ޤ���
BEFORE�Ȥ���ȯ�Ԥ��줿�ԥ�٥�ȥꥬ��NULL���֤����ˤϡ��ȥꥬ�ޥ͡�����˼ºݤιԤؤ����������褦�����Τ��ޤ��ʤĤޤꡢ���θ�˥ȥꥬ��ȯ�Ԥ��줺������INSERT/UPDATE/DELETE�Ϥ��ιԤ��Ф��Ƽ¹Ԥ���ޤ���ˡ� ��NULL�ͤ��֤����ˤϡ��������Ϥ��ι��ͤǽ�������ޤ��� ����NEW���ͤȰۤʤ���ͤ��֤����Ȥϡ�����������������ͤ��ѹ����뤳�Ȥ����դ��Ƥ������� �ʤ�������DELETE�ξ���ľ�ܱƶ����ޤ���ˡ� ��Ǽ���٤��Ԥ��ѹ����뤿��ˡ�NEW�θġ����ͤ�ľ���֤�����������NEW���֤����Ȥ⡢�������쥳����/�Ԥ����˺��������֤����Ȥ��ǽ�Ǥ���
ʸ��٥��BEFORE�ޤ���AFTER�ȥꥬ���ԥ�٥��AFTER�ȥꥬ������ͤϾ��̵�뤵��ޤ��� NULL�Ȥ��Ƥ���ޤ��� �������������μ���Υȥꥬ�Ǥ⡢���顼��ȯ�������뤳�Ȥ�������Τ����Ǥ����뤳�Ȥ���ǽ�Ǥ���
例38-2��PL/pgSQL�Υȥꥬ�ؿ�������ޤ���
例 38-2. PL/pgSQL�ȥꥬ�ץ���������
���Υȥꥬ����Ǥϡ��ơ��֥�ιԤ������ޤ��Ϲ������줿���ˤ�ɬ�������ߤΥ桼��̾�Ȼ��郎���ιԤ����äƤ��뤳�Ȥ�μ¤ˤ��ޤ��� �����ơ����Ȱ�̾��Ϳ�����Ƥ��뤳�ȤȤ��ε����������ͤǤ��뤳�Ȥ��ǧ���ޤ���
CREATE TABLE emp ( empname text, salary integer, last_date timestamp, last_user text ); CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$ BEGIN -- empname��salary��Ϳ�����Ƥ��뤳�Ȥ�����å� IF NEW.empname IS NULL THEN RAISE EXCEPTION 'empname cannot be null'; END IF; IF NEW.salary IS NULL THEN RAISE EXCEPTION '% cannot have null salary', NEW.empname; END IF; -- ��ʧ�������꤬������ʤ��褦�� IF NEW.salary < 0 THEN RAISE EXCEPTION '% cannot have a negative salary', NEW.empname; END IF; -- ï�������ѹ���������Ͽ NEW.last_date := current_timestamp; NEW.last_user := current_user; RETURN NEW; END; $emp_stamp$ LANGUAGE plpgsql; CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp FOR EACH ROW EXECUTE PROCEDURE emp_stamp();
�ơ��֥�ˤ������ѹ��Υ�������¾����ˡ�ϡ������������ޤ��Ϻ���γơ����Ф���Ԥ���ͭ���뿷�ơ��֥��������뤳�ȤǤ��� ������ˡ�ϥơ��֥�ˤ������ѹ��δƺ��ȹͤ��뤳�Ȥ��Ǥ��ޤ���
例38-3��PL/pgSQL�ˤ��ƺ��ѥȥꥬ�ץ���������ΰ�����ޤ���
例 38-3. PL/pgSQL�ˤ�� �ƺ��ѤΥȥꥬ�ץ���������
���Υȥꥬ����Ǥϡ�emp�ơ��֥�ˤ�����Ԥ������������ޤ��Ϻ���Τɤ�⤬emp_audit�ơ��֥����سμ¤˵�Ͽ�ʤ��ʤ���ƺ��ˤ���ޤ��� ������ȥ桼��̾�ϡ��Ԥä����μ���ȤȤ��emp_audit�ιԤ�����ǹ蘆��ޤ���
CREATE TABLE emp ( empname text NOT NULL, salary integer ); CREATE TABLE emp_audit( operation char(1) NOT NULL, stamp timestamp NOT NULL, userid text NOT NULL, empname text NOT NULL, salary integer ); CREATE OR REPLACE FUNCTION process_emp_audit() RETURNS TRIGGER AS $emp_audit$ BEGIN -- -- emp�ǹԤä�����ȿ�Ǥ���Ԥ�emp_audit�˺��� -- ���μ������ꤹ�뤿��ˡ��ü���ѿ�TG_OP����� -- IF (TG_OP = 'DELETE') THEN INSERT INTO emp_audit SELECT 'D', now(), user, OLD.*; RETURN OLD; ELSIF (TG_OP = 'UPDATE') THEN INSERT INTO emp_audit SELECT 'U', now(), user, NEW.*; RETURN NEW; ELSIF (TG_OP = 'INSERT') THEN INSERT INTO emp_audit SELECT 'I', now(), user, NEW.*; RETURN NEW; END IF; RETURN NULL; -- AFTER�ȥꥬ�Ǥ��Τǡ���̤�̵�뤵��ޤ� END; $emp_audit$ LANGUAGE plpgsql; CREATE TRIGGER emp_audit AFTER INSERT OR UPDATE OR DELETE ON emp FOR EACH ROW EXECUTE PROCEDURE process_emp_audit();
�ȥꥬ�λ�����Ū��1�Ĥϡ�����ơ��֥�Υ��ޥ�ơ��֥�ʥǡ�����ȴ�褷���ơ��֥�ˤ�ݻ����뤳�ȤǤ��� ���ޥ�ơ��֥�ϡ����Υơ��֥�����äơ��������䤤��碌���Ф��ƻ��ѤǤ������Ф��м¹Ի��֤������˽̾����ޤ��� �̾盧�μ�ˡ�ϥǡ����������ϥ����˻��Ѥ��졢��¬�ޤ��ϴ�¬�ǡ����ʥե����ȥơ��֥�ȸ����ޤ��ˤ������礭�����뤳�Ȥ��Ǥ��ޤ��� �ǡ����������ϥ�����Υե����ȥơ��֥���Ф��ƥ��ޥ�ơ��֥��ݻ�����PL/pgSQL�Υȥꥬ�ץ�������������例38-4�˼����ޤ���
例 38-4. ���ޥ�ơ��֥��ݻ����뤿���PL/pgSQL�ȥꥬ�ץ���������
�����˽Ҥ٤륹�����ޤΰ�����Ralph Kimball�ˤ��The Data Warehouse Toolkit��Grocery Store����˴�Ť��Ƥ��ޤ���
-- -- time dimension��sales fact�μ�ơ��֥� -- CREATE TABLE time_dimension ( time_key integer NOT NULL, day_of_week integer NOT NULL, day_of_month integer NOT NULL, month integer NOT NULL, quarter integer NOT NULL, year integer NOT NULL ); CREATE UNIQUE INDEX time_dimension_key ON time_dimension(time_key); CREATE TABLE sales_fact ( time_key integer NOT NULL, product_key integer NOT NULL, store_key integer NOT NULL, amount_sold numeric(12,2) NOT NULL, units_sold integer NOT NULL, amount_cost numeric(12,2) NOT NULL ); CREATE INDEX sales_fact_time ON sales_fact(time_key); -- -- sales by time�Υ��ޥ�ơ��֥� -- CREATE TABLE sales_summary_bytime ( time_key integer NOT NULL, amount_sold numeric(15,2) NOT NULL, units_sold numeric(12) NOT NULL, amount_cost numeric(15,2) NOT NULL ); CREATE UNIQUE INDEX sales_summary_bytime_key ON sales_summary_bytime(time_key); -- -- ��������������Ӻ���ˤ�ꥵ�ޥ�ơ��֥�����������ؿ��ȥȥꥬ -- CREATE OR REPLACE FUNCTION maint_sales_summary_bytime() RETURNS TRIGGER AS $maint_sales_summary_bytime$ DECLARE delta_time_key integer; delta_amount_sold numeric(15,2); delta_units_sold numeric(12); delta_amount_cost numeric(15,2); BEGIN -- ���äޤ��ϸ����̤� IF (TG_OP = 'DELETE') THEN delta_time_key = OLD.time_key; delta_amount_sold = -1 * OLD.amount_sold; delta_units_sold = -1 * OLD.units_sold; delta_amount_cost = -1 * OLD.amount_cost; ELSIF (TG_OP = 'UPDATE') THEN -- time_key���ѹ����빹����ػߤ��ޤ� -- �ʺ�� + ��������ˡ�ˤ������ʬ���ѹ���Ԥ����� -- ����ۤ����ǤϤ���ޤ���ˡ� IF ( OLD.time_key != NEW.time_key) THEN RAISE EXCEPTION 'Update of time_key : % -> % not allowed', OLD.time_key, NEW.time_key; END IF; delta_time_key = OLD.time_key; delta_amount_sold = NEW.amount_sold - OLD.amount_sold; delta_units_sold = NEW.units_sold - OLD.units_sold; delta_amount_cost = NEW.amount_cost - OLD.amount_cost; ELSIF (TG_OP = 'INSERT') THEN delta_time_key = NEW.time_key; delta_amount_sold = NEW.amount_sold; delta_units_sold = NEW.units_sold; delta_amount_cost = NEW.amount_cost; END IF; -- ���ޥ�ơ��֥�ιԤ������ޤ��Ͽ������ͤǹ������ޤ��� <<insert_update>> LOOP UPDATE sales_summary_bytime SET amount_sold = amount_sold + delta_amount_sold, units_sold = units_sold + delta_units_sold, amount_cost = amount_cost + delta_amount_cost WHERE time_key = delta_time_key; EXIT insert_update WHEN found; BEGIN INSERT INTO sales_summary_bytime ( time_key, amount_sold, units_sold, amount_cost) VALUES ( delta_time_key, delta_amount_sold, delta_units_sold, delta_amount_cost ); EXIT insert_update; EXCEPTION WHEN UNIQUE_VIOLATION THEN -- ���⤷�ޤ��� END; END LOOP insert_update; RETURN NULL; END; $maint_sales_summary_bytime$ LANGUAGE plpgsql; CREATE TRIGGER maint_sales_summary_bytime AFTER INSERT OR UPDATE OR DELETE ON sales_fact FOR EACH ROW EXECUTE PROCEDURE maint_sales_summary_bytime(); INSERT INTO sales_fact VALUES(1,1,1,10,3,15); INSERT INTO sales_fact VALUES(1,2,1,20,5,35); INSERT INTO sales_fact VALUES(2,2,1,40,15,135); INSERT INTO sales_fact VALUES(2,3,1,10,1,13); SELECT * FROM sales_summary_bytime; DELETE FROM sales_fact WHERE product_key = 1; SELECT * FROM sales_summary_bytime; UPDATE sales_fact SET units_sold = units_sold * 2; SELECT * FROM sales_summary_bytime;