Commit | Line | Data |
6c2a4396 |
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 | |
abc32120 |
25 | =head2 Single row delayed update versus direct update |
6c2a4396 |
26 | |
abc32120 |
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. |
6c2a4396 |
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 | |
abc32120 |
57 | B<$fred_user>'s contents can now be changed using the accessor |
6c2a4396 |
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 | |
abc32120 |
67 | |
68 | This value has not yet changed in the database, we can make the actual |
69 | update by calling *update*: |
6c2a4396 |
70 | |
71 | =item 4. Update the set value(s) into the database: |
72 | |
73 | $fred_user->update(); |
74 | |
75 | =back |
76 | |
abc32120 |
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 | |
6c2a4396 |
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 | |
abc32120 |
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 |
6c2a4396 |
167 | $fred_user->update({ username => \['username || ?', '.uk'] }); |
168 | |
2f41b1a9 |
169 | ^^ you never got around to this |
170 | |
abc32120 |
171 | # the DBIC syntax is a tad different from te thing above (i.e. we no longer encourage 'dummy' crap) |
6c2a4396 |
172 | The \[ .. ] syntax here is described in L<SQL::Abstract> |
173 | documentation, used for passing bind parameters. |
174 | |
abc32120 |
175 | |
6c2a4396 |
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 | |
2f41b1a9 |
207 | ^^ I am 95% sure this won't actually work, please try it (ideally as a passing or failing test) |
208 | |
6c2a4396 |
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 | |
2f41b1a9 |
228 | DBIx::Class does not yet produce the non-standard MySQL "ON DUPLICATE KEY |
0e8be732 |
229 | UPDATE", instead it has a shortcut for combining B<find> and B<update>. |
6c2a4396 |
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: |
2f41b1a9 |
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 |
0e8be732 |
242 | ## Not entirely sure what thing you mean here.. |
243 | |
6c2a4396 |
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 | |