Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
a294726b
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a294726b
编写于
1月 14, 2005
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Incorporate examples and doc patches from Mark Kirkwood and David Fetter.
上级
29e58330
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
203 addition
and
5 deletion
+203
-5
doc/src/sgml/plpgsql.sgml
doc/src/sgml/plpgsql.sgml
+180
-3
doc/src/sgml/ref/alter_table.sgml
doc/src/sgml/ref/alter_table.sgml
+12
-1
doc/src/sgml/ref/create_opclass.sgml
doc/src/sgml/ref/create_opclass.sgml
+11
-1
未找到文件。
doc/src/sgml/plpgsql.sgml
浏览文件 @
a294726b
<!--
$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.5
5 2005/01/08 22:13:34
tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.5
6 2005/01/14 01:16:22
tgl Exp $
-->
<chapter id="plpgsql">
...
...
@@ -2304,6 +2304,32 @@ SELECT reffunc2();
FETCH ALL IN "<unnamed cursor 1>";
COMMIT;
</programlisting>
</para>
<para>
The following example shows one way to return multiple cursors
from a single function:
<programlisting>
CREATE FUNCTION myfunc(refcursor, refcursor) RETURNS SETOF refcursor AS $$
BEGIN
OPEN $1 FOR SELECT * FROM table_1;
RETURN NEXT $1;
OPEN $2 FOR SELECT * FROM table_2;
RETURN NEXT $2;
RETURN;
END;
$$ LANGUAGE plpgsql;
-- need to be in a transaction to use cursors.
BEGIN;
SELECT * FROM myfunc('a', 'b');
FETCH ALL FROM a;
FETCH ALL FROM b;
COMMIT;
</programlisting>
</para>
</sect3>
...
...
@@ -2585,8 +2611,6 @@ $emp_stamp$ LANGUAGE plpgsql;
CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
FOR EACH ROW EXECUTE PROCEDURE emp_stamp();
</programlisting>
</example>
<para>
...
...
@@ -2646,6 +2670,159 @@ AFTER INSERT OR UPDATE OR DELETE ON emp
FOR EACH ROW EXECUTE PROCEDURE process_emp_audit();
</programlisting>
</example>
<para>
One use of triggers is to maintain a summary table
of another table. The resulting summary can be used in place of the
original table for certain queries — often with vastly reduced run
times.
This technique is commonly used in Data Warehousing, where the tables
of measured or observed data (called fact tables) can be extremely large.
<xref linkend="plpgsql-trigger-summary-example"> shows an example of a
trigger procedure in <application>PL/pgSQL</application> that maintains
a summary table for a fact table in a data warehouse.
</para>
<example id="plpgsql-trigger-summary-example">
<title>A <application>PL/pgSQL</application> Trigger Procedure For Maintaining A Summary Table</title>
<para>
The schema detailed here is partly based on the <emphasis>Grocery Store
</emphasis> example from <emphasis>The Data Warehouse Toolkit</emphasis>
by Ralph Kimball.
</para>
<programlisting>
--
-- Main tables - time dimension and 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);
--
-- Summary table - 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);
--
-- Function and trigger to amend summarized column(s) on 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
-- Work out the increment/decrement amount(s).
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
-- forbid updates that change the time_key -
-- (probably not too onerous, as DELETE + INSERT is how most
-- changes will be made).
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 the summary row with the new values.
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)
SELECT f.time_key,
sum(f.amount_sold),
sum(f.units_sold),
sum(f.amount_cost)
FROM sales_fact f
WHERE f.time_key = delta_time_key
GROUP BY f.time_key;
-- This query can potentially be very expensive if the trigger
-- is created on sales_fact without the time_key indexes.
-- Some care is needed to ensure that this situation does
-- *not* occur.
EXCEPTION
--
-- Catch race condition when two transactions are adding data
-- for a new time_key.
--
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();
</programlisting>
</example>
</sect1>
<!-- **** Porting from Oracle PL/SQL **** -->
...
...
doc/src/sgml/ref/alter_table.sgml
浏览文件 @
a294726b
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.7
6 2005/01/10 00:04:43
tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.7
7 2005/01/14 01:16:52
tgl Exp $
PostgreSQL documentation
-->
...
...
@@ -537,6 +537,17 @@ ALTER TABLE distributors
</programlisting>
</para>
<para>
To change an integer column containing UNIX timestamps to <type>timestamp
with time zone</type> via a <literal>USING</literal> clause:
<programlisting>
ALTER TABLE foo
ALTER COLUMN foo_timestamp TYPE timestamp with time zone
USING
timestamp with time zone 'epoch' + foo_timestamp * interval '1 second';
</programlisting>
</para>
<para>
To rename an existing column:
<programlisting>
...
...
doc/src/sgml/ref/create_opclass.sgml
浏览文件 @
a294726b
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_opclass.sgml,v 1.1
2 2003/11/29 19:51:38 pgsq
l Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/create_opclass.sgml,v 1.1
3 2005/01/14 01:16:52 tg
l Exp $
PostgreSQL documentation
-->
...
...
@@ -205,6 +205,16 @@ CREATE OPERATOR CLASS <replaceable class="parameter">name</replaceable> [ DEFAUL
</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>
The operators should not be defined by SQL functions. A SQL function
is likely to be inlined into the calling query, which will prevent
the optimizer from recognizing that the query matches an index.
</para>
</refsect1>
<refsect1>
<title>Examples</title>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录