<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
    <channel>
        <title>CUBRID Triggers</title>
        <link>http://www.cubrid.org/?mid=cubrid_triggers</link>
        <description>CUBRID Triggers</description>
        <language>en</language>
        <pubDate>Fri, 25 Mar 2011 15:16:21 -0800</pubDate>
        <lastBuildDate>Mon, 23 Jan 2012 07:15:17 -0800</lastBuildDate>
        <generator>XpressEngine 1.4.4.1</generator>
                        										        <item>
            <title>CUBRID Triggers

Th...</title>
            <dc:creator>CUBRID</dc:creator>
            <link>http://www.cubrid.org/cubrid_triggers</link>
            <guid isPermaLink="true">http://www.cubrid.org/cubrid_triggers</guid>
                                    <description><![CDATA[<h1>CUBRID Triggers</h1>

<p><span>The scope of this tutorial is to introduce you some of the CUBRID features regarding </span><span>database triggers</span><span>, by showing some examples of creating and using triggers in CUBRID.</span></p>

<h2><span>Overview</span></h2>
<p><span>“</span><span>A </span><span>database trigger</span><span> is procedural code that is automatically executed in response to certain events on a particular table or view in a database.</span><span>” (</span><span><a href="http://en.wikipedia.org/wiki/Database_trigger">http://en.wikipedia.org/wiki/Database_trigger</a></span><span>).</span></p>

<p><span>Database triggers can be very useful for:</span></p>
<ol><li value="1"><span>Control users’ changes in the database</span></li><li><span>Log/Audit users’ changes</span></li><li><span>Implement and enforce business rules</span></li><li><span>Perform various actions automatically</span></li><li><span>Improve performance in client/server environment (triggers run on the server side, before the results is returned to the client). </span></li></ol>
<p><span>Many database systems have nowadays support for triggers, usually using their own specific implementation of SQL-based dialects. CUBRID has an implementation which also uses SQL-based statements to define the triggers actions.</span></p>

<p><span>In CUBRID, we have 2 types of triggers:</span></p>
<ol><li value="1"><span>User triggers</span></li><li><span>Table triggers</span></li></ol>
<table cellpadding="0" cellspacing="0"><tbody><tr><td><p><span>In this tutorial, we will target only </span><span>table triggers</span><span>; user triggers will be subject to another tutorial.</span></p>
</td></tr></tbody></table>
<p><span>Triggers can be defined for combinations of:</span></p>
<ol><li value="3"><span>Events</span><span>: INSERT, UPDATE, DELETE etc.</span></li><li><span>Activation time</span><span>: BEFORE, AFTER, DEFFERED</span></li><li><span>Action type</span><span>: REJECT, STATEMENT etc.</span></li><li><span>Trigger target</span><span> (tables)</span></li></ol>
<table cellpadding="0" cellspacing="0"><tbody><tr><td><p><span>Notes</span><span>: </span></p>
<ol><li value="15"><span>CUBRID does not support VIEWs triggers.</span></li><li><span>CUBRID supports only </span><span>DML</span><span> (</span><span>D</span><span>ata </span><span>M</span><span>anipulation </span><span>L</span><span>anguage) triggers and not DDL triggers (a DDL trigger is trigger associated with events related to data definition, for example: create a table, delete a view etc.)</span></li></ol></td></tr></tbody></table>
<p><span>You can find all the details about triggers in the CUBRID manual: </span><span><a href="/manual/840">http://www.cubrid.org/manual/840</a></span><span>. </span></p>

<p><span>We will assume in this tutorial that the reader is already familiar with the basics of triggers in CUBRID and we will focus only on presenting some concrete examples of using this feature.</span></p>

<h2><span>Setup tutorial data</span></h2>
<p><span>Let’s create the following 2 tables, to implement a very simple “</span><span>virtual library</span><span>”:</span></p>
<ol><li value="7"><span>Authors</span></li><li><span>Books</span></li></ol>
<p><span>The relation between them is </span><span>1:0-n</span><span> - for each book we can have multiple books (or no books at all) in the library.</span></p>

<p><span>Here are the SQL statements to execute:</span></p>


<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>CREATE TABLE "authors"(</span></p>
<p><span>"author_id" integer AUTO_INCREMENT,</span></p>
<p><span>"author_name" character varying(64) NOT NULL,</span></p>
<p><span>"born_date" date NOT NULL,</span></p>
<p><span>"books_count" SMALLINT DEFAULT 0,</span></p>
<p><span>"notes" character varying(1024),</span></p>
<p><span>CONSTRAINT pk_authors_author_id PRIMARY KEY("author_id")</span></p>
<p><span>);</span></p>

<p><span>CREATE TABLE "books"(</span></p>
<p><span>"author_id" integer NOT NULL,</span></p>
<p><span>"book_title" character varying(64) NOT NULL,</span></p>
<p><span>"published_date" date NOT NULL,</span></p>
<p><span>"version" smallint NOT NULL,</span></p>
<p><span>FOREIGN KEY ("author_id") REFERENCES "authors"("author_id") ON DELETE RESTRICT ON UPDATE RESTRICT</span></p>
<p><span>);</span></p>
<p><span>CREATE &nbsp;UNIQUE INDEX ON "books"("author_id","book_title","published_date","version");</span></p>
</div>
</div>

<p><span>And now, let’s insert some startup data in these tables:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>INSERT INTO "authors"("author_name", "born_date", "books_count") VALUES</span></p>
<p><span>('John Miller', TO_DATE('2/9/1960', 'DD/MM/YYYY'), 2),</span></p>
<p><span>('Mike Falkner', TO_DATE('5/8/1961', 'DD/MM/YYYY'), 1),</span></p>
<p><span>('Johnny Dex', TO_DATE('25/6/1970', 'DD/MM/YYYY'), 4),</span></p>
<p><span>('Joel Smith', TO_DATE('23/12/1965', 'DD/MM/YYYY'), 0),</span></p>
<p><span>('Eduardo Diaz', TO_DATE('15/12/1950', 'DD/MM/YYYY'), 1);</span></p>

<p><span>INSERT INTO "books"("author_id","book_title", "published_date", "version") VALUES</span></p>
<p><span>(1, 'La Luna', TO_DATE('2/9/1990', 'DD/MM/YYYY'), 1),</span></p>
<p><span>(1, 'La Luna', TO_DATE('5/8/1999', 'DD/MM/YYYY'), 2),</span></p>
<p><span>(2, 'The sun is down', TO_DATE('25/6/1990', 'DD/MM/YYYY'), 1),</span></p>
<p><span>(3, 'My little book', TO_DATE('23/12/1997', 'DD/MM/YYYY'), 1),</span></p>
<p><span>(3, 'Espana', TO_DATE('15/12/1998', 'DD/MM/YYYY'), 1),</span></p>
<p><span>(3, 'Delta force', TO_DATE('20/12/1999', 'DD/MM/YYYY'), 2),</span></p>
<p><span>(3, 'Remember me', TO_DATE('15/12/1999', 'DD/MM/YYYY'), 1),</span></p>
<p><span>(5, 'You and me', TO_DATE('15/12/2001', 'DD/MM/YYYY'), 1);</span></p>
</div>
</div>

<p><span>Before we proceed to the next sections, we remind you that it is very important, when defining triggers, to understand the relation between </span><span>activation time</span><span> and the </span><span>new</span><span>, </span><span>old</span><span> and </span><span>obj</span><span> qualifiers:</span></p>

<table cellpadding="0" cellspacing="0"><tbody><tr><td>
</td><td><p><span>BEFORE</span></p>
</td><td><p><span>AFTER</span></p>
</td></tr><tr><td><p><span>INSERT</span></p>
</td><td><p><span>new</span></p>
</td><td><p><span>obj</span></p>
</td></tr><tr><td><p><span>UPDATE</span></p>
</td><td><p><span>obj<br />new</span></p>
</td><td><p><span>obj<br />old</span></p>
</td></tr><tr><td><p><span>DELETE</span></p>
</td><td><p><span>obj</span></p>
</td><td>
</td></tr></tbody></table>

<table cellpadding="0" cellspacing="0"><tbody><tr><td><p><span>Note</span><span>: If you are unsure about how are these combinations should be used in the context of triggers, please read the CUBRID manual section dedicated to this topic, before you proceed further with the next parts of this tutorial!</span></p>
</td></tr></tbody></table>
<h2><span>A Data Update trigger</span></h2>
<p><span>Let’s start by creating a trigger which will automatically update the “</span><span>notes</span><span>” column for an author, when a new book is added in our library. We will need to “intercept” the INSERT operations in the “</span><span>books</span><span>” table and, AFTER the INSERT is done, UPDATE the “</span><span>notes</span><span>” column from the “</span><span>authors</span><span>” table.</span></p>

<p><span>This is the code of the trigger which performs this operation:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>CREATE TRIGGER "t_update_notes"</span></p>
<p><span>AFTER INSERT ON "books"</span></p>
<p><span>EXECUTE </span></p>
<p><span>update authors set authors.notes= concat('A new book was released on ', obj.published_date) where authors.author_id=obj.author_id;</span></p>
</div>
</div>

<p><span>If you use the CUBRID Manager client to create the trigger, here below is the definition of the trigger:</span></p>
<p><img height="399" src="/files/attach/images/tutorials/triggers/image00.png" width="601" editor_component="image_link"/></p>

<p><span>If everything goes ok, the user will be notified that the trigger was successfully created.</span></p>

<p><span>Now, let’s add a new book in the library:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>INSERT INTO "books"("author_id","book_title", "published_date", "version") VALUES</span></p>
<p><span>(1, 'New added book', TO_DATE('1/1/1999', 'DD/MM/YYYY'), 1);</span></p>
</div>
</div>

<p><span>The trigger we created will intercept this action and will update the “</span><span>books</span><span>” table, as desired:</span></p>

<p><img height="192" src="/files/attach/images/tutorials/triggers/image01.png" width="546" editor_component="image_link"/></p>

<h2><span>A Data Validation trigger</span></h2>
<p><span>Now, we will create a trigger which will automatically verify that whenever we add a new book in our library, the “</span><span>published_date</span><span>” is a later date than the author “</span><span>born_date</span><span>”. &nbsp;We will need to “intercept” the INSERT operations in the “</span><span>books</span><span>” table and, BEFORE the INSERT is done, compare the values of the date in the both tables. If the validation fails, the trigger should REJECT the INSERT.</span></p>

<p><span>This is the code of the trigger:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>CREATE TRIGGER "t_verify_dates"</span></p>
<p><span>BEFORE INSERT ON "books"</span></p>
<p><span>IF new.published_date&lt;=(select born_date from authors where author_id=new.author_id)</span></p>
<p><span>EXECUTE BEFORE REJECT;</span></p>
</div>
</div>

<p><span>In the CUBRID Manager client, the trigger can be created as shown below:</span></p>

<p><img height="347" src="/files/attach/images/tutorials/triggers/image02.png" width="601" editor_component="image_link"/></p>

<p><span>And now, let’s see the trigger in action:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>INSERT INTO "books"("author_id","book_title", "published_date", "version") VALUES</span></p>
<p><span>(1, 'New invalid book', TO_DATE('1/1/1949', 'DD/MM/YYYY'), 1);</span></p>
</div>
</div>

<p><span>The trigger we created has intercepted this invalid action and denied it:</span></p>

<p><img height="319" src="/files/attach/images/tutorials/triggers/image03.png" width="580" editor_component="image_link"/></p>

<p><span>The trigger canceled the INSERT, because the automatic validation we setup previously has failed.</span></p>

<h2><span>Another Data Update trigger</span></h2>
<p><span>Finally, we will create a trigger which will automatically update the number of the books published by the author, after a book is removed (delete) from the library. &nbsp;We will need to “intercept” the DELETE operations in the “</span><span>books</span><span>” table and, and, AFTER the INSERT is done, UPDATE the “</span><span>books_count</span><span>” column in the “</span><span>authors</span><span>” table.</span></p>

<p><span>Here is the code of this trigger:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>CREATE TRIGGER "t_update_books_count"</span></p>
<p><span>AFTER DELETE ON "books"</span></p>
<p><span>EXECUTE </span></p>
<p><span>update authors set books_count=(select count(*) from books where books.author_id=authors.author_id);</span></p>
</div>
</div>

<p><span>The trigger definition in the CUBRID Manager client is:</span></p>

<p><img height="452" src="/files/attach/images/tutorials/triggers/image04.png" width="601" editor_component="image_link"/></p>

<p><span>Let’s test what happens when we delete a book. Let’s first add a new author, with one book in the library:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>INSERT INTO "authors"("author_id", "author_name", "born_date") VALUES</span></p>
<p><span>(10, 'John Taker', TO_DATE('2/2/1960', 'DD/MM/YYYY'));</span></p>

<p><span>INSERT INTO "books"("author_id","book_title", "published_date", "version") VALUES</span></p>
<p><span>(10, 'My book', TO_DATE('1/1/1999', 'DD/MM/YYYY'), 1);</span></p>

<p><span>UPDATE "authors" SET "books_count"=1 WHERE "author_id"=10;</span></p>
</div>
</div>

<p><span>Now, we will delete the book:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>DELETE FROM "books" WHERE "author_id"=10;</span></p>
</div>
</div>

<p><span>The trigger we created will intercept the “</span><span>books</span><span>” DELETE and will update the “</span><span>authors</span><span>” table (will set “</span><span>books_count</span><span>” value to 0):</span></p>

<p><img height="265" src="/files/attach/images/tutorials/triggers/image06.png" width="602" editor_component="image_link"/></p>


<table cellpadding="0" cellspacing="0"><tbody><tr><td><p><span>Summarizing, as you can see from the examples above, using triggers in CUBRID is not difficult at all…! </span><span></span><span> </span></p>
<p><span>Actually, all you have to do is to know SQL, understand the triggers concept and learn how to use the CUBRID Manager interface, which will significantly simplify the management of the triggers. </span></p>
</td></tr></tbody></table>
<h2><span>Other things to know about CUBRID triggers</span></h2>
<h2><span>Enable/Disable triggers</span></h2>
<p><span>A trigger can always be </span><span>enabled</span><span> or </span><span>disabled</span><span>. You can achieve this by using the ALTER TRIGGER statement:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>ALTER TRIGGER t_update_books_count </span><span>STATUS ACTIVE</span><span>;</span></p>
</div>
</div>

<p><span>Or</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>ALTER TRIGGER t_update_books_count </span><span>STATUS INACTIVE</span><span>;</span></p>
</div>
</div>

<h2><span>Trigger(s) priority</span></h2>
<p><span>Triggers in CUBRID have a “special” attribute, called </span><span>PRIORITY</span><span>. This attribute is used whenever there are multiple triggers that will be executed for the same event, to determine the execution order. </span><span>PRIORITY</span><span> can have any non-negative float value between 00.00 and 9999.99, with 0 being the highest priority. If all the triggers have the same priority, the execution order is random.</span></p>

<p><span>You can always use the ALTER TRGGER statement to change a trigger priority:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>ALTER TRIGGER t_update_books_count </span><span>PRIORITY 0.9</span><span>;</span></p>
</div>
</div>

<table cellpadding="0" cellspacing="0"><tbody><tr><td><p><span>Note</span><span>: STATUS and PRIORITY are the only trigger attributes that can be changed after the trigger was created! If you need to change other attributes of the trigger, you will need to drop the trigger and re-create it. </span></p>
</td></tr></tbody></table>
<h2><span>Trigger execution log</span></h2>
<p><span>You can view the execution log of a trigger by using the </span><span>SET TRIGGER TRACE </span><span>statement:</span></p>

<div class="code">
<div class="code" editor_component="code_highlighter" code_type="sql" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false">
<p><span>SET TRIGGER TRACE ON;</span></p>
</div>
</div>

<p><span>Let’s try this with the trigger </span><span>t_update_notes</span><span>:</span></p>

<p><img height="503" src="/files/attach/images/tutorials/triggers/image05.png" width="589" editor_component="image_link"/></p>

<h2><span>User rights &amp; Triggers</span></h2>
<p><span>In CUBRID, there is no dedicated GRANT statement for triggers (like in MySQL or ORACLE. In particular, in MySQL it is the TRIGGER privilege which enables trigger operations. You must have this privilege for a table to create, drop, or execute triggers for that table). </span></p>

<p><span>In CUBRID the following rules apply:</span></p>
<ol><li value="9"><span>A table trigger is visible to all users who have the SELECT privilege on the trigger target table.</span></li><li><span>To create a table trigger, the user must have an ALTER authorization on the table. </span></li></ol>
<h2><span>Triggers potential (down) side effects</span></h2>
<p><span>Defining (and using) triggers, beside the many useful things they can achieve, can have possible downside effects as well, and the user should know about this, before taking any decisions regarding triggers usage.</span></p>

<p><span>Such potential downside effects can be:</span></p>
<ol><li value="11"><span>Database performance slow-down. Imagine that you have a trigger which runs a slow SQL statement, and the trigger is executed for each UPDATE on a heavy-traffic table/column. Such a trigger will have a significant impact on the database performance.</span></li><li><span>Watch out for recursive triggers! &nbsp;Such triggers might even cause the current session close! Be very careful when defining triggers that modify the same table for which the trigger has been triggered!</span></li><li><span>Triggers should not be used to “hide” database design flaws! Do not use triggers to replace CASCADE constraints, or FOREIGN KEY references, for example.</span></li><li><span>Triggers are usually hard to migrate between different databases.</span></li></ol>

<table cellpadding="0" cellspacing="0"><tbody><tr><td><p><span>Summarizing, triggers are a good tool, but when </span><span>used properly</span><span>!</span></p>
</td></tr></tbody></table>
<h2><span>Links &amp; Resources</span></h2>
<table cellpadding="0" cellspacing="0"><tbody><tr><td><p><span>CUBRID Online Manual</span></p>
</td><td><p><span><a href="/manual/840">http://www.cubrid.org/manual/840</a></span><span> </span></p>
</td></tr><tr><td><p><span>CUBRID Presentation</span></p>
</td><td><p><span><a href="http://www.slideshare.net/GrupAgora/arniacubrid-programatica2010">http://www.slideshare.net/GrupAgora/arniacubrid-programatica2010</a></span><span> </span></p>
</td></tr><tr><td><p><span>CUBRID Wiki Manual</span></p>
</td><td><p><span><a href="/manual/840/en/Guideline%20for%20TRIGGER%20Definition">http://www.cubrid.org/manual/840/en/Guideline%20for%20TRIGGER%20Definition</a></span><span> </span></p>
</td></tr><tr><td><p><span>Using database triggers for alerting and auditing</span></p>
</td><td><p><span><a href="http://www.itwire.com/business-it-news/security/37191-using-database-triggers-for-alerting-and-auditing">http://www.itwire.com/business-it-news/security/37191-using-database-triggers-for-alerting-and-auditing</a></span><span> </span></p>
</td></tr><tr><td><p><span>General information about triggers</span></p>
</td><td><p><span><a href="http://database-programmer.blogspot.com/2008/05/database-triggers-encapsulation-and.html">http://database-programmer.blogspot.com/2008/05/database-triggers-encapsulation-and.html</a></span><span> </span></p>
</td></tr></tbody></table>

<p><span>This concludes the first </span><span>CUBRID Triggers tutorial</span><span>. We will return soon with another tutorial about “user triggers” in CUBRID! Please let us know your feedback and remember to periodically check the CUBRID web site – </span><span><a href="/tutorials">www.cubrid.org/tutorials</a></span><span> - for other tutorials and resources.</span></p>
<p><span>Thank you!</span></p>]]></description>
                        <pubDate>Fri, 25 Mar 2011 14:16:36 -0800</pubDate>
                        <category>triggers</category>
                                </item>
            </channel>
</rss>
