Notes and updates based on riba's most recent comments
[dbsrgits/DBIx-Class-Manual-SQLHackers.git] / lib / DBIx / Class / Manual / SQLHackers / UPDATE.pod
1 =head1 NAME
2
3 DBIx::Class::Manual::SQLHackers::UPDATE - DBIx::Class for SQL Hackers - UPDATE
4
5 =over
6
7 =item L<Introduction|DBIx::Class::Manual::SQLHackers::Introduction>
8
9 =item L<CREATE|DBIx::Class::Manual::SQLHackers::CREATE>
10
11 =item L<INSERT|DBIx::Class::Manual::SQLHackers::INSERT>
12
13 =item L<SELECT|DBIx::Class::Manual::SQLHackers::SELECT>
14
15 =item UPDATE
16
17 =item L<DELETE|DBIx::Class::Manual::SQLHackers::DELETE>
18
19 =item L<BEGIN, COMMIT|DBIx::Class::Manual::SQLHackers::Transactions>
20
21 =back
22
23 =head1 UPDATEing data
24
25 =head2 Single row delayed update versus direct update
26
27 Individual rows may be updated via their Result object in one of two
28 ways. You can create an object representing an existing database table
29 row and hold it in your programmes memory, passing it around from
30 function to function changing its values, before actually updating
31 the contents into the database. This is a delayed update.
32
33 A direct update still involves fetching the existing row from the
34 database, but instead of storing new column values in the Row object,
35 the update method is called and passed the set of new values to store
36 in the table.
37
38 NOTE: Running a direct update on a row object that already has changed
39 values, will *also* apply those values to the database. If values are
40 changed both on the object, and in the update method arguments, the
41 argument values take precedence.
42
43 =head2 Updating a row in memory
44
45 To create a Row object for delayed update (or other manipulations), first fetch it from the database as described in L<Simple SELECT|DBIx::Class::Manual::SQLHackers::SELECT/Simple SELECT>.
46
47 =over
48
49 =item 1. Create a Schema object representing the database you are working with:
50
51         my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
52
53 =item 2. Call the B<find> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to update the contents of:
54
55         my $fred_user = $schema->resultset('User')->find({ id => 1 });
56
57 B<$fred_user>'s contents can now be changed using the accessor
58 methods created by B<add_columns>, back in
59 L<CREATE|DBIx::Class::Manual::SQLHackers::CREATE>. These are generally named
60 after the columns in the database, so to change fred's real name, use
61 the B<realname> method.
62
63 =item 3. Call the B<realname> accessor method on the $fred_user object:
64
65         $fred_user->realname("John Bloggs");
66         
67
68 This value has not yet changed in the database, we can make the actual
69 update by calling *update*:
70
71 =item 4. Update the set value(s) into the database:
72
73         $fred_user->update();
74
75 =back
76
77 The update method will only actually send an UPDATE statement to the
78 database if one or more of the columns have changed. The internal
79 tracking of which columns have been changed can be queried using
80 several methods. B<is_changed> returns true (or a list of changed
81 column names), if any column values have changed. B<is_column_changed>
82 will return true or false for the given column name argument. The
83 previous values of the columns are not stored.
84
85
86 =head2 Update a single row with simple values
87
88     UPDATE users
89     SET username = 'new@email.address'
90     WHERE id = 1;
91     
92 To update an existing row, first B<find> it using the methods shown in L<DBIx::Class::Manual::SQLHackers::SELECT/Simple SELECT, one row via the primary key> or L<DBIx::Class::Manual::SQLHackers::SELECT/Simple SELECT, one row via a unique key>, for example:
93
94 =over
95
96 =item 1. Create a Schema object representing the database you are working with:
97
98         my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
99
100 =item 2. Call the B<find> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to fetch data from:
101
102         my $fred_user = $schema->resultset('User')->find({ id => 1 });
103
104     The Row object has an B<update> method that will change the values on
105 the object, and send an UPDATE query to the database.
106
107 =item 3. Call the B<update> method, passing it a hashref of new data:
108
109         $fred_user->update({ username => 'new@email.address' }); 
110
111 =back
112
113 See also: L</Direct update versus delayed update>.
114
115 =head2 Update multiple rows with simple values
116
117     -- Warning, pointless example!
118     UPDATE users
119     SET dob = '2010-08-16'
120     WHERE realname LIKE 'jess%';
121
122 To update a whole set of rows, or all of them, we first need to create a ResultSet object representing the query conditions that would be needed to select that same set of rows. We need to use B<search>, then we use the B<update> method on the ResultSet.
123
124 =over
125
126 =item 1. Create a Schema object representing the database you are working with:
127
128         my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
129
130 =item 2. Call the B<search> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to fetch data from:
131
132         my $user_search = $schema->resultset('User')->search(
133           { realname => { like => 'jess%' } }
134         );
135
136 =item 3. Call the B<update> method on the resultset to change the matching rows:
137
138         $user_search->update({ dob => '2010-08-16' });
139
140 =back
141
142 =head2 Update a row or rows using a column calculation
143
144     -- Yet another pointless example
145     UPDATE users
146     SET username = username || '.uk'
147     WHERE id = 1;
148
149 =over
150
151 =item 1. Create a Schema object representing the database you are working with:
152
153         my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
154
155 =item 2. Call the B<find> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to fetch data from:
156
157         my $fred_user = $schema->resultset('User')->find({ id => 1 });
158
159 The Row object has an B<update> method that will change the values on
160 the object, and send an UPDATE query to the database.
161
162 =item 3. Call the B<update> method, passing it a hashref of new data:
163
164 # this won't yet work, DBIC for now mandates the [ {} => $value ] format, the simple \[ $sql, $value1, $value2 ] will start being recognized later on 
165 # the only documentation we currently have is this, if you can turn it into a DBIC pod-patch it will be freaking awesome
166 # https://github.com/dbsrgits/dbix-class/commit/0e773352
167         $fred_user->update({ username => \['username || ?', '.uk'] }); 
168
169 ^^ you never got around to this
170
171 # the DBIC syntax is a tad different from te thing above (i.e. we no longer encourage 'dummy' crap)
172 The \[ .. ] syntax here is described in L<SQL::Abstract>
173 documentation, used for passing bind parameters.
174
175
176 =back
177
178 =head2 Update a row based on data in other tables
179
180     -- Slightly less pointless example
181     UPDATE posts 
182     SET title = user.username || title
183     JOIN users user ON user.id = posts.user_id;
184
185 Joining two tables for an update is a similar sort of exercise to
186 joining them for a select query and using data from both.
187
188 =over
189
190 =item 1. Create a Schema object representing the database you are working with:
191
192         my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
193
194 =item 2. Call the B<search> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to update data in, joining to the second table:
195
196         my $posts = $schema->resultset('Post')->search(
197           {},
198           { join => 'user' }
199         );
200
201     The B<join> key takes as an argument a nested structure of one or more relation names (see L<DBIx::Class::Manual::SQLHackers::CREATE>).
202
203 =item 3. Call the B<update> method on the resultset to run the UPDATE statement:
204
205         $posts->update({ 'me.title' => \[ 'user.username || me.title' ] });
206
207 ^^ I am 95% sure this won't actually work, please try it (ideally as a passing or failing test)
208
209 =back
210
211 =head2 Update or create a row
212
213     -- MySQL non-standardness (and another silly example)
214     INSERT INTO users ( ... ) 
215     VALUES ( ... )
216     ON DUPLICATE KEY UPDATE password = 'newpass';
217
218     -- OR:
219     BEGIN TRANSACTION;
220     SELECT id, username, dob, realname, password
221     FROM users
222     WHERE username = 'joebloggs';
223     
224     UPDATE users
225     SET id = ?, username = ?, dob = ?, realname = ?, password = ?;
226     COMMIT;
227     
228 DBIx::Class does not yet produce the non-standard MySQL "ON DUPLICATE KEY
229 UPDATE", instead it has a shortcut for combining B<find> and B<update>.
230
231 To avoid race conditions, this should be done in a transaction.
232
233 =over
234
235 =item 1. Create a Schema object representing the database you are working with:
236
237         my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
238
239 =item 2. Call the B<txn_do> method on the schema object, passing it a coderef to execute inside the transaction:
240 ^^ ouch! I didn't realize we don't do that automatically, this is a bug
241 ^^ probably a good idea not to mention it - I'll fix it @ GPW
242 ## Not entirely sure what thing you mean here.. 
243
244         $schema->txn_do( sub {
245
246 =item 3. Call the B<update_or_create> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to update data in:
247
248         $schema->resultset('User')->update_or_create(
249           {
250             username => 'joebloggs',
251             dob => '2010-09-10',
252             realname = 'Joe Bloggs'
253           },
254           {
255             key => 'uniq_username'
256           }
257         );
258
259 =item 4. Close off the transaction / coderef:
260
261         } );
262
263 =back
264        
265 A transaction is issued containing two statements, a B<SELECT> and then
266 either an B<INSERT> or an B<UPDATE> depending on the results.
267
268 Do not use this method if you definitely don't have either the primary
269 key, or a unique index value available. The B<find> method used under
270 the hood will probably not do what you expect. In this case, manually
271 run a separate B<search> method call to check for existance, and then
272 call B<create>.
273