NAME SQL::Abstract - Generate SQL from Perl data structures SYNOPSIS use SQL::Abstract; my $sql = SQL::Abstract->new(case => 'lower', cmp => 'like'); my($stmt, @bind) = $sql->select($table, \@fields, \%where, \@order); my($stmt, @bind) = $sql->insert($table, \@values || \%fieldvals); my($stmt, @bind) = $sql->update($table, \%fieldvals, \%where); my($stmt, @bind) = $sql->delete($table, \%where); # Just generate the WHERE clause my($stmt, @bind) = $sql->where(\%where); DESCRIPTION This module was inspired by the excellent DBIx::Abstract. However, in using the module I found that what I wanted to do was generate SQL, but still retain complete control over my statement handles and use the DBI interface. So, I set out to create an abstract SQL generation module. This module is based largely on DBIx::Abstract. However, there are several important differences, especially when it comes to WHERE clauses. I have modified the concepts used to make the SQL easier to generate from Perl data structures and, IMO, more intuitive. In particular, if you want to see if a field is within a set of values, you can use an arrayref. Let's look at a specific example: my $where = { worker => ['nwiger', 'bob', 'jim'], status => { '!=', 'completed' } }; my($stmt, @bind) = $sql->select('requests', '*', $where); This would give you something like this: $stmt = "SELECT * FROM requests WHERE ( ( worker = ? OR worker = ? OR worker = ? ) AND ( status != ? ) )"; @bind = ('nwiger', 'bob', 'jim', 'completed'); Which you could then use in DBI code: my $sth = $dbh->prepare($stmt); $sth->execute(@bind); Easy, eh? FUNCTIONS The functions are simple. There's one for each major SQL operation, and a constructor you use first. new(case => 'lower', cmp => 'like') The "new()" function takes a list of options and values, and returns a new "SQL::Abstract" object which can then be used to generate SQL through the methods below. The options accepted are: case If set to 'lower', then SQL will be generated in all lowercase. By default SQL is generated in "textbook" case meaning something like: SELECT a_field FROM a_table WHERE some_field LIKE '%someval%' cmp This determines what the default comparison operator is. By default it is "=", meaning that a hash like this: %where = (name => 'nwiger', email => 'nate@wiger.org'); Will generate SQL like this: ... WHERE name = 'nwiger' AND email = 'nate@wiger.org' However, you may want loose comparisons by default, so if you set "cmp" to "like" you would get SQL such as: ... WHERE name like 'nwiger' AND email like 'nate@wiger.org' You can also override the comparion on an individual basis - see the huge section on "WHERE CLAUSES" at the bottom. insert($table, \@values || \%fieldvals) This is the simplest function. You simply give it a table name and either an arrayref of values or hashref of field/value pairs. It returns an SQL INSERT statement and a list of bind values. update($table, \%fieldvals, \%where) This takes a table, hashref of field/value pairs, and an optional hashref where clause. It returns an SQL UPDATE function and a list of bind values. select($table, \@fields, \%where, \@order) This takes a table, arrayref of fields (or '*'), optional hashref where clause, and optional arrayref order by, and returns the corresponding SQL SELECT statement and list of bind values. delete($table, \%where) This takes a table name and optional hashref where clause. It returns an SQL DELETE statement and list of bind values. where(\%where) This is used just to generate the WHERE clause. For example, if you have an arbitrary data structure and know what the rest of your SQL is going to look like but want an easy way to produce a WHERE clause, use this. It returns an SQL WHERE clause and list of bind values. WHERE CLAUSES This module uses a variation on the idea from DBIx::Abstract. It is NOT, repeat *not* 100% compatible. The easiest way is to show lots of examples. After each %where hash shown, it is assumed you ran: my($stmt, @bind) = $sql->where(\%where); However, note that the %where hash can be used directly in any of the other functions as well, as described above. So, let's get started. To begin, a simple hash: my %where = ( user => 'nwiger', status => 'completed' ); Is converted to SQL "key = val" statements: $stmt = "WHERE user = ? AND status = ?"; @bind = ('nwiger', 'completed'); One common thing I end up doing is having a list of values that a field can be in. To do this, simply specify a list inside of an arrayref: my %where = ( user => 'nwiger', status => ['assigned', 'in-progress', 'pending']; ); This simple code will create the following: $stmt = "WHERE user = ? AND ( status = ? OR status = ? OR status = ? )"; @bind = ('nwiger', 'assigned', 'in-progress', 'pending'); Note this is not compatible with "DBIx::Abstract" If you want to specify a different type of operator for your comparison, you can use a hashref: my %where = ( user => 'nwiger', status => { '!=', 'completed' } ); Which would generate: $stmt = "WHERE user = ? AND status != ?"; @bind = ('nwiger', 'completed'); So far, we've seen how multiple conditions are joined with "AND". However, we can change this by putting the different conditions we want in hashes and then putting those hashes in an array. For example: my @where = ( { user => 'nwiger', status => ['pending', 'dispatched'], }, { user => 'robot', status => 'unassigned', } ); This data structure would create the following: $stmt = "WHERE ( user = ? AND ( status = ? OR status = ? ) ) OR ( user = ? AND status = ? ) )"; @bind = ('nwiger', 'pending', 'dispatched', 'robot', 'unassigned'); If you want to include plain SQL verbatim, you must specify it as a scalar reference, namely: my $inn = 'is not null'; my %where = ( pri => { '>', 3 }, name => \$inn ); This would create: $stmt = "WHERE pri > ? AND name is not null"; @bind = (3); Note you only get one bind parameter back. SEE ALSO DBIx::Abstract, SQL::Statement VERSION $Id: Abstract.pm,v 1.9 2002/08/29 18:04:35 nwiger Exp $ AUTHOR Copyright (c) 2001 Nathan Wiger . All Rights Reserved. This module is free software; you may copy this under the terms of the GNU General Public License, or the Artistic License, copies of which should have accompanied your Perl kit.