SlideShare uma empresa Scribd logo
1 de 6
Baixar para ler offline
SYSADMIN                                  MySQL 5




Stored procedures, triggers, and views in MySQL 5


THE SEQUEL


We’ll show you how some new features of MySQL 5 will improve

software design and boost application performance.

BY LARKIN CUNNINGHAM




T
        he open source MySQL database                troduced in version 5.0, and some may           will no doubt continue to improve with
        system serves many of the                    be enhanced in version 5.1, which is in         later versions of MySQL.
        world’s leading enterprises, such            beta at this time of writing but may be
                                                                                                     The Ordering Scenario
as Yahoo and Ticketmaster. It also pow-              official by the time you read this article. I
ers a legion of high volume open source              used version 5.1.9-beta when testing the        Throughout this article I will refer to a
websites like Wikipedia. Many enter-                 listings in this article.                       products table, an order_headers table,
prise organizations, however, have tradi-               Three of the most appealing new fea-         an order_lines table, a stock_quantities
tionally avoided MySQL in favor of fea-              tures in MySQL 5.x are stored proce-            table and a customers table for the pur-
ture-rich commercial database systems,               dures, triggers, and views. These fea-          poses of illustration. Listing 1 shows the
such as Oracle and DB2. Starting with                tures are hardly new for the industry. Or-      SQL create table statements that create
MySQL 5.0 [1], the MySQL developers                  acle, for example, first introduced PL/         the tables. When giving examples of
have begun introducing a range of enter-             SQL [2], its implementation of a proce-         stored procedures, triggers, and views, I
prise features that will ultimately make             dural language for SQL, in 1991. Sybase,        will refer to the tables in the listing.
MySQL more competitive with commer-                  PostgreSQL, and DB2 are among the
                                                                                                     Stored Procedures
cial database systems. This article exam-            other database management systems
ines some of the enterprise features that            with a procedural language for SQL.             Before explaining what stored proce-
have been making their way into                      However, triggers, views, and stored pro-       dures are, I should explain that when I
MySQL. Many of these features were in-               cedures are nevertheless a welcome ad-          use the term stored procedure, I am usu-
                                                     dition to MySQL.                                ally referring to both stored procedures
                                                        I should point out that some of these        and stored functions. A stored procedure
THE AUTHOR




             Larkin Cunningham just loves open
             source software. Soon to begin re-      MySQL enterprise features are in early          accepts multiple input and output pa-
             searching towards a PhD, Larkin         stages of development. Many of these            rameters. A stored function also accepts
             currently works with Oracle PL/SQL      features are either incomplete or not per-      multiple input parameters but returns a
             and Java, but finds time to dabble in   forming at optimum levels. Version 5.1          single value to the caller. This restriction
             all things Linux. He can be contacted
                                                     has addressed some of the issues related        allows stored functions to be used
             at larkin.cunningham@gmail.com.
                                                     to these new features, and the situation        within SQL statements, which effectively




52                ISSUE 69 AUGUST 2006                  W W W. L I N U X - M A G A Z I N E . C O M
SYSADMIN
                                                                                               MySQL 5




allows you to extend the capability of        warrant dedicated development re-                  heterogeneous environment with many
SQL.                                          sources.                                           development platforms, then using
   Stored procedures are a powerful tool         Portability is also aided by developing         stored procedures may be a way for you
to have in a developer’s arsenal. They        more of your logic within the database.            to develop your data processing logic
can be of great benefit in terms of perfor-   It would be possible, for example, to de-          once in a central location. After all,
mance and application design. In terms        velop a batch application using C, a web           stored procedures do not care what pro-
of performance, it is possible to reduce a    application using Ruby on Rails, and a             gramming language makes the call.
lot of network traffic by performing more     web service developed using Java, and
                                                                                                 Triggers
data processing within the confines of        have them all using the same set of
the database. By reducing network traf-       stored procedures.                                 Triggers have many uses, including
fic, you can eliminate the latency associ-       The approach of many to developing              house-keeping jobs like auditing and ar-
ated with the application server commu-       applications that use a relational data-           chival. They can have many other uses
nicating with the database server, partic-    base is to either embed all of the SQL             too. One common scenario is where a
ularly when they are on separate servers,     within their code or to embed all of the           trigger is fired (more on trigger timing
as is the case with most large scale ap-      SQL in stored procedures and only call             and firing later) after a row is created,
plications.                                   stored procedures from their code. Many            for example an order line being added to
   With stored procedures you can take a      developers rely on object-relational map-          the order_lines table. A trigger could be
black box approach to application design      pers such as Hibernate [3] (for Java) and          fired after the row is inserted to update
and development. A developer program-         ActiveRecord [4] (for Ruby on Rails),              the stock quantity of the product in the
ming in Java, PHP, Ruby, or any other         where stored procedures are largely irrel-         stock_quantities table.
language with MySQL driver support            evant. Deciding on your approach to                   Where archiving is required, you can
does not need to have extensive knowl-        how to handle data processing in your              have an additional archive table for each
edge of SQL or PL/SQL. On a multi-            applications will depend on factors such           table where you want to store archive in-
member development team, you can              as performance and portability. If perfor-         formation. For example, the products
have stored procedure developers con-         mance is not a concern, then you would             table may have an associated products_
centrating on stored procedure develop-       be in a position to consider an object-re-         archive table with all of the same col-
ment and Java, PHP or Ruby developers         lational mapper that generates your SQL            umns as the products table. To automati-
concentrating on their particular pro-        on the fly. But if you care about perfor-          cally archive, you would create triggers
gramming language. As long as each de-        mance, and you have service level agree-           on the products table to insert a row into
veloper is aware of the inputs and ex-        ments that demand a certain number of              the products_archive table after every
pected outputs, both developers can           transactions per second or a response              update or delete. You would not create a
work in parallel. This can be a way of        time in a certain number of milliseconds,          trigger that is fired after an insert be-
best leveraging the expertise of your de-     you will want to investigate the merits of         cause to query the entire history for a
velopers, if the project is large enough to   using stored procedures. If you operate a          product, you would retrieve the union of

                             Listing 1: The database schema for these examples
 01 CREATE TABLE products (                    14                                                 27        quantity      MEDIUMINT NOT
                                                                                                       NULL DEFAULT 0,
 02        id          MEDIUMINT NOT           15 CREATE TABLE order_headers (
      NULL AUTO_INCREMENT,                                                                        28       PRIMARY KEY (id)
                                               16        id          MEDIUMINT NOT
 03        name          CHAR(40)    NOT            NULL AUTO_INCREMENT,                          29 );
      NULL,                                    17        customer_id       MEDIUMINT NOT          30
 04        cost        DOUBLE(9,2)                  NULL,                                         31 CREATE TABLE     customers (
      UNSIGNED DEFAULT 0.0,                    18        order_date        DATETIME      NOT      32        id          MEDIUMINT
 05       PRIMARY KEY (id)                          NULL,                                              NOT NULL AUTO_INCREMENT,
 06 );                                         19        order_status CHAR(1)                     33        name         VARCHAR(70)
                                                    DEFAULT 'O',
 07                                                                                                    NOT NULL,
                                               20        PRIMARY KEY (id)
 08 CREATE TABLE stock_quantities                                                                 34        address       VARCHAR(200)
    (                                          21 );                                                   NOT NULL,
 09        id          MEDIUMINT NOT           22                                                 35        phone        VARCHAR(20)
      NULL AUTO_INCREMENT,                                                                             NOT NULL,
                                               23 CREATE TABLE order_lines (
 10        product_id     MEDIUMINT NOT                                                           36        email        VARCHAR(40)
                                               24        id          MEDIUMINT NOT
      NULL,                                                                                            NOT NULL,
                                                    NULL AUTO_INCREMENT,
 11        quantity       MEDIUMINT NOT                                                           37       PRIMARY KEY    (id)
                                               25        order_id          MEDIUMINT NOT
      NULL DEFAULT 0,                               NULL,                                         38 );
 12       PRIMARY KEY (id)                     26        product_id        MEDIUMINT NOT
 13 );                                              NULL,




                                                                                                                                      53
                                                                                                        ISSUE 69 AUGUST 2006
                                                 W W W. L I N U X - M A G A Z I N E . C O M
SYSADMIN                            MySQL 5




                                                                          the underlying         will seem rather simplistic. MySQL’s pro-
                                                                          view query will be     cedural language is designed as a means
                                                                          cached and will        for providing input into SQL statements
                                                                          load faster than       and manipulating the results, not as a
                                                                          several versions of    language to compete with the likes of
                                                                          the same query         PHP and Java.
                                                                          running from dif-
                                                                                                 The Structure of a Stored
                                                                          ferent locations.
                                                                                                 Procedure
                                                                          About the              Stored procedures are written in a way
                                                                          MySQL                  that allows them to be created by any
                                                                          Procedural             tool that executes SQL. Some of my list-
                                                                          Language               ings are displayed in MySQL Query
                                                                        MySQL 5 provides         Browser [6], a very useful and free tool
                                                                        a procedural lan-        from MySQL. They are written as SQL
Figure 1: A simple stored procedure in MySQL Query Browser.
                                                                        guage you can use        scripts that basically tell MySQL what
the row in the products table and the as-       to create your stored procedures and             the name of the stored procedure is and
sociated rows in the products_archive           triggers. Instead of going for a proce-          what the contents are. If the stored pro-
table.                                          dural language based on C or Python,             cedure contains any errors, MySQL will
   The approach is similar when auditing        the developers of MySQL created a pro-           inform you when you attempt to create
is required. Instead of the approach of         cedural language compliant with the              the stored procedure.
having an associated archive table where        ANSI SQL:2003 standard [5]. The ANSI                Figure 1 shows a stored procedure that
archiving is concerned, you might have          standard is used by the developers of            accepts an integer value for an amount
a single audit table. For the tables you        other relational database management             to be added to stock. Because the default
wanted to retain an audit trail of activity     systems to varying degrees, so by follow-        delimiter in MySQL is a semi-colon, and
for, you might have triggers fired after        ing the standard, the skillset acquired in       MySQL’s procedural language uses semi-
any add, update, or delete. These trig-         developing stored procedures and trig-           colons to terminate each program state-
gers would insert a row into the audit          gers for MySQL is transferable to other          ment, we need to instruct MySQL to
table containing the nature of the action,      databases such as Oracle, DB2, and Post-         change the delimiter while we attempt to
the table affected, the user performing         greSQL, which have similar procedural            create our procedure. The usual conven-
the action, the time stamp, and any key         language implementations.                        tion is to change the delimiter to double
data or non-key data deemed appropri-              Like the programming languages you            dollar signs with the DELIMITER $$
ate. The approach of using triggers in the      might be familiar with, such as PHP and          statement (Line 1). The next statement
database for auditing and not in your ap-       Java, MySQL’s procedural language has            (Line 3) instructs MySQL to drop (de-
plication code can reduce the coding            the constructs you need to develop use-          stroy) the existing stored procedure of
burden on your developers and encour-           ful code. This includes conditional state-       the same name if it exists. If it does not
age consistency in an environment               ments (IF-THEN-ELSE and CASE-                    exist, then this statement will be ignored
where many applications access the              WHEN) and iterative statements (RE-              and the MySQL parser will move on.
same database. There are many good ap-          PEAT-UNTIL and WHILE-DO).                        Line 4 instructs MySQL to create a new
proaches to auditing that can be em-               The length of this article does not           stored procedure with the name and pa-
ployed within your application code, so         allow for an exhaustive reference of all         rameters provided. All stored procedure
each case will need to be examined in           MySQL procedural language features. In-          logic begins with the BEGIN statement
context.                                        stead, I will ex-
                                                plain how MySQL
About Views                                     stored procedures
A view is a virtual table generated from        and triggers are
a stored query. The stored query is often       structured and
a multi-join query taking data from             provide some sim-
many tables with certain conditions at-         ple examples that
tached. At a simpler, level it might be         offer a flavor of
just a subset of a large table. A trivial ex-   what stored proce-
ample, again using the products table, is       dures, triggers and
to create a view called products_out_of_        views really are. If
stock, which joins the products table           you are a sea-
with the stock_quantities table, where          soned program-
the stock level is zero.                        mer in any mod-
  Views help you cut down on writing            ern language,
SQL code for commonly accessed data             MySQL’s proce-
sets. Views also help efficiency because        dural language          Figure 2: A procedure designed to return a result set to the caller.




54         ISSUE 69 AUGUST 2006                    W W W. L I N U X - M A G A Z I N E . C O M
SYSADMIN
                                                                                            MySQL 5




(Line 7). A number of declaration, se-         Variables must be explicitly declared          worry about and no special function or
quence, conditional, and iterative state-   and assigned a type as well as an op-             method calls to execute your SQL. In-
ments can follow before the stored pro-     tional default value. The types you can           stead, SQL statements can be run on the
cedure logic finishes with an END state-    choose from are the standard SQL data             fly and results read directly into vari-
ment (Line 26). Note how the END state-     types for table columns. All of the data          ables. UPDATE and INSERT statements
ment is followed by our temporary de-       types are scalar, that is, they can only          can read values directly from your vari-
limiter, the double dollars. This is be-    store a single discrete value. This rules         ables and parameters.
cause we have now left the stored proce-    out data types such as arrays, which can             In Figure 1, an UPDATE statement
dure and have returned to normal            be frustrating for developers from lan-           (Line 12) intermingles table names, col-
MySQL SQL parsing. At this point, we        guages like PHP and Java, but there are           umn names, and parameters. In the fol-
switch back to the default semi-colon       workarounds, such as temporary tables             lowing SELECT statement (Line 16), a
delimiter (Line 28).                        using a memory storage engine. Some of            value is selected directly INTO an OUT
                                            the typical data types include CHAR and           parameter. As I said earlier, MySQL’s
Variables, Parameters, and                  VARCHAR (for characters and strings),             procedural language is ultimately a
Data Types                                  DATE, DATETIME, INT (including TI-                means for inputting data to SQL and pro-
In Figure 1, I have declared one variable   NYINT, SMALLINT, MEDIUMINT and                    cessing the results.
max_addition (Line 8) and three param-                                                           In the SELECT statement (Line 16) in
                                            BIGINT), DECIMAL, FLOAT, DOUBLE,
eters stock_addition, product_id and        and others. Large amounts of data can             Figure 1, a value was selected into an
new_stock (Lines 4 to 6). The IN and        be stored using other data types, such as         OUT parameter. Assuming the id column
OUT keywords tell MySQL that the pa-        TEXT (up to 64 kilobytes) and BLOB (bi-           guarantees uniqueness, this is fine. But,
rameter can receive a value in, pass a      nary large object-- in theory you can             what if there were multiple values re-
value back to the caller, or both (by de-   store up to 4 Terabytes in a LONGBLOB).           turned by the SQL statement? You
claring a parameter to be IN OUT). Pa-                                                        should only select into a variable if you
                                            Using SQL in Stored
rameters can be used like normal vari-                                                        are 100% certain of a single value being
                                            Procedures
ables, but only OUT parameters should                                                         returned. This will be the case where the
have their values changed in the proce-     Unlike programming languages such as              discriminator (the clauses after the
dure.                                       PHP and Java, there are no drivers to             WHERE keyword) uses a unique key,

                                 Listing 2: A stored procedure using a cursor
 01 DELIMITER $$                                  ol.quantity) AS total_cost                   44     FETCH   order_summary_cur
                                                                                               45      INTO   v_o_id
                                             21         FROM    products p
 02
                                                                                               46          , v_c_name
                                             22             , customers c
 03 DROP PROCEDURE IF EXISTS show_
    orders_processed $$                                                                        47          , v_c_phone
                                             23             , order_headers oh
 04 CREATE PROCEDURE show_orders_                                                              48          , v_o_date
                                             24             , order_lines ol
    processed ()                                                                               49          , v_o_total;
                                             25         WHERE   c.id = oh.customer_
 05 BEGIN                                         id                                           50
 06                                          26          AND    oh.id = ol.order_id            51     IF not_found THEN
 07 DECLARE v_o_id          MEDIUMINT;       27          AND    ol.product_id = p.id           52        LEAVE order_summary_loop;
 08 DECLARE v_c_name                                                                           53     END IF;
                                             28          AND    oh.order_status =
    VARCHAR(70);                                  'P'                                          54
 09 DECLARE v_c_phone                        29   GROUP BY      oh.id                          55      SELECT CONCAT('Order ID: ',
    VARCHAR(20);
                                                                                                    v_o_id, ', Name: ', v_c_name,
                                             30             , c.name
 10 DECLARE v_o_date        DATETIME;
                                                                                               56                   ', Phone: ', v_
                                             31             , c.phone
 11 DECLARE v_o_total                                                                               c_phone, ', Order Date: ', v_
                                             32             , oh.order_date;
    DOUBLE(9,2);                                                                                    o_date,
                                             33
 12 DECLARE not_found       TINYINT;                                                           57                    ', Order Total:
                                             34 DECLARE CONTINUE HANDLER FOR                        ', v_o_total);
 13
                                             35        NOT FOUND                               58
 14 /* Select all processed orders
                                             36         SET not_found = 1;
    */                                                                                         59 UNTIL not_found
                                             37                                                60 END REPEAT order_summary_loop;
 15 DECLARE order_summary_cur
    CURSOR FOR                               38 SET not_found = 0;                             61
 16     SELECT   oh.id                       39                                                62 CLOSE order_summary_cur;
 17           , c.name                       40 OPEN order_summary_cur;                        63
 18           , c.phone                      41                                                64 END $$
 19           , oh.order_date                42 order_summary_loop:REPEAT                      65
 20           , SUM(p.cost *                 43                                                66 DELIMITER ;




                                                                                                                                  55
                                                                                                     ISSUE 69 AUGUST 2006
                                               W W W. L I N U X - M A G A Z I N E . C O M
SYSADMIN                           MySQL 5




                                                                         cursor’s select         if you were executing your SQL in
                                                                         statement. To           MySQL Query Browser or phpMyAdmin
                                                                         fetch all of the        [7].
                                                                         rows returned by           In the example in Listing 2, you can
                                                                         our select query,       simply abandon all statements between
                                                                         we must use an it-      the BEGIN and END other than the SQL
                                                                         erative statement.      query. Figure 2 shows this rather sleek
                                                                         There are a num-        stored procedure.
                                                                         ber of ways to do          Notice how I have now changed the
                                                                         this, but my pre-       stored procedure to receive a parameter
                                                                         ferred way is the       to select orders of a particular order sta-
                                                                                                 tus. This stored procedure can now po-
                                                                         REPEAT-UNTIL.
                                                                         Though our RE-          tentially return the result set of the query
                                                                         PEAT statement          to a calling program, assuming your call-
                                                                         continues UNTIL         ing programming language can support
                                                                         a specific condi-       retrieving these unbounded result sets.
                                                                         tion is found to be        It is possible to have multiple SQL
                                                                         true (the not_          queries like in Figure 2. This may be use-
                                                                         found variable, in      ful for related sets of data, however, I
Figure 3: Sample PHP call to a stored procedure using mysqli.
                                                                         this case), we          prefer to stay clear of that approach and
such as an id column using an auto_in-          have the option to LEAVE the iteration           have single queries returning single re-
crement, or where you select a function         before the UNTIL condition is reached.           sult sets.
value into the variable, such as with           To do so, we use a label to name the iter-
                                                                                                 Example of a Stored
SUM() or MAX(). I mentioned earlier             ation, order_summary_loop in this exam-
                                                                                                 Procedure Call
that variables were scalar and could only       ple. This allows us to leave the iteration
hold single values. This rules out the          before using any of the fetched vari-            Many of you will have been waiting for
possibility of returning a list of values di-   ables, which, in the case of a fetch be-         me to show some sample code for your
rectly into a variable. This is where the       yond the last row, will result in an error.      preferred programming language. I am
concept of cursors come to the rescue.             The SELECT CONCAT statement may               going to show a sample using PHP. The
                                                look odd, but it is how we display the           approach is similar for other languages
Using Cursors                                   values returned by our cursor’s query.           with MySQL driver support, such as
A cursor is a pointer into a result set re-                                                      Java, Ruby, and Python. My sample code
                                                Returning Result Sets to
turned by a SELECT query. Though used                                                            will call the stored procedure in Figure 2.
                                                Your Calling Code
primarily for SELECT queries that return                                                            For MySQL 5, you must have the ob-
more than one row, you can still use a          If you are a hardened programmer using           ject-oriented mysqli extension [8] loaded
cursor where only one row is returned.          something like PHP, Java, Python or              or compiled into PHP. Figure 3 shows
Even if there are no rows returned, an          Ruby, you may wonder about the pur-              the method calls using mysqli. Line 10
error will not be generated. However, if        pose of a stored procedure like the one          shows the stored procedure being called.
we try to fetch a row either from a null        in Listing 2, since it only displays the re-     You will notice that it does not appear to
result set or if we try and fetch beyond        sult to the console or in MySQL Query            be different from a normal SQL call. The
the last row in the result set, a MySQL         Browser. It’s not much use if you would          while statement on Line 21 loops
error will be thrown.                           like to manipulate the data in the result        through the rows in the result set re-
   Listing 2 shows my preferred way of          set of that cursor.
handling cursors using REPEAT-UNTIL.            It is, however,
We begin the procedure by declaring             possible to return
some standard variables, including one          a result set to your
called not_found. The not_found vari-           calling program
able is used in conjunction with a HAN-         without the cursor
DLER for the NOT FOUND condition.               and handler code.
That is, when a NOT FOUND condition                A plain SQL
is encountered, such as with our cursor         statement can be
going beyond its bounds, the value of           placed in a stored
not_found will be set to 1 or TRUE.             procedure without
   Our cursor order_summary_cur is              declaring a cursor
nothing more than a value assigned to a         and without per-
variable of that name until we actually         forming a SELECT
OPEN it. Once opened, we can begin              into any variables.
fetching from our cursor into variables         It is written just as
in the same order as the columns in our         you would write it       Figure 4: The SQL to create a view.




56        ISSUE 69 AUGUST 2006                     W W W. L I N U X - M A G A Z I N E . C O M
SYSADMIN
                                                                                                 MySQL 5




                                                                          business rules.          MySQL 5 stored procedures, triggers,
                                                                          Rather than hav-         and views. These examples will give you
                                                                          ing to write the         an idea of whether these new features
                                                                          update query             will be useful to your software develop-
                                                                          every time we            ment efforts. Don’t forget that stored
                                                                          order a product,         procedures are all about SQL queries. If
                                                                          we can create a          you were writing inefficient SQL in your
                                                                          trigger that is exe-     program code, you will probably still be
                                                                          cuted every time         writing inefficient SQL queries in your
                                                                          an order line is in-     stored procedures.
                                                                          serted. This allows        The feature set is completely new to
                                                                          us to have con-          MySQL, but those of you who have
                                                                          crete business           worked with stored procedures in other
                                                                          rules enforced in        databases, such as Oracle, DB2, and
                                                                          the database.            PostgreSQL, will probably be more inter-
                                                                             Listing 3 shows       ested in the differences between
Figure 5: Using a view just like a regular query.
                                                                          a trigger that is        MySQL’s implementation and what you
turned, just like a result set returned           fired after an update occurs. The NEW            are used to. MySQL’s procedural lan-
from executing a normal SQL query.                keyword refers to the new row values, as         guage is not yet finished. Subsequent re-
                                                  they are after the update has completed.         leases of MySQL 5 should improve the
Trigger Example                                   The keyword OLD is also available and            feature set considerably and address the
While stored procedures are initiated by          will contain the values of the row as it         areas where MySQL’s implementation
direct calls as their execution is required,      was before an update or delete. For ar-          falls short of its competitors.
triggers, on the other hand, are initiated        chiving, for example, you might want to            The documentation [9] of the new fea-
by events that cause the triggers to be           insert the old row values into an archive        ture set on the MySQL website is ade-
fired. The events in question are inserts,        table for access to historical data. For au-     quate at best, though I am being kind
updates, and deletes.                             diting, you might insert both old and            when I write that. However, books are
   Returning to the example tables in             new values into an audit trail table.            being published by MySQL Press and
Listing 1, we can imagine a scenario                 You can also have a trigger fired before      other publishers that give a more de-
where customer A orders product B. One            an update, insert, or delete occurs. This        tailed overview of MySQL features. ■
approach to recording this in our data-           can be useful where you want to modify
                                                                                                                    INFO
base is to execute a stored procedure             the NEW row values, for example, for
that inserts an order header and an order         validation purposes.                              [1] MySQL 5.0 Community Edition:
line and then updates the stock quantity                                                                http://www.mysql.com/products/data
                                                  A View Example
for the product. However, another ap-                                                                   base/mysql/community_edition.html
proach is to say that any time an order           In Listing 2, we had an attractive looking        [2] Oracle’s PL/SQL Technology Center:
line is created, the corresponding stock          piece of SQL that retrieved processed                 http://www.oracle.com/technology/
quantity for the product ordered will al-         order summaries. For many applications,               tech/pl_sql/index.html
ways be reduced by the quantity or-               this may be a useful result set to have           [3] Hibernate Object Relational Mapper
dered. We can consider this one of our            around and re-use in several places                   for Java and .NET:
                                                  within your application. A view is a                  http://www.hibernate.org/
    Listing 3: A simple after                     mechanism for us to store and re-use              [4] ActiveRecord Object Relational
            update trigger                        such useful queries and access them as                Mapper for Ruby: http://rubyforge.
                                                                                                        org/projects/activerecord/
                                                  if they were just a regular table. The un-
  01 DELIMITER $$
                                                  derlying complexity of the query is hid-          [5] A Publication on ANSI SQL:2003 by
  02 CREATE TRIGGER order_lines_                                                                        Eisenberg et al: http://www.sigmod.
                                                  den from us, and we can simply select
      ins_trg                                                                                           org/sigmod/record/issues/0403/E.
                                                  columns from this virtual table.
                                                                                                        JimAndrew-standard.pdf
  03      AFTER UPDATE ON order_lines                Views cannot accept parameters. If
                                                                                                    [6] MySQL Query Browser:
      FOR EACH ROW                                you need your query to accept parame-
                                                                                                        http://www.mysql.com/products/
                                                  ters, you must create a stored procedure.
  04 BEGIN
                                                                                                        tools/query-browser/
                                                  Figure 4 shows the query from Listing 3
  05      UPDATE stock_quantities
                                                                                                    [7] phpMyAdmin: http://sourceforge.net/
                                                  created in the form of a view. Figure 5
  06         SET quantity = quantity                                                                    projects/phpmyadmin
                                                  shows the results of running a query
      - NEW.quantity                                                                                [8] PHP’s mysqli extension:
                                                  using the view. Notice how it looks like
                                                                                                        http://www.php.net/mysqli
  07       WHERE product_id = NEW.                a query against any regular table.
     product_id;                                                                                    [9] MySQL’s rather sparse online docu-
                                                 Next Steps                                             mentation for stored procedures:
 08 END $$
                                                                                                        http://dev.mysql.com/doc/refman/5.0/
                                                 In this article I have attempted to intro-
 09 DELIMITER ;                                                                                         en/stored-procedures.html
                                                 duce you to some of the capabilities of




                                                                                                                                             57
                                                                                                         ISSUE 69 AUGUST 2006
                                                    W W W. L I N U X - M A G A Z I N E . C O M

Mais conteúdo relacionado

Destaque

How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
 

Destaque (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

MySQL 5 Stored Procedures, Triggers and Views - An Article by Larkin Cunningham

  • 1. SYSADMIN MySQL 5 Stored procedures, triggers, and views in MySQL 5 THE SEQUEL We’ll show you how some new features of MySQL 5 will improve software design and boost application performance. BY LARKIN CUNNINGHAM T he open source MySQL database troduced in version 5.0, and some may will no doubt continue to improve with system serves many of the be enhanced in version 5.1, which is in later versions of MySQL. world’s leading enterprises, such beta at this time of writing but may be The Ordering Scenario as Yahoo and Ticketmaster. It also pow- official by the time you read this article. I ers a legion of high volume open source used version 5.1.9-beta when testing the Throughout this article I will refer to a websites like Wikipedia. Many enter- listings in this article. products table, an order_headers table, prise organizations, however, have tradi- Three of the most appealing new fea- an order_lines table, a stock_quantities tionally avoided MySQL in favor of fea- tures in MySQL 5.x are stored proce- table and a customers table for the pur- ture-rich commercial database systems, dures, triggers, and views. These fea- poses of illustration. Listing 1 shows the such as Oracle and DB2. Starting with tures are hardly new for the industry. Or- SQL create table statements that create MySQL 5.0 [1], the MySQL developers acle, for example, first introduced PL/ the tables. When giving examples of have begun introducing a range of enter- SQL [2], its implementation of a proce- stored procedures, triggers, and views, I prise features that will ultimately make dural language for SQL, in 1991. Sybase, will refer to the tables in the listing. MySQL more competitive with commer- PostgreSQL, and DB2 are among the Stored Procedures cial database systems. This article exam- other database management systems ines some of the enterprise features that with a procedural language for SQL. Before explaining what stored proce- have been making their way into However, triggers, views, and stored pro- dures are, I should explain that when I MySQL. Many of these features were in- cedures are nevertheless a welcome ad- use the term stored procedure, I am usu- dition to MySQL. ally referring to both stored procedures I should point out that some of these and stored functions. A stored procedure THE AUTHOR Larkin Cunningham just loves open source software. Soon to begin re- MySQL enterprise features are in early accepts multiple input and output pa- searching towards a PhD, Larkin stages of development. Many of these rameters. A stored function also accepts currently works with Oracle PL/SQL features are either incomplete or not per- multiple input parameters but returns a and Java, but finds time to dabble in forming at optimum levels. Version 5.1 single value to the caller. This restriction all things Linux. He can be contacted has addressed some of the issues related allows stored functions to be used at larkin.cunningham@gmail.com. to these new features, and the situation within SQL statements, which effectively 52 ISSUE 69 AUGUST 2006 W W W. L I N U X - M A G A Z I N E . C O M
  • 2. SYSADMIN MySQL 5 allows you to extend the capability of warrant dedicated development re- heterogeneous environment with many SQL. sources. development platforms, then using Stored procedures are a powerful tool Portability is also aided by developing stored procedures may be a way for you to have in a developer’s arsenal. They more of your logic within the database. to develop your data processing logic can be of great benefit in terms of perfor- It would be possible, for example, to de- once in a central location. After all, mance and application design. In terms velop a batch application using C, a web stored procedures do not care what pro- of performance, it is possible to reduce a application using Ruby on Rails, and a gramming language makes the call. lot of network traffic by performing more web service developed using Java, and Triggers data processing within the confines of have them all using the same set of the database. By reducing network traf- stored procedures. Triggers have many uses, including fic, you can eliminate the latency associ- The approach of many to developing house-keeping jobs like auditing and ar- ated with the application server commu- applications that use a relational data- chival. They can have many other uses nicating with the database server, partic- base is to either embed all of the SQL too. One common scenario is where a ularly when they are on separate servers, within their code or to embed all of the trigger is fired (more on trigger timing as is the case with most large scale ap- SQL in stored procedures and only call and firing later) after a row is created, plications. stored procedures from their code. Many for example an order line being added to With stored procedures you can take a developers rely on object-relational map- the order_lines table. A trigger could be black box approach to application design pers such as Hibernate [3] (for Java) and fired after the row is inserted to update and development. A developer program- ActiveRecord [4] (for Ruby on Rails), the stock quantity of the product in the ming in Java, PHP, Ruby, or any other where stored procedures are largely irrel- stock_quantities table. language with MySQL driver support evant. Deciding on your approach to Where archiving is required, you can does not need to have extensive knowl- how to handle data processing in your have an additional archive table for each edge of SQL or PL/SQL. On a multi- applications will depend on factors such table where you want to store archive in- member development team, you can as performance and portability. If perfor- formation. For example, the products have stored procedure developers con- mance is not a concern, then you would table may have an associated products_ centrating on stored procedure develop- be in a position to consider an object-re- archive table with all of the same col- ment and Java, PHP or Ruby developers lational mapper that generates your SQL umns as the products table. To automati- concentrating on their particular pro- on the fly. But if you care about perfor- cally archive, you would create triggers gramming language. As long as each de- mance, and you have service level agree- on the products table to insert a row into veloper is aware of the inputs and ex- ments that demand a certain number of the products_archive table after every pected outputs, both developers can transactions per second or a response update or delete. You would not create a work in parallel. This can be a way of time in a certain number of milliseconds, trigger that is fired after an insert be- best leveraging the expertise of your de- you will want to investigate the merits of cause to query the entire history for a velopers, if the project is large enough to using stored procedures. If you operate a product, you would retrieve the union of Listing 1: The database schema for these examples 01 CREATE TABLE products ( 14 27 quantity MEDIUMINT NOT NULL DEFAULT 0, 02 id MEDIUMINT NOT 15 CREATE TABLE order_headers ( NULL AUTO_INCREMENT, 28 PRIMARY KEY (id) 16 id MEDIUMINT NOT 03 name CHAR(40) NOT NULL AUTO_INCREMENT, 29 ); NULL, 17 customer_id MEDIUMINT NOT 30 04 cost DOUBLE(9,2) NULL, 31 CREATE TABLE customers ( UNSIGNED DEFAULT 0.0, 18 order_date DATETIME NOT 32 id MEDIUMINT 05 PRIMARY KEY (id) NULL, NOT NULL AUTO_INCREMENT, 06 ); 19 order_status CHAR(1) 33 name VARCHAR(70) DEFAULT 'O', 07 NOT NULL, 20 PRIMARY KEY (id) 08 CREATE TABLE stock_quantities 34 address VARCHAR(200) ( 21 ); NOT NULL, 09 id MEDIUMINT NOT 22 35 phone VARCHAR(20) NULL AUTO_INCREMENT, NOT NULL, 23 CREATE TABLE order_lines ( 10 product_id MEDIUMINT NOT 36 email VARCHAR(40) 24 id MEDIUMINT NOT NULL, NOT NULL, NULL AUTO_INCREMENT, 11 quantity MEDIUMINT NOT 37 PRIMARY KEY (id) 25 order_id MEDIUMINT NOT NULL DEFAULT 0, NULL, 38 ); 12 PRIMARY KEY (id) 26 product_id MEDIUMINT NOT 13 ); NULL, 53 ISSUE 69 AUGUST 2006 W W W. L I N U X - M A G A Z I N E . C O M
  • 3. SYSADMIN MySQL 5 the underlying will seem rather simplistic. MySQL’s pro- view query will be cedural language is designed as a means cached and will for providing input into SQL statements load faster than and manipulating the results, not as a several versions of language to compete with the likes of the same query PHP and Java. running from dif- The Structure of a Stored ferent locations. Procedure About the Stored procedures are written in a way MySQL that allows them to be created by any Procedural tool that executes SQL. Some of my list- Language ings are displayed in MySQL Query MySQL 5 provides Browser [6], a very useful and free tool a procedural lan- from MySQL. They are written as SQL Figure 1: A simple stored procedure in MySQL Query Browser. guage you can use scripts that basically tell MySQL what the row in the products table and the as- to create your stored procedures and the name of the stored procedure is and sociated rows in the products_archive triggers. Instead of going for a proce- what the contents are. If the stored pro- table. dural language based on C or Python, cedure contains any errors, MySQL will The approach is similar when auditing the developers of MySQL created a pro- inform you when you attempt to create is required. Instead of the approach of cedural language compliant with the the stored procedure. having an associated archive table where ANSI SQL:2003 standard [5]. The ANSI Figure 1 shows a stored procedure that archiving is concerned, you might have standard is used by the developers of accepts an integer value for an amount a single audit table. For the tables you other relational database management to be added to stock. Because the default wanted to retain an audit trail of activity systems to varying degrees, so by follow- delimiter in MySQL is a semi-colon, and for, you might have triggers fired after ing the standard, the skillset acquired in MySQL’s procedural language uses semi- any add, update, or delete. These trig- developing stored procedures and trig- colons to terminate each program state- gers would insert a row into the audit gers for MySQL is transferable to other ment, we need to instruct MySQL to table containing the nature of the action, databases such as Oracle, DB2, and Post- change the delimiter while we attempt to the table affected, the user performing greSQL, which have similar procedural create our procedure. The usual conven- the action, the time stamp, and any key language implementations. tion is to change the delimiter to double data or non-key data deemed appropri- Like the programming languages you dollar signs with the DELIMITER $$ ate. The approach of using triggers in the might be familiar with, such as PHP and statement (Line 1). The next statement database for auditing and not in your ap- Java, MySQL’s procedural language has (Line 3) instructs MySQL to drop (de- plication code can reduce the coding the constructs you need to develop use- stroy) the existing stored procedure of burden on your developers and encour- ful code. This includes conditional state- the same name if it exists. If it does not age consistency in an environment ments (IF-THEN-ELSE and CASE- exist, then this statement will be ignored where many applications access the WHEN) and iterative statements (RE- and the MySQL parser will move on. same database. There are many good ap- PEAT-UNTIL and WHILE-DO). Line 4 instructs MySQL to create a new proaches to auditing that can be em- The length of this article does not stored procedure with the name and pa- ployed within your application code, so allow for an exhaustive reference of all rameters provided. All stored procedure each case will need to be examined in MySQL procedural language features. In- logic begins with the BEGIN statement context. stead, I will ex- plain how MySQL About Views stored procedures A view is a virtual table generated from and triggers are a stored query. The stored query is often structured and a multi-join query taking data from provide some sim- many tables with certain conditions at- ple examples that tached. At a simpler, level it might be offer a flavor of just a subset of a large table. A trivial ex- what stored proce- ample, again using the products table, is dures, triggers and to create a view called products_out_of_ views really are. If stock, which joins the products table you are a sea- with the stock_quantities table, where soned program- the stock level is zero. mer in any mod- Views help you cut down on writing ern language, SQL code for commonly accessed data MySQL’s proce- sets. Views also help efficiency because dural language Figure 2: A procedure designed to return a result set to the caller. 54 ISSUE 69 AUGUST 2006 W W W. L I N U X - M A G A Z I N E . C O M
  • 4. SYSADMIN MySQL 5 (Line 7). A number of declaration, se- Variables must be explicitly declared worry about and no special function or quence, conditional, and iterative state- and assigned a type as well as an op- method calls to execute your SQL. In- ments can follow before the stored pro- tional default value. The types you can stead, SQL statements can be run on the cedure logic finishes with an END state- choose from are the standard SQL data fly and results read directly into vari- ment (Line 26). Note how the END state- types for table columns. All of the data ables. UPDATE and INSERT statements ment is followed by our temporary de- types are scalar, that is, they can only can read values directly from your vari- limiter, the double dollars. This is be- store a single discrete value. This rules ables and parameters. cause we have now left the stored proce- out data types such as arrays, which can In Figure 1, an UPDATE statement dure and have returned to normal be frustrating for developers from lan- (Line 12) intermingles table names, col- MySQL SQL parsing. At this point, we guages like PHP and Java, but there are umn names, and parameters. In the fol- switch back to the default semi-colon workarounds, such as temporary tables lowing SELECT statement (Line 16), a delimiter (Line 28). using a memory storage engine. Some of value is selected directly INTO an OUT the typical data types include CHAR and parameter. As I said earlier, MySQL’s Variables, Parameters, and VARCHAR (for characters and strings), procedural language is ultimately a Data Types DATE, DATETIME, INT (including TI- means for inputting data to SQL and pro- In Figure 1, I have declared one variable NYINT, SMALLINT, MEDIUMINT and cessing the results. max_addition (Line 8) and three param- In the SELECT statement (Line 16) in BIGINT), DECIMAL, FLOAT, DOUBLE, eters stock_addition, product_id and and others. Large amounts of data can Figure 1, a value was selected into an new_stock (Lines 4 to 6). The IN and be stored using other data types, such as OUT parameter. Assuming the id column OUT keywords tell MySQL that the pa- TEXT (up to 64 kilobytes) and BLOB (bi- guarantees uniqueness, this is fine. But, rameter can receive a value in, pass a nary large object-- in theory you can what if there were multiple values re- value back to the caller, or both (by de- store up to 4 Terabytes in a LONGBLOB). turned by the SQL statement? You claring a parameter to be IN OUT). Pa- should only select into a variable if you Using SQL in Stored rameters can be used like normal vari- are 100% certain of a single value being Procedures ables, but only OUT parameters should returned. This will be the case where the have their values changed in the proce- Unlike programming languages such as discriminator (the clauses after the dure. PHP and Java, there are no drivers to WHERE keyword) uses a unique key, Listing 2: A stored procedure using a cursor 01 DELIMITER $$ ol.quantity) AS total_cost 44 FETCH order_summary_cur 45 INTO v_o_id 21 FROM products p 02 46 , v_c_name 22 , customers c 03 DROP PROCEDURE IF EXISTS show_ orders_processed $$ 47 , v_c_phone 23 , order_headers oh 04 CREATE PROCEDURE show_orders_ 48 , v_o_date 24 , order_lines ol processed () 49 , v_o_total; 25 WHERE c.id = oh.customer_ 05 BEGIN id 50 06 26 AND oh.id = ol.order_id 51 IF not_found THEN 07 DECLARE v_o_id MEDIUMINT; 27 AND ol.product_id = p.id 52 LEAVE order_summary_loop; 08 DECLARE v_c_name 53 END IF; 28 AND oh.order_status = VARCHAR(70); 'P' 54 09 DECLARE v_c_phone 29 GROUP BY oh.id 55 SELECT CONCAT('Order ID: ', VARCHAR(20); v_o_id, ', Name: ', v_c_name, 30 , c.name 10 DECLARE v_o_date DATETIME; 56 ', Phone: ', v_ 31 , c.phone 11 DECLARE v_o_total c_phone, ', Order Date: ', v_ 32 , oh.order_date; DOUBLE(9,2); o_date, 33 12 DECLARE not_found TINYINT; 57 ', Order Total: 34 DECLARE CONTINUE HANDLER FOR ', v_o_total); 13 35 NOT FOUND 58 14 /* Select all processed orders 36 SET not_found = 1; */ 59 UNTIL not_found 37 60 END REPEAT order_summary_loop; 15 DECLARE order_summary_cur CURSOR FOR 38 SET not_found = 0; 61 16 SELECT oh.id 39 62 CLOSE order_summary_cur; 17 , c.name 40 OPEN order_summary_cur; 63 18 , c.phone 41 64 END $$ 19 , oh.order_date 42 order_summary_loop:REPEAT 65 20 , SUM(p.cost * 43 66 DELIMITER ; 55 ISSUE 69 AUGUST 2006 W W W. L I N U X - M A G A Z I N E . C O M
  • 5. SYSADMIN MySQL 5 cursor’s select if you were executing your SQL in statement. To MySQL Query Browser or phpMyAdmin fetch all of the [7]. rows returned by In the example in Listing 2, you can our select query, simply abandon all statements between we must use an it- the BEGIN and END other than the SQL erative statement. query. Figure 2 shows this rather sleek There are a num- stored procedure. ber of ways to do Notice how I have now changed the this, but my pre- stored procedure to receive a parameter ferred way is the to select orders of a particular order sta- tus. This stored procedure can now po- REPEAT-UNTIL. Though our RE- tentially return the result set of the query PEAT statement to a calling program, assuming your call- continues UNTIL ing programming language can support a specific condi- retrieving these unbounded result sets. tion is found to be It is possible to have multiple SQL true (the not_ queries like in Figure 2. This may be use- found variable, in ful for related sets of data, however, I Figure 3: Sample PHP call to a stored procedure using mysqli. this case), we prefer to stay clear of that approach and such as an id column using an auto_in- have the option to LEAVE the iteration have single queries returning single re- crement, or where you select a function before the UNTIL condition is reached. sult sets. value into the variable, such as with To do so, we use a label to name the iter- Example of a Stored SUM() or MAX(). I mentioned earlier ation, order_summary_loop in this exam- Procedure Call that variables were scalar and could only ple. This allows us to leave the iteration hold single values. This rules out the before using any of the fetched vari- Many of you will have been waiting for possibility of returning a list of values di- ables, which, in the case of a fetch be- me to show some sample code for your rectly into a variable. This is where the yond the last row, will result in an error. preferred programming language. I am concept of cursors come to the rescue. The SELECT CONCAT statement may going to show a sample using PHP. The look odd, but it is how we display the approach is similar for other languages Using Cursors values returned by our cursor’s query. with MySQL driver support, such as A cursor is a pointer into a result set re- Java, Ruby, and Python. My sample code Returning Result Sets to turned by a SELECT query. Though used will call the stored procedure in Figure 2. Your Calling Code primarily for SELECT queries that return For MySQL 5, you must have the ob- more than one row, you can still use a If you are a hardened programmer using ject-oriented mysqli extension [8] loaded cursor where only one row is returned. something like PHP, Java, Python or or compiled into PHP. Figure 3 shows Even if there are no rows returned, an Ruby, you may wonder about the pur- the method calls using mysqli. Line 10 error will not be generated. However, if pose of a stored procedure like the one shows the stored procedure being called. we try to fetch a row either from a null in Listing 2, since it only displays the re- You will notice that it does not appear to result set or if we try and fetch beyond sult to the console or in MySQL Query be different from a normal SQL call. The the last row in the result set, a MySQL Browser. It’s not much use if you would while statement on Line 21 loops error will be thrown. like to manipulate the data in the result through the rows in the result set re- Listing 2 shows my preferred way of set of that cursor. handling cursors using REPEAT-UNTIL. It is, however, We begin the procedure by declaring possible to return some standard variables, including one a result set to your called not_found. The not_found vari- calling program able is used in conjunction with a HAN- without the cursor DLER for the NOT FOUND condition. and handler code. That is, when a NOT FOUND condition A plain SQL is encountered, such as with our cursor statement can be going beyond its bounds, the value of placed in a stored not_found will be set to 1 or TRUE. procedure without Our cursor order_summary_cur is declaring a cursor nothing more than a value assigned to a and without per- variable of that name until we actually forming a SELECT OPEN it. Once opened, we can begin into any variables. fetching from our cursor into variables It is written just as in the same order as the columns in our you would write it Figure 4: The SQL to create a view. 56 ISSUE 69 AUGUST 2006 W W W. L I N U X - M A G A Z I N E . C O M
  • 6. SYSADMIN MySQL 5 business rules. MySQL 5 stored procedures, triggers, Rather than hav- and views. These examples will give you ing to write the an idea of whether these new features update query will be useful to your software develop- every time we ment efforts. Don’t forget that stored order a product, procedures are all about SQL queries. If we can create a you were writing inefficient SQL in your trigger that is exe- program code, you will probably still be cuted every time writing inefficient SQL queries in your an order line is in- stored procedures. serted. This allows The feature set is completely new to us to have con- MySQL, but those of you who have crete business worked with stored procedures in other rules enforced in databases, such as Oracle, DB2, and the database. PostgreSQL, will probably be more inter- Listing 3 shows ested in the differences between Figure 5: Using a view just like a regular query. a trigger that is MySQL’s implementation and what you turned, just like a result set returned fired after an update occurs. The NEW are used to. MySQL’s procedural lan- from executing a normal SQL query. keyword refers to the new row values, as guage is not yet finished. Subsequent re- they are after the update has completed. leases of MySQL 5 should improve the Trigger Example The keyword OLD is also available and feature set considerably and address the While stored procedures are initiated by will contain the values of the row as it areas where MySQL’s implementation direct calls as their execution is required, was before an update or delete. For ar- falls short of its competitors. triggers, on the other hand, are initiated chiving, for example, you might want to The documentation [9] of the new fea- by events that cause the triggers to be insert the old row values into an archive ture set on the MySQL website is ade- fired. The events in question are inserts, table for access to historical data. For au- quate at best, though I am being kind updates, and deletes. diting, you might insert both old and when I write that. However, books are Returning to the example tables in new values into an audit trail table. being published by MySQL Press and Listing 1, we can imagine a scenario You can also have a trigger fired before other publishers that give a more de- where customer A orders product B. One an update, insert, or delete occurs. This tailed overview of MySQL features. ■ approach to recording this in our data- can be useful where you want to modify INFO base is to execute a stored procedure the NEW row values, for example, for that inserts an order header and an order validation purposes. [1] MySQL 5.0 Community Edition: line and then updates the stock quantity http://www.mysql.com/products/data A View Example for the product. However, another ap- base/mysql/community_edition.html proach is to say that any time an order In Listing 2, we had an attractive looking [2] Oracle’s PL/SQL Technology Center: line is created, the corresponding stock piece of SQL that retrieved processed http://www.oracle.com/technology/ quantity for the product ordered will al- order summaries. For many applications, tech/pl_sql/index.html ways be reduced by the quantity or- this may be a useful result set to have [3] Hibernate Object Relational Mapper dered. We can consider this one of our around and re-use in several places for Java and .NET: within your application. A view is a http://www.hibernate.org/ Listing 3: A simple after mechanism for us to store and re-use [4] ActiveRecord Object Relational update trigger such useful queries and access them as Mapper for Ruby: http://rubyforge. org/projects/activerecord/ if they were just a regular table. The un- 01 DELIMITER $$ derlying complexity of the query is hid- [5] A Publication on ANSI SQL:2003 by 02 CREATE TRIGGER order_lines_ Eisenberg et al: http://www.sigmod. den from us, and we can simply select ins_trg org/sigmod/record/issues/0403/E. columns from this virtual table. JimAndrew-standard.pdf 03 AFTER UPDATE ON order_lines Views cannot accept parameters. If [6] MySQL Query Browser: FOR EACH ROW you need your query to accept parame- http://www.mysql.com/products/ ters, you must create a stored procedure. 04 BEGIN tools/query-browser/ Figure 4 shows the query from Listing 3 05 UPDATE stock_quantities [7] phpMyAdmin: http://sourceforge.net/ created in the form of a view. Figure 5 06 SET quantity = quantity projects/phpmyadmin shows the results of running a query - NEW.quantity [8] PHP’s mysqli extension: using the view. Notice how it looks like http://www.php.net/mysqli 07 WHERE product_id = NEW. a query against any regular table. product_id; [9] MySQL’s rather sparse online docu- Next Steps mentation for stored procedures: 08 END $$ http://dev.mysql.com/doc/refman/5.0/ In this article I have attempted to intro- 09 DELIMITER ; en/stored-procedures.html duce you to some of the capabilities of 57 ISSUE 69 AUGUST 2006 W W W. L I N U X - M A G A Z I N E . C O M