PostgreSQL 8.0.0 �����ĵ���PostgreSQL �й� ������ | ||||
---|---|---|---|---|
Prev | Fast Backward | Chapter 35. PL/pgSQL - SQL �������� | Fast Forward | Next |
PL/pgSQL �������ڶ��崥�������̡� һ���������������� CREATE FUNCTION ������ģ� ��������ʽ��һ�������ܲ������ҷ��� trigger ���͵ĺ����� ��ע��ú�����ʹ�� CREATE TRIGGER ����������Ϊ�����ܲ����� ��Ҳ��������Ϊ���� — �������IJ�����ͨ�� TG_ARGV ���ݵģ�������������
��һ�� PL/pgSQL �����������������õ�ʱ�� ϵͳ���ڶ�������������Զ��������������������������Щ��
���������� RECORD�� �ñ���ΪINSERT/UPDATE ����ʱ�����У�ROW��һ���Ĵ������µ����ݿ��С� ����伶��Ĵ��������������� NULL��
���������� RECORD�� �ñ���Ϊ INSERT/UPDATE ����ʱ�����У�ROW��һ���Ĵ������µ����ݿ��С� ����伶��Ĵ��������������� NULL��
���������� name���ñ�������ʵ�ʴ����Ĵ��������� fired.
���������� text����һ���ɴ���������������ַ����� Ҫô�� BEFORE Ҫô�� AFTER��
���������� text����һ���ɴ���������������ַ����� Ҫô�� ROW Ҫô�� STATEMENT��
���������� text����һ��˵�������������IJ������ַ����� ������ INSERT��UPDATE ���� DELETE��
���������� oid���ǵ��´��������õı�Ķ����ʶ��OID����
���������� name���Ǽ���������õı�����ơ�
���������� integer�� ����CREATE TRIGGER ������渳�败�������̵IJ����ĸ�����
���������� text �����飻�� CREATE TRIGGER�����IJ����� �±�� 0 ��ʼ�������Ƿ��±꣨С�� 0 ���ߴ��ڵ��� tg_nargs�����·���һ�� NULL ֵ��
һ���������������뷵�� NULL ������ һ���뵼�´��������еı�ļ�¼/����ȫһ���Ľṹ�����ݡ�
��BEFORE�������м���ĵĴ��������Է���һ�� NULL�����ߴ��������������ԶԸ���ʣ�µIJ��� ��Ҳ����˵�����Ĵ�����������ִ�У����Ҳ���Ը��в���INSERT/UPDATE/DELETE�������� ���������һ���� NULL ���У���ô�������Ը�����ֵ���д��� ��ע�⣬����һ����ԭ����NEW��ͬ������ֵ�����Ǹ����������µ��С� ���ǿ�����һ��ֱֵ�Ӵ���NEW���ij����ֵ���ҷ���֮����������Ҳ���Թ���һ����ȫ�µļ�¼/���ٷ��ء�
BEFORE ���� AFTER��伶��Ĵ������� ����һ��AFTER �м���Ĵ������ķ���ֵ�����DZ����ԣ� ����Ҳ���Է��� NULL �����Է���ֵ���������κ��������͵Ĵ�������Ȼ���� ͨ���׳�һ���������˳�����������������
Example 35-1 ��ʾ��һ�� PL/pgSQL д�Ĵ��������̵����ӡ�
Example 35-1. һ��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 ISNULL THEN RAISE EXCEPTION 'empname cannot be null'; END IF; IF NEW.salary ISNULL THEN RAISE EXCEPTION '% cannot have null salary', NEW.empname; END IF; -- ���DZ��븶�ʸ�˭�� IF NEW.salary < 0 THEN RAISE EXCEPTION '% cannot have a negative salary', NEW.empname; END IF; -- ��ס��ʱ���˵�нˮ������ NEW.last_date := 'now'; 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();
����һ��������¼�仯�ķ����漰����һ���±�Ȼ��Ϊ����������ÿ�β��롢���»���ɾ����������һ�С� ����������Ե�����һ�������ơ� Example 35-2 ��ʾ��һ�� PL/pgSQL д����ƴ��������̵����ӡ�
Example 35-2. һ��������Ƶ� PL/pgSQL ����������
������Ӵ�������֤���� emp ���ϵ��κβ��룬 ���»���ɾ������������¼���� emp_audit ���Ҳ���ǣ���ƣ��� ��ǰʱ����û����ᱻ��¼����������Լ�����ִ�еIJ�����
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_audit �ﴴ��һ�У���ӳ�� emp �IJ����� -- ʹ��������� 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; 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() ;
��������һ����;��ά������һ����ĸ�Ҫ�����ɵĸ�Ҫ����������ijЩ��ѯ�д���ԭʼ�� — ͨ�����Դ����С����ʱ�䡣 ������ɾ����������ݲֿ⣬���ʱ����Ҫ�����ı�����ʵ�����ܻ�dz��� Example 35-3 ��ʾ��һ�� PL/pgSQL ���������̵����ӣ� ��Ϊij�����ݲֿ��һ����ʵ��ά��һ����Ҫ��
Example 35-3. һ��ά����Ҫ��� PL/pgSQL ����������
�����ģʽ��һ�����ǻ��� Ralph Kimball ��The Data Warehouse Toolkit ����� Grocery Store ���ӡ�
-- -- ���� - ʱ��ά�Լ�������ʵ�� -- 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); -- -- ժҪ�� - ����ʱ������ۡ� -- 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); -- -- �� UPDATE��INSERT��DELETE ��ʱ����¸�Ҫ�ֶεĺ����ʹ������� -- 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 �ĸ��� - -- �����ܲ����Ǻ�ǿ�ƣ���Ϊ DELETE + INSERT �Ǵ�������� -- �������ģ��� 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; -- ������ֵ���¸�Ҫ�С� 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; -- There might have been no row with this time_key (e.g new data!). IF (NOT FOUND) THEN 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 ); EXCEPTION -- -- ������������άһ���� time_key �������ݵij�ͻ���� -- WHEN UNIQUE_VIOLATION THEN 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; END; END IF; 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();