PhpRiot
Download This Article
Download this article in PDF format with all listings and files.

Price: $5.00 AUD
(Approx. $4.10 USD)

More information
Related Books
SQL Pocket Guide (Pocket References)

SQL Pocket Guide (Pocket References)

SQL is the language of databases. It's used to create and maintain database objects, place data...

PostgreSQL (2nd Edition) (Developer's Library)

PostgreSQL (2nd Edition) (Developer's Library)

The second edition of the best-selling PostgreSQL has been updated to completely cover new...
Browse Articles
Ajax (4), APC (1), CAPTCHA (1), CSS (3), Debugging (1), File Upload (1), Google (3), Google Maps (2), JavaScript (12), JSON (2), MVC (1), MySQL (7), onbeforeunload (1), OOP (1), PHP (28), PhpDoc (1), PostgreSQL (6), Prototype (11), Reflection (1), RFC 1867 (1), Robots (1), Scriptaculous (1), SEO (1), Sessions (1), SimpleXML (1), Smarty (5), SOAP (1), SPL (1), Templates (2), W3C (1), XHTML (1), Zend Framework (1), Zend_Search_Lucene (1)

PhpRiot Newsletter
Your Email Address:

Understanding Transactions And Locking In PostgreSQL

Automation With PLPGSQL

Now we need to actually do something useful with this information.

We will create a plpgsql function block that will determine if the user has a 5 dollar positive balance, insert into some other table (to simulate the purchase of some item), and then post a 5 dollar debit to the users account.

For those not familiar with plpgsql it’s extremely easy to use. Just be sure to use the createlang binary in the PostgreSQL distribution to add plpgsql support to your database. (/usr/local/pgsql/bin/createlang plpgsql yourdbname) as the postgres user.

Listing 3 listing-3.sql
CREATE OR REPLACE FUNCTION buysomething(varchar(255),TEXT) RETURNS integer AS $$
    DECLARE
        account_balance NUMERIC(22,9);
    BEGIN
        SELECT (SUM(COALESCE(credit,0)) - SUM(COALESCE(debit,0)) INTO account_balance
            FROM accounting
            WHERE account_id = $1;
 
        IF account_balance >= 5 THEN
            INSERT INTO purchases (SomeTextCol) VALUES ($2);
            INSERT INTO accounting (account_id, debit) VALUES ($1, 5);
        ELSE
            RAISE EXCEPTIONThe account % does not have enough free balance’, $1;
        END IF;
    END;
$$ Language plpgsql;

Note: there are better ways to write this function, but this method demonstrates the most functionality.

So this function looks like it would do the job, but there’s a trick. What happens if this function is called twice at the same identical time?

Well what happens is between the balance selection and the insert into accounting, another debit could have been committed to the accounting table. There is no guarantee that after the select is run the balance will not change until the end of the function.

In This Article


Tagged in