Sunteți pe pagina 1din 12

Goran Udovicic has published an excellent PL/SQL function to

quickly detect if any given year value is a leap year:


create or replace function IS_LEAP_YEAR
(nYear in number) return boolean

is

V_REMAINDER1 NUMBER(5,2);

V_REMAINDER2 NUMBER(5,2);

V_REMAINDER3 NUMBER(5,2);

BEGIN

V_REMAINDER1 := MOD(nYear,4);

V_REMAINDER2 := MOD(nYear,100);

V_REMAINDER3 := MOD(nYear,400);

IF ((V_REMAINDER1 = 0 AND V_REMAINDER2 <> 0 )


OR V_REMAINDER3 = 0) THEN

DBMS_OUTPUT.PUT_LINE(nYear || ' is a leap


year');

return true;

ELSE

DBMS_OUTPUT.PUT_LINE (nYear || ' is not a


leap year');

return false;

END IF;
END;

piece of PLSQL code:

.....

.....

If IS_LEAP_YEAR(2001) then

.....

else

.....

end if;

......

Q1

-1 down I am trying to insert values into an Employees table using the following procedure. I'm
favorite

vote getting errors. Can anyone please explain the problem to me? Error code: Line 29:
SQL statement ignored.

CREATE OR REPLACE PROCEDURE insert_employee(


p_emp_id IN NUMBER,
p_emp_fname IN VARCHAR2,
p_emp_sname IN VARCHAR2,
p_emp_add1 IN VARCHAR2,
p_emp_add2 IN VARCHAR2,
p_emp_town IN VARCHAR2,
p_emp_county IN VARCHAR2,
p_emp_telno IN NUMBER,
p_emp_position IN VARCHAR2,
p_emp_manager IN VARCHAR2

) IS
v_county_id County.county_id%type;
v_position_id Positions.position_id%type;
v_manager_id Facilities.facilty_id%type;
BEGIN

SELECT county_id
INTO v_county_id
FROM County WHERE county_name = p_emp_county;

SELECT position_id
INTO v_position_id
FROM Positions WHERE position_name = p_emp_position;

SELECT facility_manager
INTO v_manager_id
FROM Facilities WHERE facility_name = p_emp_manager;

INSERT INTO Employees (emp_id, emp_fname, emp_sname,


emp_add1, emp_add2, emp_town, emp_county, emp_telno,
emp_position, emp_salary, emp_manager)
VALUES(p_emp_id, p_emp_fname, p_emp_sname, p_emp_add1,
p_emp_add2, p_emp_town, v_county_id, p_emp_telno,
v_position_id, p_emp_salary, v_manager_id);
END;
/
CREATE TRIGGER statement
A trigger defines a set of actions that are executed when a database event occurs on a
specified table. A database event is a delete, insert, or update operation. For example, if
you define a trigger for a delete on a particular table, the trigger's action occurs whenever
someone deletes a row or rows from the table.

Along with constraints, triggers can help enforce data integrity rules with actions such as
cascading deletes or updates. Triggers can also perform a variety of functions such as
issuing alerts, updating other tables, sending e-mail, and other useful actions.

You can define any number of triggers for a single table, including multiple triggers on
the same table for the same event.

You can create a trigger in any schema except one that starts with SYS. The trigger need
not reside in the same schema as the table on which it is defined.

If a qualified trigger name is specified, the schema name cannot begin with SYS.

Syntax

CREATE TRIGGER TriggerName


{ AFTER | NO CASCADE BEFORE }
{ INSERT | DELETE | UPDATE } [ OF column-Name [, column-Name ]* ]
ON table-Name
[ ReferencingClause ]
FOR EACH { ROW | STATEMENT } MODE DB2SQL
Triggered-SQL-statement

Before or after: when triggers fire

Triggers are defined as either Before or After triggers.


 Before triggers fire before the statement's changes are applied and before any
constraints have been applied. Before triggers can be either row or statement
triggers (see Statement versus row triggers).
 After triggers fire after all constraints have been satisfied and after the changes
have been applied to the target table. After triggers can be either row or statement
triggers (see Statement versus row triggers).

Insert, delete, or update: what causes the trigger to fire

A trigger is fired by one of the following database events, depending on how you define it
(see Syntax above):
 INSERT
 UPDATE
 DELETE

You can define any number of triggers for a given event on a given table. For update, you
can specify columns.

Referencing old and new values: the referencing clause

Many triggered-SQL-statements need to refer to data that is currently being changed by


the database event that caused them to fire. The triggered-SQL-statement might need to
refer to the new (post-change or "after") values.

Derby provides you with a number of ways to refer to data that is currently being
changed by the database event that caused the trigger to fire. Changed data can be
referred to in the triggered-SQL-statement using transition variables or transition tables.
The referencing clause allows you to provide a correlation name or alias for these
transition variables by specifying OLD/NEW AS correlation-Name .

For example, if you add the following clause to the trigger definition:
REFERENCING OLD AS DELETEDROW

you can then refer to this correlation name in the triggered-SQL-statement:


DELETE FROM HotelAvailability WHERE hotel_id = DELETEDROW.hotel_id

The OLD and NEW transition variables map to a java.sql.ResultSet with a single row.
Note: Only row triggers (see Statement versus row triggers) can use the transition
variables. INSERT row triggers cannot reference an OLD row. DELETE row triggers
cannot reference a NEW row.

For statement triggers, transition tables serve as a table identifier for the triggered-SQL-
statement or the trigger qualification. The referencing clause allows you to provide a
correlation name or alias for these transition tables by specifying
OLD_TABLE/NEW_TABLE AS correlation-Name

For example:
REFERENCING OLD_TABLE AS DeletedHotels

allows you to use that new identifier (DeletedHotels) in the triggered-SQL-statement:


DELETE FROM HotelAvailability WHERE hotel_id IN
(SELECT hotel_id FROM DeletedHotels)

The old and new transition tables map to a java.sql.ResultSet with cardinality equivalent
to the number of rows affected by the triggering event.
Note: Only statement triggers (see Statement versus row triggers) can use the transition
tables. INSERT statement triggers cannot reference an OLD table. DELETE statement
triggers cannot reference a NEW table.
The referencing clause can designate only one new correlation or identifier and only one
old correlation or identifier. Row triggers cannot designate an identifier for a transition
table and statement triggers cannot designate a correlation for transition variables.

Statement versus row triggers

You must specify whether a trigger is a statement trigger or a row trigger:


 statement triggers

A statement trigger fires once per triggering event and regardless of whether any
rows are modified by the insert, update, or delete event.

 row triggers

A row trigger fires once for each row affected by the triggering event. If no rows
are affected, the trigger does not fire.

Note: An update that sets a column value to the value that it originally contained (for
example, UPDATE T SET C = C) causes a row trigger to fire, even though the value of
the column is the same as it was prior to the triggering event.

Triggered-SQL-statement

The action defined by the trigger is called the triggered-SQL-statement (in Syntax above,
see the last line). It has the following limitations:
 It must not contain any dynamic parameters (?).
 It must not create, alter, or drop the table upon which the trigger is defined.
 It must not add an index to or remove an index from the table on which the trigger
is defined.
 It must not add a trigger to or drop a trigger from the table upon which the trigger
is defined.
 It must not commit or roll back the current transaction or change the isolation
level.
 It must not execute a CALL statement.
 Before triggers cannot have INSERT, UPDATE or DELETE statements as their
action.

The triggered-SQL-statement can reference database objects other than the table upon
which the trigger is declared. If any of these database objects is dropped, the trigger is
invalidated. If the trigger cannot be successfully recompiled upon the next execution, the
invocation throws an exception and the statement that caused it to fire will be rolled back.

For more information on triggered-SQL-statements, see the Derby Developer's Guide.

Order of execution

When a database event occurs that fires a trigger, Derby performs actions in this order:
 It fires No Cascade Before triggers.
 It performs constraint checking (primary key, unique key, foreign key, check).
 It performs the insert, update, or delete.
 It fires After triggers.

When multiple triggers are defined for the same database event for the same table for the
same trigger time (before or after), triggers are fired in the order in which they were
created.
-- Statements and triggers:

CREATE TRIGGER t1 NO CASCADE BEFORE UPDATE ON x


FOR EACH ROW MODE DB2SQL
values app.notifyEmail('Jerry', 'Table x is about to be
updated');

CREATE TRIGGER FLIGHTSDELETE


AFTER DELETE ON FLIGHTS
REFERENCING OLD_TABLE AS DELETEDFLIGHTS
FOR EACH STATEMENT MODE DB2SQL
DELETE FROM FLIGHTAVAILABILITY WHERE FLIGHT_ID IN
(SELECT FLIGHT_ID FROM DELETEDFLIGHTS);

CREATE TRIGGER FLIGHTSDELETE3


AFTER DELETE ON FLIGHTS
REFERENCING OLD AS OLD
FOR EACH ROW MODE DB2SQL
DELETE FROM FLIGHTAVAILABILITY WHERE FLIGHT_ID = OLD.FLIGHT_ID;

Note: You can find more examples in the Derby Developer's Guide.

Trigger recursion

The maximum trigger recursion depth is 16.

Related information

Special system functions that return information about the current time or current user are
evaluated when the trigger fires, not when it is created. Such functions include:
 CURRENT_DATE
 CURRENT_TIME
 CURRENT_TIMESTAMP
 CURRENT_USER
 SESSION_USER
 USER

 ReferencingClause

Parent topic: CREATE statements


Related reference
CREATE FUNCTION statement
CREATE INDEX statement
CREATE PROCEDURE statement
CREATE SCHEMA statement
CREATE SYNONYM statement
CREATE TABLE statement
CREATE VIEW statement

---------------------------
Windows Internet Explorer
---------------------------
Internet Explorer cannot open the Internet site
http://technobytz.com/sql-trigger-example-in-postgresql.html.

Operation aborted

---------------------------
OK

What is an SQL Trigger ?

Before going into the PostgreSQL trigger example, let’s first try to define what an sql
trigger is.

A trigger is associated with a table or view and is fired whenever an event occur. The
‘events’ are INSERT, DELETE, UPDATE or TRUNCATE.

Trigger will eventually call a function which is written in PL/SQL or PL/pgSQL or any
other compatible language.
Trigger can be set to fire BEFORE an event occur or AFTER an event occur or even we
can bypass the event by using the INSTEAD OF command.

If we configured a trigger to fire BEFORE an INSERT or UPDATE, we will have the


additional benefit of modifying the new data to be inserted or updated, and even skipping
the operation itself!

There are both Row level trigger and Statement Level trigger available. A row level
trigger is fired for each affected row. A statement level trigger is fired only once for a
statement. To make it even simpler, lets consider the statement: UPDATE
account_current SET balance = balance + 100 WHERE balance > 100000; Executing this
statement may affect more than one rows. If a row level trigger is defined for the table,
the trigger will be fired for each updated rows. But if it was a statement level trigger,it
would have fired only once.

That is pretty much about the idea behind sql triggers. If you still need more theory, read
here.

The use case

The sql trigger example given here assumes you have PostgreSQL installed in your
system along with PL/pgSQL(which comes default in most distributions). We will be
creating three types of triggers which are supported by PostgreSQL :- sql update trigger,
sql insert trigger and sql delete trigger.

Ok, let’s start with the use case. What we have in our DB is three tables:
account_current, account_savings and log.
CREATE TABLE account_current
(
customer_id integer NOT NULL,
customer_name character varying,
balance numeric,
CONSTRAINT account_current_pkey PRIMARY KEY (customer_id)
)

CREATE TABLE account_savings


(
customer_id integer NOT NULL,
customer_name character varying,
balance numeric,
CONSTRAINT account_savings_pkey PRIMARY KEY (customer_id)
)

CREATE TABLE log


(
log_id serial NOT NULL,
log_time time with time zone,
description character varying,
CONSTRAINT log_pkey PRIMARY KEY (log_id)
)

The first two tables stores the customer name along with a unique id and their current or
savings account balance respectively. You might be expecting one users table with user
details alone, but for the sake of simplicity we ignore normalization here. The third table
log is an auditing table which store each action or transaction with its time and a
description.

The four kinds of actions possible here are:

1. A customer opens a savings and/or current account. This is done by an INSERT


query.
2. A customer withdraw/ deposit money from/ to his/her account. Which is in effect
an UPDATE query.
3. A customer sends or receive money to/from other customer. Which is in fact the
combination of two UPDATE queries.
4. A customer closes his account, which is done by a DELETE command.

We need to keep track of all these actions. For that we are adding one log entry for each
of the actions 1, 2 and 4. We wont be adding any separate entry for 3, since it can be
divided into two update entries.

So if Bob starts a savings account, deposit a 2000$ in it and then sends 300$ to Tom and
finally decide to close the account and move to another bank, we will have the following
entries in log table:

Log table – SQL TRIGGER

To populate the log table we are gonna use PostgreSQL triggers. We have to create two
triggers, one for ‘savings table’ and one for ‘current table’. These two sql triggers will
then hook in to one PL/pgSQL function. You might have noticed-we need only one single
function. That means one function can be associated with n number of triggers!

So let’s start by writing the function first. We will create the trigger later on.

1. Writing an SQL Trigger Procedure(Function)

Before writing the procedure, let’s be familiar with some special variables created
automatically by postgres to serve us.

NEW : Variable holding the new row to be inserted for INSERT/UPDATE command in
row-level triggers. Its of data type RECORD.

OLD: Variable holding the old row for INSERT/UPDATE operation in row-level
triggers. Data type is RECORD

TG_OP: Contains one of the strings of INSERT, UPDATE, DELETE, or TRUNCATE,


tells for which operation the trigger is called.

TG_TABLE_NAME: The name of the table for which the trigger is fired.

TG_WHEN: A string of BEFORE, AFTER, or INSTEAD OF, depending on the trigger’s


definition

There are more variables available. For a full list of variables, refer PostgreSQL
Documentation.

An SQL trigger procedure must return either NULL or a record or row having the same
structure of the table for which the it is fired. If a row-level trigger fired BEFORE returns
a NULL, the rest of the operations including any other triggers and the actual
INSERT/UPDATE/DELETE operation would be cancelled.

In the function definition, it must be written as it returns TRIGGER, no matter whether it


return NULL or a RECORD/ROW.

So, in our trigger procedure we will be using some of these variables. The first thing we
need to figure out in our trigger procedure is to determine for which table the trigger is
fired for. So we begin with our procedure like this:
CREATE OR REPLACE FUNCTION add_log_trigg_function()
RETURNS trigger AS
$BODY$
DECLARE
account_type varchar;
BEGIN
IF (TG_TABLE_NAME = 'account_current') THEN
account_type := 'Current';
RAISE NOTICE 'TRIGER called on %', TG_TABLE_NAME;

ELSIF (TG_TABLE_NAME = 'account_savings') THEN


account_type := 'Savings';
RAISE NOTICE 'TRIGER called on %', TG_TABLE_NAME;

END IF;

RETURN null;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION add_log_trigg_function()
OWNER TO postgres;

Now we got the account type of the customer by checking the TG_TABLE_NAME
variable. Next we are gonna handle the INSERT operation.
CREATE OR REPLACE FUNCTION add_log_trigg_function()
RETURNS trigger AS
$BODY$
DECLARE
account_type varchar;
BEGIN
IF (TG_TABLE_NAME = 'account_current') THEN
account_type := 'Current';
RAISE NOTICE 'TRIGER called on %', TG_TABLE_NAME;

S-ar putea să vă placă și