`
zjut_xiongfeng
  • 浏览: 280188 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

存储过程的使用方法

阅读更多

在pgadmin里试了一下的例子,还不错,对于初学者来说是不错的资料。

PL/pgSQL can be used to define trigger procedures. A trigger procedure is created with the CREATE FUNCTION command, declaring it as a function with no arguments and a return type of trigger. Note that the function must be declared with no arguments even if it expects to receive arguments specified in CREATE TRIGGER---trigger arguments are passed via TG_ARGV, as described below.

When a PL/pgSQL function is called as a trigger, several special variables are created automatically in the top-level block. They are:

NEW
Data type RECORD; variable holding the new database row for INSERT/UPDATE operations in row-level triggers. This variable is NULL in statement-level triggers.
OLD
Data type RECORD; variable holding the old database row for UPDATE/DELETE operations in row-level triggers. This variable is NULL in statement-level triggers.
TG_NAME
Data type name; variable that contains the name of the trigger actually fired.
TG_WHEN
Data type text; a string of either BEFORE or AFTER depending on the trigger's definition.
TG_LEVEL
Data type text; a string of either ROW or STATEMENT depending on the trigger's definition.
TG_OP
Data type text; a string of INSERT, UPDATE, or DELETE telling for which operation the trigger was fired.
TG_RELID
Data type oid; the object ID of the table that caused the trigger invocation.
TG_RELNAME
Data type name; the name of the table that caused the trigger invocation. This is now deprecated, and could disappear in a future release. Use TG_TABLE_NAME instead.
TG_TABLE_NAME
Data type name; the name of the table that caused the trigger invocation.
TG_TABLE_SCHEMA
Data type name; the name of the schema of the table that caused the trigger invocation.
TG_NARGS
Data type integer; the number of arguments given to the trigger procedure in the CREATE TRIGGER statement.
TG_ARGV[]
Data type array of text; the arguments from the CREATE TRIGGER statement. The index counts from 0. Invalid indices (less than 0 or greater than or equal to tg_nargs) result in a null value.

A trigger function must return either NULL or a record/row value having exactly the structure of the table the trigger was fired for.

Row-level triggers fired BEFORE may return null to signal the trigger manager to skip the rest of the operation for this row (i.e., subsequent triggers are not fired, and the INSERT/UPDATE/DELETE does not occur for this row). If a nonnull value is returned then the operation proceeds with that row value. Returning a row value different from the original value of NEW alters the row that will be inserted or updated (but has no direct effect in the DELETE case). To alter the row to be stored, it is possible to replace single values directly in NEW and return the modified NEW, or to build a complete new record/row to return.

The return value of a BEFORE or AFTER statement-level trigger or an AFTER row-level trigger is always ignored; it may as well be null. However, any of these types of triggers can still abort the entire operation by raising an error.

section 9.10 Trigger Procedures shows an example of a trigger procedure in PL/pgSQL.

A PL/pgSQL Trigger Procedure:

This example trigger ensures that any time a row is inserted or updated in the table, the current user name and time are stamped into the row. And it checks that an employee's name is given and that the salary is a positive value.

CREATE TABLE emp (
    empname text,
    salary integer,
    last_date timestamp,
    last_user text
);

CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
    BEGIN
        -- Check that empname and salary are given
        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;

        -- Who works for us when she must pay for it?
        IF NEW.salary < 0 THEN
            RAISE EXCEPTION '% cannot have a negative
 salary', NEW.empname;
        END IF;

        -- Remember who changed the payroll when
        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();

Another way to log changes to a table involves creating a new table that holds a row for each insert, update, or delete that occurs. This approach can be thought of as auditing changes to a table. section 9.10 Trigger Procedures shows an example of an audit trigger procedure in PL/pgSQL.

A PL/pgSQL Trigger Procedure For Auditing:

This example trigger ensures that any insert, update or delete of a row in the emp table is recorded (i.e., audited) in the emp_audit table. The current time and user name are stamped into the row, together with the type of operation performed on it.

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
        --
        -- Create a row in emp_audit to reflect the
        -- operation performed on emp, make use of the
        -- special variable TG_OP to work out the
        -- operation.
        --
        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; -- result is ignored since this is an
 AFTER trigger
    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();

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. section 9.10 Trigger Procedures shows an example of a trigger procedure in PL/pgSQL that maintains a summary table for a fact table in a data warehouse.

A PL/pgSQL Trigger Procedure For Maintaining A Summary Table:

The schema detailed here is partly based on the Grocery Store example from The Data Warehouse Toolkit by Ralph Kimball.

--
-- 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;

        -- Insert or update the summary row with the new values.
        <<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
                    -- do nothing
            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;

分享到:
评论

相关推荐

    java 存储过程使用方法介绍

    ### Java存储过程使用方法介绍 #### 执行概览与背景 在现代数据库系统中,存储过程作为一种封装了复杂逻辑的数据处理单元,在提升应用程序性能、增强数据完整性及简化应用开发方面扮演着重要角色。传统的存储过程...

    调用oracle存储过程的公用方法

    C#调用oracle存储过程的通用方法 C#调用oracle存储过程的通用方法

    Python使用cx_Oracle调用Oracle存储过程的方法示例

    本文实例讲述了Python使用cx_Oracle调用Oracle存储过程的方法。分享给大家供大家参考,具体如下: 这里主要测试在Python中通过cx_Oracle调用PL/SQL。 首先,在数据库端创建简单的存储过程。 create or replace ...

    MySQL存储过程的异常处理方法

    首先,我们注意到在创建存储过程`myProc`时,使用了`delimiter $$`来改变MySQL客户端的语句分隔符,这是为了在存储过程中使用多个分号(;)而不会导致命令提前结束。存储过程的定义如下: ```sql CREATE PROCEDURE ...

    实验八 存储过程的使用(学生).doc

    本实验的目的是让学生掌握创建存储过程的基本方法,并学会使用 Transact-SQL 编写存储过程的方法。实验中,学生需要创建多个存储过程来完成不同的数据库操作,例如检索学生基本信息、检索成绩、插入记录、输出学生...

    SQLServer存储过程中事务的使用方法

    本篇将详细介绍如何在SQL Server存储过程中使用事务。 首先,事务有四个基本特性,即ACID(原子性、一致性、隔离性和持久性): 1. 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成,不会留下...

    实验9 存储过程的创建和使用

    实验9主要围绕存储过程的创建、使用、查看、修改和删除等核心概念展开,这是数据库管理系统中的重要组成部分,尤其在SQL Server中具有广泛的应用。存储过程是一组预先编写的SQL语句,它允许用户像调用函数一样重复...

    dapper的调用各种存储过程的方法

    在 C# 中,你可以使用 Dapper 的 `Execute()` 方法来调用这个存储过程,如下所示: ```csharp public int NoReturn_Add(string className) { using (SqlConnection con = new SqlConnection(constr)) { con.Open...

    Java调用Oracle存储过程的方法

    - **创建CallableStatement**:使用`Connection.prepareCall()`方法,传入存储过程的SQL调用语句。在括号内,`?`表示占位符,`call`后面是存储过程的名称,参数用括号包裹。例如,`"{ ?=call procedure_name(?,?) }...

    pb调用存储过程

    4. **DataWindow对象**:如果你想要在DataWindow中使用存储过程,可以设置DataWindow的SQL源为存储过程,然后在适当的方法(如RowChange, Fetch等)中调用执行。 其次,关于**存储过程的创建**,在提供的描述中,...

    针对sqlserver 2008 存储过程通过With Encryption加密方式的解密

    在下面的存储过程中,我们使用了 With Encryption 加密方式来对存储过程进行加密,并使用解密存储过程来还原加密的存储过程。该存储过程可以对加密的存储过程进行解密,并提供了详细的解密过程。 解密存储过程的...

    Java调用存储过程的2种方法

    使用`setString`方法为存储过程的输入参数赋值,参数索引对应于SQL语句中的位置。 5. **注册输出参数**: ```java proc.registerOutParameter(2, Types.VARCHAR); ``` 使用`registerOutParameter`方法来指定...

    hibernate调用存储过程的方法调用

    - **设置参数**:使用`setXXX`方法(根据参数类型,如`setString`, `setInteger`等)设置输入参数,如果存储过程有返回值,可以使用`registerOutParameter`注册输出参数。 - **执行存储过程**:调用`executeUpdate...

    数据库的存储过程

    创建存储过程通常使用`CREATE PROCEDURE`语句,例如: ```sql CREATE PROCEDURE ProcName (参数1 数据类型, 参数2 数据类型) BEGIN SQL语句; ... END; ``` 调用存储过程使用`CALL`语句,如下所示: ```sql CALL...

    mysql存储过程之返回多个值的方法示例

    本文实例讲述了mysql存储过程之返回多个值的方法。分享给大家供大家参考,具体如下: mysql存储函数只返回一个值。要开发返回多个值的存储过程,需要使用带有INOUT或OUT参数的存储过程。咱们先来看一个orders表它的...

    PLSQL中存储过程的建立,导出,导入,使用

    通过本文的介绍,我们了解到在Oracle数据库中使用PL/SQL创建、导出、导入和使用存储过程的方法。存储过程不仅可以提高SQL语句的执行效率,还能简化复杂的业务逻辑处理。掌握这些技能对于数据库开发者来说是非常重要...

    oracle存储过程学习经典入门

    本文将从 Oracle 存储过程的基础知识开始,逐步深入到 Oracle 存储过程的高级应用,包括 Hibernate 调用 Oracle 存储过程和 Java 调用 Oracle 存储过程的方法。 Oracle 存储过程基础知识 Oracle 存储过程是 Oracle...

    实 验 五 存储过程的建立与使用

    在本节中,我们将详细介绍存储过程和触发器的概念、作用、创建和使用方法。 一、 触发器的概念和作用 触发器是数据库系统中的一个特殊对象,它可以在某个事件发生时自动执行某些操作。触发器可以帮助我们自动化...

    JDBC 调用存储过程方法

    5. **执行存储过程**:使用`CallableStatement`的`execute()`方法执行存储过程。 ```java cs.execute(); ``` 6. **获取结果**:如果存储过程有输出参数或返回结果集,可以使用`getXXX()`方法获取。例如,获取...

Global site tag (gtag.js) - Google Analytics