Recordset(3pm) | User Contributed Perl Documentation | Recordset(3pm) |
DBIx::Recordset - Perl extension for DBI recordsets
use DBIx::Recordset; # Setup a new object and select some recods... *set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:Oracle:....', '!Table' => 'users', '$where' => 'name = ? and age > ?', '$values' => ['richter', 25] }) ; # Get the values of field foo ... print "First Records value of foo is $set[0]{foo}\n" ; print "Second Records value of foo is $set[1]{foo}\n" ; # Get the value of the field age of the current record ... print "Age is $set{age}\n" ; # Do another select with the already created object... $set -> Search ({name => 'bar'}) ; # Show the result... print "All users with name bar:\n" ; while ($rec = $set -> Next) { print $rec -> {age} ; } # Setup another object and insert a new record *set2 = DBIx::Recordset -> Insert ({'!DataSource' => 'dbi:Oracle:....', '!Table' => 'users', 'name' => 'foo', 'age' => 25 }) ; # Update this record (change age from 25 to 99)... $set -> Update ({age => 99}, {name => 'foo'}) ;
DBIx::Recordset is a perl module for abstraction and simplification of database access.
The goal is to make standard database access (select/insert/update/delete) easier to handle and independend of the underlying DBMS. Special attention is made on web applications to make it possible to handle the state-less access and to process the posted data of formfields, but DBIx::Recordset is not limited to web applications.
DBIx::Recordset uses the DBI API to access the database, so it should work with every database for which a DBD driver is available (see also DBIx::Compat).
Most public functions take a hash reference as parameter, which makes it simple to supply various different arguments to the same function. The parameter hash can also be taken from a hash containing posted formfields like those available with CGI.pm, mod_perl, HTML::Embperl and others.
Before using a recordset it is necessary to setup an object. Of course the setup step can be made with the same function call as the first database access, but it can also be handled separately.
Most functions which set up an object return a typglob. A typglob in Perl is an object which holds pointers to all datatypes with the same name. Therefore a typglob must always have a name and can't be declared with my. You can only use it as global variable or declare it with local. The trick for using a typglob is that setup functions can return a reference to an object, an array and a hash at the same time.
The object is used to access the object's methods, the array is used to access the records currently selected in the recordset and the hash is used to access the current record.
If you don't like the idea of using typglobs you can also set up the object, array and hash separately, or just set the ones you need.
Since most methods take a hash reference as argument, here is a description of the valid arguments first.
All parameters starting with an '!' are only recognized at setup time. If you specify them in later function calls they will be ignored. You can also preset these parameters with the TableAttr method of DBIx::Database. This allows you to presetup most parameters for the whole database and they will be use every time you create a new DBIx::Recordset object, without specifying it every time.
NOTE 1: Fieldnames specified with !Fields can't be overridden. If you plan to use other fields with this object later, use $Fields instead.
NOTE 2: The keys for the returned hash normally don't have a table part. Only the fieldname part forms the key. (See !LongNames for an exception.)
NOTE 3: Because the query result is returned in a hash, there can only be one out of multiple fields with the same name fetched at once. If you specify multiple fields with the same name, only one is returned from a query. Which one this actually is depends on the DBD driver. (See !LongNames for an exception.)
NOTE 4: Some databases (e.g. mSQL) require you to always qualify a fieldname with a tablename if more than one table is accessed in one query.
NOTE 1: Fieldnames specified with !Order can't be overridden. If you plan to use other fields with this object later, use $order instead.
Example '!Table' => 'tab1, tab2', '!TabRelation' => 'tab1.id=tab2.id', 'name' => 'foo' This will generate the following SQL statement: SELECT * FROM tab1, tab2 WHERE name = 'foo' and tab1.id=tab2.id ;
Example '!Table' => 'tab1, tab2', '!TabJoin' => 'tab1 LEFT JOIN tab2 ON (tab1.id=tab2.id)', 'name' => 'foo' This will generate the following SQL statement: SELECT * FROM tab1 LEFT JOIN tab2 ON (tab1.id=tab2.id) WHERE name = 'foo' ;
Example: '!SeqClass' => 'DBIx::Recordset::FileSeq, /tmp/seq'
NOTE: The !WriteMode only works for the DBIx::Recordset methods. If you disable !WriteMode, it is still possible to use do to send normal SQL statements to the database engine to write/delete any data.
!WriteMode consists of some flags, which may be added together:
Default is wmINSERT + wmUPDATE + wmDELETE
NOTE: The default for versions before 0.18 was 2.
Example: '!Filter' => { DBI::SQL_DATE => [ sub { shift =~ /(\d\d)\.(\d\d)\.(\d\d)/ ; "19$3$2$1"}, sub { shift =~ /\d\d(\d\d)(\d\d)(\d\d)/ ; "$3.$2.$1"} ], 'datefield' => [ sub { shift =~ /(\d\d)\.(\d\d)\.(\d\d)/ ; "19$3$2$1"}, sub { shift =~ /\d\d(\d\d)(\d\d)(\d\d)/ ; "$3.$2.$1"} ], }
Both filters convert a date in the format dd.mm.yy to the database format 19yymmdd and vice versa. The first one does this for all fields of the type SQL_DATE, the second one does this for the fields with the name datefield.
The !Filter parameter can also be passed to the function TableAttr of the DBIx::Database object. In this case it applies to all DBIx::Recordset objects which use these tables.
A third parameter can be optionally specified. It could be set to "DBIx::Recordset::rqINSERT", "DBIx::Recordset::rqUPDATE", or the sum of both. If set, the InputFunction (which is called during UPDATE or INSERT) is always called for this field in updates and/or inserts depending on the value. If there is no data specified for this field as an argument to a function which causes an UPDATE/INSERT, the InputFunction is called with an argument of undef.
During UPDATE and INSERT the input function gets either the string 'insert' or 'update' passed as second parameter.
See also !Links and WORKING WITH MULTIPLE TABLES below
Look at !LinkName for more information.
The following example prefetches all record with id < 7: tie %dbhash, 'DBIx::Recordset::Hash', {'!DataSource' => $DSN, '!Username' => $User, '!Password' => $Password, '!Table' => 'foo', '!PreFetch' => { '*id' => '<', 'id' => 7 }, '!PrimKey' => 'id'} ; The following example prefetches all records: tie %dbhash, 'DBIx::Recordset::Hash', {'!DataSource' => $DSN, '!Username' => $User, '!Password' => $Password, '!Table' => 'bar', '!PreFetch' => '*', '!PrimKey' => 'id'} ;
The following example sets up a hash, that, when more then one record with the same id is found, the field C<sum> is added and the first record is returned, where the C<sum> field contains the sum of B<all> found records: tie %dbhash, 'DBIx::Recordset::Hash', {'!DataSource' => $DSN, '!Username' => $User, '!Password' => $Password, '!Table' => 'bar', '!MergeFunc' => sub { my ($a, $b) = @_ ; $a->{sum} += $b->{sum} ; }, '!PrimKey' => 'id'} ;
The following parameters are used to build an SQL WHERE expression
Example: *set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:Oracle:....', '!Table' => 'users', '$where' => 'name = ? and age > ?', '$values' => ['richter', 25] }) ;
NOTE: Filters defined with "!Filter" are not applied to these values, because DBIx::Recordset has no chance to know with values belongs to which field.
Example: 'name' => [ 'mouse', 'cat'] will expand to name='mouse' or name='cat'
Example: 'name' => "mouse\tcat" will expand to name='mouse' or name='cat' NOTE: The above example can also be written as 'name' => [ 'mouse', 'cat']
Example: 'value' => 9, '*value' => '>' expand to value > 9
Could also be an array ref, so you can pass different operators for the values. This is mainly handy when you need to select a range
Example: $set -> Search ({id => [5, 7 ], '*id' => ['>=', '<='], '$valueconj' => 'and'}) ; This will expanded to "id >= 5 and id <= 7"
NOTE: To get a range you need to specify the $valueconj parameter as "and" because it defaults to "or".
Example: $set -> Search ({id => 5, '$expr' => { 'name' => 'Richter', 'country' => 'de', '$conj' => 'or' } }) ; This will expand to (name = 'Richter' or country = 'de') and id = 5
NOTE 1: If !fields is supplied at setup time, this can not be overridden by $fields.
NOTE 2: The keys for the returned hash normally don't have a table part. Only the fieldname part forms the key. (See !LongNames for an exception.)
NOTE 3: Because the query result is returned in a hash, there can only be one out of multiple fields with the same name fetched at once. If you specify multiple fields with same name, only one is returned from a query. Which one this actually is, depends on the DBD driver. (See !LongNames for an exception.)
See also !PrimKey
The following parameters specify which action is to be executed:
params: setup
params: setup
params: setup
The first form ties the hash to an already existing object, the second one sets up a new object.
params: setup
The first form ties the hash to an already existing object, the second one sets up a new object.
params: setup
The first syntax setups a new DBIx::Recordset object and does the select.
The second and third syntax selects from an existing DBIx::Recordset object.
params: setup (only syntax 1), where (without $order and $fields)
where: (only syntax 3) string for SQL WHERE expression
fields: comma separated list of fieldnames to select
order: comma separated list of fieldnames to sort on
params: setup (only syntax 1), where, search
Fieldnames may be prefixed with a '\' in which case they are not processed (quoted) in any way.
params: setup (only syntax 1), fields
Fieldnames may be prefixed with a '\', in which case they are not processed (quoted) in any way.
params: setup (only syntax 1+2), where (only if $where is omitted), fields
params: setup (only syntax 1), where
params: setup (only syntax 1), where
If none of the above parameters are specified, a search is performed. A search is always performed. On an "=update", the "!PrimKey", if given, is looked upon and used for the where part of the SQL statement, while all other parameters are updated.
params: setup (only syntax 1), execute, where, search, fields
"Next" returns the first row.
Example: # Add an empty record $i = $set -> Add () ; # Now assign some data $set[$i]{id} = 5 ; $set[$i]{name} = 'test' ; # and here it is written to the database # (without Flush it is written, when the record goes out of scope) $set -> Flush () ;
Add will also set the current record to the newly created empty record. So, you can assign the data by simply using the current record.
# Add an empty record $set -> Add () ; # Now assign some data to the new record $set{id} = 5 ; $set{name} = 'test' ;
To tell you if there are more records, More actually fetches the next record from the database and stores it in memory. It does not, however, change the current record.
The second for allows you the specifies addtional parameter, which creates first, previous, next, last and goto buttons. Example:
$set -> PrevNextForm ({-first => 'First', -prev => '<<Back', -next => 'Next>>', -last => 'Last', -goto => 'Goto #'}, \%fdat)
The goto button lets you jump to an random record number. If you obmit any of the parameters, the corresponding button will not be shown.
Example: # this destroys $set, @set and %set DBIx::Recordset::Undef ('set') ;
The data which is returned by a Select or a Search can be accessed in two ways:
1.) Through an array. Each item of the array corresponds to one of the selected records. Each array-item is a reference to a hash containing an entry for every field.
Example:
$set[1]{id} access the field 'id' of the second
record found
$set[3]{name} access the field 'name' of the fourth
record found
The record is fetched from the DBD driver when you access it the first time and is stored by DBIx::Recordset for later access. If you don't access the records one after each other, the skipped records are not stored and therefore can't be accessed anymore, unless you specify the !StoreAll parameter.
2.) DBIx::Recordset holds a current record which can be accessed directly via a hash. The current record is the one you last accessed via the array. After a Select or Search, it is reset to the first record. You can change the current record via the methods Next, Prev, First, Add.
Example:
$set{id} access the field 'id' of the current record
$set{name} access the field 'name' of the current
record
Instead of doing a Select or Search you can directly access one row of a table when you have tied a hash to DBIx::Recordset::Hash or have specified the !HashAsRowKey Parameter. The hashkey will work as primary key to the table. You must specify the !PrimKey as setup parameter.
Example:
$set{4}{name} access the field 'name' of the row
with primary key = 4
One way to update/insert data into the database is by using the Update, Insert or Execute method of the DBIx::Recordset object. A second way is to directly assign new values to the result of a previous Select/Search.
Example:
# setup a new object and search all records with name xyz
*set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:db:tab',
'!PrimKey => 'id', '!Table' => 'tabname', 'name' =>
'xyz'}) ;
#now you can update an existing record by assigning new values #Note: if possible, specify a PrimKey for update to work faster $set[0]{'name'} = 'zyx' ; # or insert a new record by setting up an new array row $set[9]{'name'} = 'foo' ; $set[9]{'id'} = 10 ; # if you don't know the index of a new row you can obtain # one by using Add my $i = $set -> Add () ; $set[$i]{'name'} = 'more foo' ; $set[$i]{'id'} = 11 ; # or add an empty record via Add and assign the values to the current # record $set -> Add () ; $set{'name'} = 'more foo' ; $set{'id'} = 11 ; # or insert the data directly via Add $set -> Add ({'name' => 'even more foo', 'id' => 12}) ; # NOTE: up to this point, NO data is actually written to the db! # we are done with that object, Undef will flush all data to the db DBIx::Recordset::Undef ('set') ;
IMPORTANT: The data is not written to the database until you explicitly call flush, or a new query is started, or the object is destroyed. This is to keep the actual writes to the database to a minimum.
DBIx::Recordset has some nice features to make working with multiple tables and their relations easier.
First, you can specify more than one table to the !Table parameter. If you do so, you need to specify how both tables are related. You do this with !TabRelation parameter. This method will access all the specified tables simultanously.
If you have the following two tables, where the field street_id is a pointer to the table street:
table name name char (30), street_id integer table street id integer, street char (30), city char (30)
You can perform the following search:
*set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:drv:db', '!Table' => 'name, street', '!TabRelation'=> 'name.street_id = street.id'}) ;
The result is that you get a set which contains the fields name, street_id, street, city and id, where id is always equal to street_id. If there are multiple streets for one name, you will get as many records for that name as there are streets present for it. For this reason, this approach works best when you have a 1:1 relation.
It is also possible to specify JOINs. Here's how:
*set = DBIx::Recordset -> Search ({ '!DataSource' => 'dbi:drv:db', '!Table' => 'name, street', '!TabJoin' => 'name LEFT JOIN street ON (name.street_id=street.id)'}) ;
The difference between this and the first example is that this version also returns a record even if neither table contains a record for the given id. The way it's done depends on the JOIN you are given (LEFT/RIGHT/INNER) (see your SQL documentation for details about JOINs).
If you have 1:n relations between two tables, the following may be a better way to handle it:
*set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:drv:db', '!Table' => 'name', '!Links' => { '-street' => { '!Table' => 'street', '!LinkedField' => 'id', '!MainField' => 'street_id' } } }) ;
After that query, every record will contain the fields name and street_id. Additionally, there is a pseudofield named -street, which could be used to access another recordset object, which is the result of a query where street_id = id. Use
$set{name} to access the name field $set{-street}{street} to access the first street (as long as the current record of the subobject isn't modified) $set{-street}[0]{street} first street $set{-street}[1]{street} second street $set{-street}[2]{street} third street $set[2]{-street}[1]{street} to access the second street of the third name
You can have multiple linked tables in one recordset; you can also nest linked tables or link a table to itself.
NOTE: If you select only some fields and not all, the field which is specified by '!MainField' must be also given in the '!Fields' or '$fields' parameter.
NOTE: See also Automatic detection of links below
In the LinkName feature you may specify a "name" for every table. A name is one or more fields which gives a human readable "key" of that record. For example in the above example id is the key of the record, but the human readable form is street.
*set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:drv:db', '!Table' => 'name', '!LinkName' => 1, '!Links' => { '-street' => { '!Table' => 'street', '!LinkedField' => 'id', '!MainField' => 'street_id', '!NameField' => 'street' } } }) ;
For every record in the table, this example will return the fields:
name street_id street
If you have more complex records, you may also specify more than one field in !NameField and pass it as an reference to an array e.g. ['street', 'city']. In this case, the result will contain
name street_id street city
If you set !LinkName to 2, the result will contain the fields
name street_id STREET_ID
where STREET_ID contains the values of the street and city fields joined together. If you set !LinkName to 3, you will get only
name street_id
where street_id contains the values of the street and city fields joined together.
NOTE: The !NameField can also be specified as a table attribute with the function TableAttr. In this case you don't need to specify it in every link. When a !NameField is given in a link description, it overrides the table attribute.
DBIx::Recordset and DBIx::Database will try to automatically detect links between tables based on the field and table names. For this feature to work, the field which points to another table must consist of the table name and the field name of the destination joined together with an underscore (as in the above example name.street_id). Then it will automatically recognized as a pointer to street.id.
*set = DBIx::Recordset -> Search ({'!DataSource' => 'dbi:drv:db', '!Table' => 'name') ;
is enough. DBIx::Recordset will automatically add the !Links attribute. Additionally, DBIx::Recordset adds a backlink (which starts with a star ('*')), so for the table street, in our above example, there will be a link, named *name, which is a pointer from table street to all records in the table name where street.id is equal to name.street_id.
You may use the !Links attribute to specify links which can not be automatically detected.
NOTE: To specify more then one link from one table to another table, you may prefix the field name with an specifier followed by two underscores. Example: first__street_id, second__street_id. The link (and backlink) names are named with the prefix, e.g. -first__street and the backlink *first__name.
The DBIx::Database object gathers information about a datasource. Its main purpose is to create, at startup, an object which retrieves all necessary information from the database. This object detects links between tables and stores this information for use by the DBIx::Recordset objects. There are additional methods which allow you to add kinds of information which cannot be retrieved automatically.
Example:
$db = DBIx::Database -> new ({'!DataSource' => $DSN, '!Username' => $User, '!Password' => $Password, '!KeepOpen' => 1}) ; *set = DBIx::Recordset -> Search ({'!DataSource' => $db, '!Table' => 'foo', }) ;
This is intended as mechanism to retrieve the necessary metadata; for example, when your web server starts (e.g. in the startup.pl file of mod_perl). Here you can give the database object a name. Later in your mod_perl or Embperl scripts, you can use this metadata by specifying this name. This will speed up the setup of DBIx::Recordset object without the need to pass a reference to the DBIx::Database object.
You also can specify a hashref which can contain the following parameters:
!DataSource, !Username, !Password, !DBIAttr, !SaveAs, !KeepOpen, !TableFilter, !DoOnConnect, !Reconnect
returns the database handle (only if you specify !KeepOpen when calling "new").
$name = The name of the DBIx::Database object you wish to retrieve
Get a DBIx::Database object which has already been set up based on the name.
get and/or set an attribute for an specfic table.
Get and/or set a link description for an table. If no $linkname is given, returns all links for that table.
Get and/or set the meta data for the given table.
This returns a reference to a hash of the keys to all the tables of the datasource.
Returns a reference to an array of all fieldnames for the given table.
Returns a reference to an array of all fieldtypes for the given table.
The CreateTables method is used to create an modify the schema of your database. The idea is to define the schema as a Perl data structure and give it to this function, it will compare the actual schema of the database with the one provided and creates new tables, new fields or drop fields as necessary. It also sets the permission on the tables and is able to create indices for the tables. It will never drop a whole table! NOTE: Create tables cannot deteminate changes of the datatype of a fields, because DBI is not able to provide this information in a standard way.
If give as a filename, the file must contain an hash %DBDefault and an array @DBSchema. The first gives default and the second is an array of hashs. Every of this hash defines one table.
Example:
%DBDefault = ( '!Grant' => [ 'select', 'insert', 'update', 'delete', ], ) ; @DBSchema = ( { '!Table' => 'language', '!Fields' => [ 'id' => 'char (2)', 'directory' => 'varchar(40)', 'name' => 'varchar(40)', 'europe' => 'bool', ], '!PrimKey' => 'id', '!Default' => { 'europe' => 1, }, '!Init' => [ {'id' => 'de', 'directory' => 'html_49', 'name' => 'deutsch'}, {'id' => 'en', 'directory' => 'html_76', 'name' => 'english'}, {'id' => 'fr', 'directory' => 'html_31', 'name' => 'french'}, ], '!Index' => [ 'directory' => '', ] }, );
The hash which defines a table can have the following keys:
Example:
'!For' => { 'Oracle' => { '!Constraints' => { 'web_id' => ['foreign key' => 'REFERENCES web (id)'], 'prim__menu_id' => ['!Name' => 'web_prim_menu_id', 'foreign key' => 'REFERENCES menu (id)', 'not null' => ''], } }, },
Drops all tables. Use with care!
In SQL all names (field/tablenames etc.) should be case insensitive. Various DBMS handle the case of names differently. For that reason DBIx::Recordset translates all names to lower case, ensuring your application will run with any DBMS, regardless of whether names are returned in lower/uppercase by the DBMS. Some DBMS are case-sensitive (I know at least Sybase, depending on your collate settings). To use such a case-sensitive DBMS, it is best to create your database with all names written in lowercase. In a situation where this isn't possible, you can set $PreserveCase to 1. In this case DBIx::Recordset will not perform any case translation. NOTE: $PreserveCase is still experimental and may change in future releases.
Some operations in Perl (i.e. "foreach", assigning arrays) need to know the size of the whole array. When Perl needs to know the size of an array it call the method "FETCHSIZE". Since not all DBD drivers/DBMS returns the number of selected rows after an SQL "SELECT", the only way to really determine the number of selected rows would be to fetch them all from the DBMS. Since this could cause a lot of work, it may be very inefficent. Therefore DBIx::Recordset by default calls die() when Perl calls FETCHSIZE. If you know your DBD drivers returns the correct value in $sth -> "rows" after the execution of an "SELECT", you can set $FetchsizeWarn to zero to let "FETCHSIZE" return the value from $sth -> "rows". Setting it to 1 will cause DBIx::Recordset to only issue a warning, but perform the operation.
NOTE: Since I don't have enough experience with the behaviour of this feature with different DBMS, this is considered experimental.
DBIx::Recordset is able to write a logfile so you can see what's happening inside. There are two public variables and the "!Debug" parameter used for this purpose:
$DBIx::Recordset::Debug sets the default debug level for new objects, "!Debug" can be used to set the debuglevel on a per object basis.
Example: # open the log file open LOG, ">test.log" or die "Cannot open test.log" ; # assign filehandle *DBIx::Recordset::LOG = \*LOG ; # set debugging level $DBIx::Recordset::Debug = 2 ; # now you can create a new DBIx::Recordset object
Since one possible application of DBIx::Recordset is its use in a web-server environment, some attention should paid to security issues.
The current version of DBIx::Recordset does not include extended security management, but some features can be used to make your database access safer. (More security features will come in future releases.)
First of all, use the security feature of your database. Assign the web server process as few rights as possible.
The greatest security risk is when you feed DBIx::Recordset a hash which contains the formfield data posted to the web server. Somebody who knows DBIx::Recordset can post other parameters than those you would expect a normal user to post. For this reason, a primary issue is to override all parameters which should never be posted by your script.
Example:
*set = DBIx::Recordset -> Search ({%fdat, ('!DataSource' =>
"dbi:$Driver:$DB", '!Table' => "$Table")}) ;
(assuming your posted form data is in %fdat). The above call will make sure that nobody from outside can override the values supplied by $Driver, $DB and $Table.
It is also wise to initialize your objects by supplying parameters which can not be changed.
Somewhere in your script startup (or at server startup time) add a setup call:
*set = DBIx::Recordset-> Setup ({'!DataSource' => "dbi:$Driver:$DB", '!Table' => "$Table", '!Fields' => "a, b, c"}) ;
Later, when you process a request you can write:
$set -> Search (\%fdat) ;
This will make sure that only the database specified by $Driver, $DB, the table specified by $Table and the Fields a, b, and c can be accessed.
I have put a great deal of effort into making DBIx::Recordset run with various DBD drivers. The problem is that not all necessary information is specified via the DBI interface (yet). So I have made the module DBIx::Compat which gives information about the difference between various DBD drivers and their underlying database systems. Currently, there are definitions for:
DBIx::Recordset has been tested with all those DBD drivers (on Linux 2.0.32, except DBD::ODBC, which has been tested on Windows '95 using Access 7 and with MS SQL Server).
If you want to use another DBD driver with DBIx::Recordset, it may be necessary to create an entry for that driver. See perldoc DBIx::Compat for more information.
The following are some examples of how to use DBIx::Recordset. The Examples are from the test.pl. The examples show the DBIx::Recordset call first, followed by the generated SQL command.
*set = DBIx::Recordset-> Setup ({'!DataSource' => "dbi:$Driver:$DB", '!Table' => "$Table"}) ;
Setup a DBIx::Recordset for driver $Driver, database $DB to access table $Table.
$set -> Select () ; SELECT * from <table> ; $set -> Select ({'id'=>2}) ; is the same as $set1 -> Select ('id=2') ; SELECT * from <table> WHERE id = 2 ; $set -> Search({ '$fields' => 'id, balance AS paid - total ' }) ; SELECT id, balance AS paid - total FROM <table> $set -> Select ({name => "Second Name\tFirst Name"}) ; SELECT * from <table> WHERE name = 'Second Name' or name = 'First Name' ; $set1 -> Select ({value => "9991 9992\t9993", '$valuesplit' => ' |\t'}) ; SELECT * from <table> WHERE value = 9991 or value = 9992 or value = 9993 ; $set -> Select ({'+name&value' => "9992"}) ; SELECT * from <table> WHERE name = '9992' or value = 9992 ; $set -> Select ({'+name&value' => "Second Name\t9991"}) ; SELECT * from <table> WHERE (name = 'Second Name' or name = '9991) or (value = 0 or value = 9991) ; $set -> Search ({id => 1,name => 'First Name',addon => 'Is'}) ; SELECT * from <table> WHERE id = 1 and name = 'First Name' and addon = 'Is' ; $set1 -> Search ({'$start'=>0,'$max'=>2, '$order'=>'id'}) or die "not ok ($DBI::errstr)" ; SELECT * from <table> ORDER BY id ; B<Note:> Because of the B<start> and B<max> only records 0,1 will be returned $set1 -> Search ({'$start'=>0,'$max'=>2, '$next'=>1, '$order'=>'id'}) or die "not ok ($DBI::errstr)" ; SELECT * from <table> ORDER BY id ; B<Note:> Because of the B<start>, B<max> and B<next> only records 2,3 will be returned $set1 -> Search ({'$start'=>2,'$max'=>1, '$prev'=>1, '$order'=>'id'}) or die "not ok ($DBI::errstr)" ; SELECT * from <table> ORDER BY id ; B<Note:> Because of the B<start>, B<max> and B<prev> only records 0,1,2 will be returned $set1 -> Search ({'$start'=>5,'$max'=>5, '$next'=>1, '$order'=>'id'}) or die "not ok ($DBI::errstr)" ; SELECT * from <table> ORDER BY id ; B<Note:> Because of the B<start>, B<max> and B<next> only records 5-9 will be returned *set6 = DBIx::Recordset -> Search ({ '!DataSource' => "dbi:$Driver:$DB", '!Table' => "t1, t2", '!TabRelation' => "t1.value=t2.value", '!Fields' => 'id, name, text', 'id' => "2\t4" }) or die "not ok ($DBI::errstr)" ; SELECT id, name, text FROM t1, t2 WHERE (id=2 or id=4) and t1.value=t2.value ; $set6 -> Search ({'name' => "Fourth Name" }) or die "not ok ($DBI::errstr)" ; SELECT id, name, text FROM t1, t2 WHERE (name = 'Fourth Name') and t1.value=t2.value ; $set6 -> Search ({'id' => 3, '$operator' => '<' }) or die "not ok ($DBI::errstr)" ; SELECT id, name, text FROM t1, t2 WHERE (id < 3) and t1.value=t2.value ; $set6 -> Search ({'id' => 4, 'name' => 'Second Name', '*id' => '<', '*name' => '<>' }) or die "not ok ($DBI::errstr)" ; SELECT id, name, text FROM t1, t2 WHERE (id<4 and name <> 'Second Name') and t1.value=t2.value ; $set6 -> Search ({'id' => 2, 'name' => 'Fourth Name', '*id' => '<', '*name' => '=', '$conj' => 'or' }) or die "not ok ($DBI::errstr)" ; SELECT id, name, text FROM t1, t2 WHERE (id<2 or name='Fourth Name') and t1.value=t2.value ; $set6 -> Search ({'+id|addon' => "7\tit", 'name' => 'Fourth Name', '*id' => '<', '*addon' => '=', '*name' => '<>', '$conj' => 'and' }) or die "not ok ($DBI::errstr)" ; SELECT id, name, text FROM t1, t2 WHERE (t1.value=t2.value) and ( ((name <> Fourth Name)) and ( ( id < 7 or addon = 7) or ( id < 0 or addon = 0))) $set6 -> Search ({'+id|addon' => "6\tit", 'name' => 'Fourth Name', '*id' => '>', '*addon' => '<>', '*name' => '=', '$compconj' => 'and', '$conj' => 'or' }) or die "not ok ($DBI::errstr)" ; SELECT id, name, text FROM t1, t2 WHERE (t1.value=t2.value) and ( ((name = Fourth Name)) or ( ( id > 6 and addon <> 6) or ( id > 0 and addon <> 0))) ; *set7 = DBIx::Recordset -> Search ({ '!DataSource' => "dbi:$Driver:$DB", '!Table' => "t1, t2", '!TabRelation' => "t1.id=t2.id", '!Fields' => 'name, typ'}) or die "not ok ($DBI::errstr)" ; SELECT name, typ FROM t1, t2 WHERE t1.id=t2.id ; %h = ('id' => 22, 'name2' => 'sqlinsert id 22', 'value2'=> 1022) ; *set9 = DBIx::Recordset -> Insert ({%h, ('!DataSource' => "dbi:$Driver:$DB", '!Table' => "$Table[1]")}) or die "not ok ($DBI::errstr)" ; INSERT INTO <table> (id, name2, value2) VALUES (22, 'sqlinsert id 22', 1022) ; %h = ('id' => 22, 'name2' => 'sqlinsert id 22u', 'value2'=> 2022) ; $set9 -> Update (\%h, 'id=22') or die "not ok ($DBI::errstr)" ; UPDATE <table> WHERE id=22 SET id=22, name2='sqlinsert id 22u', value2=2022 ; %h = ('id' => 21, 'name2' => 'sqlinsert id 21u', 'value2'=> 2021) ; *set10 = DBIx::Recordset -> Update ({%h, ('!DataSource' => "dbi:$Driver:$DB", '!Table' => "$Table[1]", '!PrimKey' => 'id')}) or die "not ok ($DBI::errstr)" ; UPDATE <table> WHERE id=21 SET name2='sqlinsert id 21u', value2=2021 ; %h = ('id' => 21, 'name2' => 'Ready for delete 21u', 'value2'=> 202331) ; *set11 = DBIx::Recordset -> Delete ({%h, ('!DataSource' => "dbi:$Driver:$DB", '!Table' => "$Table[1]", '!PrimKey' => 'id')}) or die "not ok ($DBI::errstr)" ; DELETE FROM <table> WHERE id = 21 ; *set12 = DBIx::Recordset -> Execute ({'id' => 20, '*id' => '<', '!DataSource' => "dbi:$Driver:$DB", '!Table' => "$Table[1]", '!PrimKey' => 'id'}) or die "not ok ($DBI::errstr)" ; SELECT * FROM <table> WHERE id<20 ; *set13 = DBIx::Recordset -> Execute ({'=search' => 'ok', 'name' => 'Fourth Name', '!DataSource' => "dbi:$Driver:$DB", '!Table' => "$Table[0]", '!PrimKey' => 'id'}) or die "not ok ($DBI::errstr)" ; SELECT * FROM <table> WHERE ((name = Fourth Name)) $set12 -> Execute ({'=insert' => 'ok', 'id' => 31, 'name2' => 'insert by exec', 'value2' => 3031, # Execute should ignore the following params, since it is already setup '!DataSource' => "dbi:$Driver:$DB", '!Table' => "quztr", '!PrimKey' => 'id99'}) or die "not ok ($DBI::errstr)" ; SELECT * FROM <table> ; $set12 -> Execute ({'=update' => 'ok', 'id' => 31, 'name2' => 'update by exec'}) or die "not ok ($DBI::errstr)" ; UPDATE <table> SET name2=update by exec,id=31 WHERE id=31 ; $set12 -> Execute ({'=insert' => 'ok', 'id' => 32, 'name2' => 'insert/upd by exec', 'value2' => 3032}) or die "not ok ($DBI::errstr)" ; INSERT INTO <table> (name2,id,value2) VALUES (insert/upd by exec,32,3032) ; $set12 -> Execute ({'=delete' => 'ok', 'id' => 32, 'name2' => 'ins/update by exec', 'value2' => 3032}) or die "not ok ($DBI::errstr)" ; DELETE FROM <table> WHERE id=32 ;
As far as possible for me, support will be available via the DBI Users' mailing list. (dbi-user@fugue.com)
G.Richter (richter@dev.ecos.de)
2022-06-13 | perl v5.34.0 |