X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FManual%2FSQLHackers%2FUPDATE.pod;h=1620acd31eb3561e1daad9622bf5fa170cefb64e;hb=07acc18d929eb449f0f83a9fde8bd34b13abf40f;hp=0cb3cb8d3f852c17a065bd00c414da9e338f0d28;hpb=6c2a4396fbfa0868cd964f15050a67c9a36b563d;p=dbsrgits%2FDBIx-Class-Manual-SQLHackers.git diff --git a/lib/DBIx/Class/Manual/SQLHackers/UPDATE.pod b/lib/DBIx/Class/Manual/SQLHackers/UPDATE.pod index 0cb3cb8..1620acd 100644 --- a/lib/DBIx/Class/Manual/SQLHackers/UPDATE.pod +++ b/lib/DBIx/Class/Manual/SQLHackers/UPDATE.pod @@ -22,13 +22,13 @@ DBIx::Class::Manual::SQLHackers::UPDATE - DBIx::Class for SQL Hackers - UPDATE =head1 UPDATEing data -=head2 Delayed update versus direct update +=head2 Single row delayed update versus direct update -Rows may be updated in one of two ways. You can create an object -representing an existing database table row, and hold it in your -programmes memory, passing it around from function to function, -changing its values, before actually updating the contents into the -database. This is a delayed update. +Individual rows may be updated via their Result object in one of two +ways. You can create an object representing an existing database table +row and hold it in your programmes memory, passing it around from +function to function changing its values, before actually updating +the contents into the database. This is a delayed update. A direct update still involves fetching the existing row from the database, but instead of storing new column values in the Row object, @@ -54,7 +54,7 @@ To create a Row object for delayed update (or other manipulations), first fetch my $fred_user = $schema->resultset('User')->find({ id => 1 }); - B<$fred_user>'s contents can now be changed using the accessor +B<$fred_user>'s contents can now be changed using the accessor methods created by B, back in L. These are generally named after the columns in the database, so to change fred's real name, use @@ -64,8 +64,9 @@ the B method. $fred_user->realname("John Bloggs"); - This value has not yet changed in the database, we can make the actual -update by calling *update: + +This value has not yet changed in the database, we can make the actual +update by calling *update*: =item 4. Update the set value(s) into the database: @@ -73,6 +74,15 @@ update by calling *update: =back +The update method will only actually send an UPDATE statement to the +database if one or more of the columns have changed. The internal +tracking of which columns have been changed can be queried using +several methods. B returns true (or a list of changed +column names), if any column values have changed. B +will return true or false for the given column name argument. The +previous values of the columns are not stored. + + =head2 Update a single row with simple values UPDATE users @@ -129,66 +139,6 @@ To update a whole set of rows, or all of them, we first need to create a ResultS =back -=head2 Update a row or rows using a column calculation - - -- Yet another pointless example - UPDATE users - SET username = username || '.uk' - WHERE id = 1; - -=over - -=item 1. Create a Schema object representing the database you are working with: - - my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db'); - -=item 2. Call the B method on the resultset for the L you wish to fetch data from: - - my $fred_user = $schema->resultset('User')->find({ id => 1 }); - -The Row object has an B method that will change the values on -the object, and send an UPDATE query to the database. - -=item 3. Call the B method, passing it a hashref of new data: - - $fred_user->update({ username => \['username || ?', '.uk'] }); - -The \[ .. ] syntax here is described in L -documentation, used for passing bind parameters. - -=back - -=head2 Update a row based on data in other tables - - -- Slightly less pointless example - UPDATE posts - SET title = user.username || title - JOIN users user ON user.id = posts.user_id; - -Joining two tables for an update is a similar sort of exercise to -joining them for a select query and using data from both. - -=over - -=item 1. Create a Schema object representing the database you are working with: - - my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db'); - -=item 2. Call the B method on the resultset for the L you wish to update data in, joining to the second table: - - my $posts = $schema->resultset('Post')->search( - {}, - { join => 'user' } - ); - - The B key takes as an argument a nested structure of one or more relation names (see L). - -=item 3. Call the B method on the resultset to run the UPDATE statement: - - $posts->update({ 'me.title' => \[ 'user.username || me.title' ] }); - -=back - =head2 Update or create a row -- MySQL non-standardness (and another silly example) @@ -206,8 +156,8 @@ joining them for a select query and using data from both. SET id = ?, username = ?, dob = ?, realname = ?, password = ?; COMMIT; -DBIx::Class does not produce the non-standard MySQL "ON DUPLICATE KEY -UPDATE", instead it has a shortcut for combining *find* and *update*. +DBIx::Class does not yet produce the non-standard MySQL "ON DUPLICATE KEY +UPDATE", instead it has a shortcut for combining B and B. To avoid race conditions, this should be done in a transaction.