PostgreSQL & PHP Tutorials - Database Design Issues - Triggers & Functions

PostgreSQL »  Database Design Issues
Random Stuff »  Database Design Issues
Forum Project »  Database Design Issues

Posted By Chris Smith Posted on 20 Apr 2006, 08:54 AM
Viewing page 4 of 5
« | Back | Next | »

The problem now becomes keeping this information up to date.

Thankfully, postgresql supports triggers and functions.

First we need to install the language which allows us to create functions. From the command line:

$ createlang plpgsql database_name

There are a few languages you can use to write the functions in (for example, Perl, PHP, Ruby, C, TCL, Python), we'll come back to those perhaps in later tutorials. See documentation for more information.

The plpgsql language is similar to the oracle PL/SQL language so it makes converting from oracle to postgresql quite easy.


Back inside psql, we can create the function.


CREATE OR REPLACE FUNCTION increment_forum_postcount() RETURNS TRIGGER as '
    BEGIN
        UPDATE myforum_forums SET postcount=postcount+1 WHERE forumid=new.forumid;

        UPDATE myforum_threads SET postcount=postcount+1 WHERE threadid=new.threadid;
        RETURN new;
    END
' language'plpgsql';


Using the 'new.' syntax, we can get the forumid & threadid we're inserting in to when we run an insert query into that table. This particular function will update the forum and thread tables with the new postcount. Nice and easy!

Now we have to get postgresql to execute that function every time we insert, which is where a plpgsql trigger comes in handy:

CREATE TRIGGER insert_forum_post AFTER INSERT ON myforum_posts FOR EACH ROW EXECUTE PROCEDURE increment_forum_postcount();

So, after every row that's inserted into the myforum_posts table, it will execute the function called increment_forum_postcount() - the database will update the other tables for us!
Viewing page 4 of 5
« | Back | Next | »



Avg Rating: 4
Vote Count: 10


              

  New Reply


You've missed an important point. Consider the following:

---
create table forums (
forumid int primary key
);

create table threads (
threadid int primary key,
forumid int references forums
);

create table posts (
postid int primary key,
threadid int
);

insert into forums values(1);
insert into forums values(2);

insert into threads values(1, 1);
insert into threads values(2, 1);

insert into posts values(1, 1);
insert into posts values(2, 1);

insert into posts values(3, 2);
insert into posts values(4, 2);
insert into posts values(5, 2);
insert into posts values(6, 2);

select f.forumid, count(distinct t.threadid), count(distinct p.postid) from forums f
left outer join threads t on(f.forumid = t.forumid) left outer join
posts p on(t.threadid = p.threadid) group by 1;

---

This is a correct design and simpler query. However, this is not the best way to do what you're trying to achieve in PostgreSQL. Instead, you should use rules and triggers to maintain a forum, thread and post count in a count cache table. This will give you O(n) count performance and can be done without modifying your application code. Just create insert and delete triggers/rules to manage the counts when posts/threads are added and removed.
Gavin Sherry 23 Apr 2006 Reply
`-- I thought that's what I was trying to demonstrate.. or do you mean having a separate count table instead of including it in the forum/thread table ? Chris Smith 24 Apr 2006 Reply


Want to post a comment? Fill in the details below.

Your Name  : 
Your Email  : 
Your Website  : 
Spam Check! Please answer this question  : 7 + 3 =
Comment