3 DBIx::Class::Manual::SQLHackers::SELECT - DBIx::Class for SQL Hackers - SELECT
7 =item L<Introduction|DBIx::Class::Manual::SQLHackers::Introduction>
9 =item L<CREATE|DBIx::Class::Manual::SQLHackers::CREATE>
11 =item L<INSERT|DBIx::Class::Manual::SQLHackers::INSERT>
15 =item L<UPDATE|DBIx::Class::Manual::SQLHackers::UPDATE>
17 =item L<DELETE|DBIx::Class::Manual::SQLHackers::DELETE>
19 =item L<BEGIN, COMMIT|DBIx::Class::Manual::SQLHackers::Transactions>
25 =head2 Fetching rows from a query
27 SELECT id, username, dob, realname, password
30 In DBIx::Class queries are represented by ResultSet objects. These are created by calling B<search> on existing resultsets, passing new search conditions. A query is not run against the database until data is explicitly requested.
32 You can either fetch all the data at once, or iterate over the results:
36 =item 1. Create a Schema object representing the database you are working with:
38 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
40 =item 2. The B<resultset> method returns a ResultSet representing a query with no conditions on the given B<ResultSource>:
42 my $user_resultset = $schema->resultset('User');
44 =item 3. Fetch all users as Row objects using the B<all> method:
46 my @users = $user_resultset->all();
48 =item 4. OR, fetch each user as a Row object using B<next>:
50 while( my $user = $user_resultset->next()) {
55 =head2 Fetching column values from a Row object
57 The Row object represents the results from a single data source table in the query. The column values can be retrieved by using the accessor methods named after the column names. (By default that is, accessors can be changed in the L<Result Class|DBIx::Class::ResulSource> if needed).
59 print $user->username;
61 See the L<DBIx::Class::Row> documentation for more things you can do
64 =head2 Simple SELECT, one row via the primary key
66 SELECT id, username, dob, realname, password
70 The B<find> method on a ResultSet is a shortcut to create a query based on the inputs, run the query, and return a single row as a Row object result.
72 If passed a condition which matches multiple rows, a warning is given.
76 =item 1. Create a Schema object representing the database you are working with:
78 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
80 =item 2. Call the B<find> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to fetch data from:
82 my $fred_user = $schema->resultset('User')->find({ id => 1 });
86 B<$fred_user> is a now Row object.
88 =head2 Simple SELECT, one row via a unique key
90 SELECT id, username, dob, realname, password
92 WHERE username = 'fredbloggs';
94 B<find> also works well on unique constraints, for example the username of our user. Unique constraints can be defined on Result classes using B<add_unique_constraint> (See L<CREATE|DBIx::Class::Manual::SQLHackers::CREATE>).
98 =item 1. Create a Schema object representing the database you are working with:
100 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
102 =item 2. Call the B<find> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to fetch data from:
104 my $fred_user = $schema->resultset('User')->find(
105 { username => 'fredbloggs' },
106 { key => 'uniq_username' }
111 "uniq_username" is the name of a constraint defined on the User L<ResultSource|DBIx::Class::ResultSource> which specifies that the username column is unique across the table. The second argument to B<find> is a set of attributes, of which the "key" attribute defines which constraint to do a lookup on.
113 =head2 Simple SELECT, with WHERE condition
115 SELECT id, username, dob, realname, password
117 WHERE dob = '1910-02-01';
119 To select all users born on the date '1910-02-01', we can use the B<search> method to prepare a query. Search returns a new resultset with the search conditions stored in it, it does not run the query on the database.
123 =item 1. Create a Schema object representing the database you are working with:
125 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
127 =item 2. Call the B<search> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to fetch data from:
129 my $dob_search = $schema->resultset('User')->search(
130 { dob => '1910-02-01' }
135 To run the query, use the B<all> or B<next> methods shown at the beginning of this page.
137 =head2 SELECT with different WHERE conditions
139 Below are shown some common SQL where conditions. The syntax for these is parsed by a module called L<SQL::Abstract> which DBIx::Class uses. They can all be passed to the B<search> method as conditions.
141 SELECT id, username, dob, realname, password
143 WHERE username LIKE 'fred%';
145 my $name_search = $schema->resultset('User')->search(
146 { username => { '-like' => 'fred%' } }
149 SELECT id, username, dob, realname, password
151 WHERE dob BETWEEN '1910-01-01' AND '1910-12-31';
153 my $year_dob_search = $schema->resultset('User')->search(
154 { dob => { '-between' => ['1910-01-01', '1910-12-31'] } }
157 SELECT id, username, dob, realname, password
159 WHERE dob IN ('1910-02-01', '1910-02-02');
161 my $feb_dob_search = $schema->resultset('User')->search(
162 { dob => { '-in' => ['1910-02-01', '1910-02-02'] } }
165 SELECT id, username, dob, realname, password
167 WHERE dob >= 1911-01-01;
169 my $next_year_dob = $schema->resultset('User')->search(
170 { dob => { '>=', '1911-01-01' } }
174 =head2 SELECT with WHERE condition on JOINed table
176 SELECT posts.id, created_date, title, post
178 JOIN users user ON user.id = posts.user_id
179 WHERE user.username = 'fredbloggs';
181 The second argument to B<search> is a hashref of attributes to apply to the query. One of them is B<join>, which is used to connect to other tables using the relationships defined in the Result classes.
185 =item 1. Create a Schema object representing the database you are working with:
187 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
189 =item 2. Call the B<search> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to fetch data from:
191 my $freds_posts = $schema->resultset('Post')->search(
192 { 'user.username' => 'fredbloggs' },
198 Note that the string "user", used twice here, refers to the B<name> of the L<Relationship|DBIx::Class::Manual::SQLHackers::CREATE> between the "Post" source and the "User" source. All dealings with related tables are refered to by relationship names, not table names.
200 To run the query, use the B<all> or B<next> methods show at the beginning of this page.
202 =head2 SELECT with fewer columns
207 There's usually little reason to do this sort of query, as fetching all the data in a row doesn't cost any more time than fetching some of it. Unless of course your source is a View with calculations, or has huge blobs, or.. Okay, you might well want to do this occasionally.
209 # this is completely false, is there a doc that states this that we need to fix?
210 # find() takes all search() attributes, including things like prefetch
211 B<find> will always pull all the columns for the found row, so use the *search* method for this.
215 =item 1. Create a Schema object representing the database you are working with:
217 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
219 =item 2. Call the B<search> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to fetch data from:
221 my $post_titles = $schema->resultset('Post')->search(
223 { columns => [qw/id title/] }
228 Note that accessors for other columns not fetched will return B<undef>, which is also the perl equivalent of the SQL C<NULL> value. To discover whether a columns data has been loaded or not, use L<DBIx::Class::Row/has_column_loaded>.
231 =head2 SELECT with aggregates
236 To find out how many users exist. This simple one can be achieved with a built-in method, B<count>.
240 =item 1. Create a Schema object representing the database you are working with:
242 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
244 =item 2. Call the *count* method on the resultset for the [Source] you wish to fetch data from:
246 my $posts_count = $schema->resultset('Post')->count();
250 The result is not an object, just a number.
255 A rather pointless exercise in summing an entire "amount" column from an imaginary "prices" table. This can be done in several ways, first, the built-in L<DBIx::Class::ResultSet::Column> method, by calling B<get_column>.
259 =item 1. Create a Schema object representing the database you are working with:
261 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
263 =item 2. Call the B<get_column> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to fetch data from, then the B<sum> method:
265 my $sum_prices = $schema->resultset('Price')->get_column('amount')
270 The result is just a number.
272 The alternate way uses the B<search> method and is easier to build further refinements into.
276 =item 1. Create a Schema object representing the database you are working with:
278 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
280 =item 2. Call the B<search> method on the resultset for the L<ResultSource|DBIx::Class::ResultSource> you wish to fetch data from:
282 my $sum_prices_rs = $schema->resultset('Price')->search(
284 { columns => { sum_amount => { SUM => 'amount'} } },
289 The result is a resultset. To fetch the one-row result, call B<single> or B<all>. The resulting Row object will not contain an accessor for the virtual "sum_amount" column, we'll need to fetch it using the Row method B<get_column>.
291 print $sum_prices_rs->single->get_column('sum_amount');
293 =head2 SELECT from JOINed tables
295 SELECT users.id, username, posts.id, posts.title
297 JOIN posts posts ON posts.used_id = users.id
299 To select data from other tables, use the B<join> attribute to name the table relationships to create a JOIN clause to.
303 =item 1. Create a Schema object representing the database you are working with:
305 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
307 =item 2. Call the B<search> method on the resultset of the L<ResultSource|DBIx::Class::ResultSource> you wish to group data on:
309 my $posts_count_per_user = $schema->resultset('User')->search(
311 { columns => [ qw/id username posts.id posts.title/ ],
318 Here "posts" refers to the name of the L<Relationship|DBIx::Class::Relationship> between the "User" source and the "Post" source.
320 To retrieve the extra data, call the usual relationship accessor:
322 while( my $row = $sorted_users->next) {
323 print "user/post: ", $row->username;
324 print $_->title for $row->posts;
329 =head2 SELECT with GROUP BY
331 SELECT users.id, username, COUNT(posts.id)
333 JOIN posts posts ON posts.used_id = users.id
334 GROUP BY users.id, username;
336 To group your results, use the B<group_by> attribute on a B<search> method. We also use the B<columns> attribute to select and name a subset of columns.
340 =item 1. Create a Schema object representing the database you are working with:
342 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
344 =item 2. Call the *search* method on the resultset of the L<ResultSource|DBIx::Class::ResultSource> you wish to group data on:
346 my $posts_count_per_user = $schema->resultset('User')->search(
348 { columns => [ qw/id username/, { post_count => { count => 'posts.id' } } ],
350 group_by => [qw/id username/],
356 Here "posts" refers to the name of the L<Relationship|DBIx::Class::Relationship> between the "User" source and the "Post" source.
358 The results will contain two columns with the usual accessors, "id" and "username", and one with no accessor, as it is a virtual column.
360 while( my $row = $posts_count_per_user->next) {
361 print "user: ", $row->username, " posts: ", $row->get_column('post_count');
364 Note: Remember to disambiguate the columns when joining two tables with identical column names.
366 =head2 SELECT with simple ORDER BY
368 SELECT users.id, username, dob, realname, password, posts.title
370 JOIN posts posts ON posts.used_id = users.id
371 ORDER BY username, posts.title;
373 To sort the results, use the B<order_by> attributes on a B<search> method. Content can of course be ordered by columns in the current table, or in a joined table
377 =item 1. Create a Schema object representing the database you are working with:
379 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
381 =item 2. Call the B<search> method on the resultset of the L<ResultSource|DBIx::Class::ResultSource> you wish to sort data on:
383 # this will not collapse results (you will get users * (amount of posts || 1) as a result, sure you want to showcase this?
384 my $sorted_users = $schema->resultset('User')->search(
386 { '+columns' => [ qw/posts.id posts.title/ ],
388 order_by => [qw/username posts.title/],
394 Here "posts" refers to the name of the L<Relationship|DBIx::Class::Relationship> between the "User" source and the "Post" source.
396 The results will be ordered by username, then post title, ready for outputting.
398 Note how we have added the title of each post, this prevents us having to fire off a second query to fetch the post data to output it. The B<+columns> attribute specifies an extended set of columns to fetch, in addition to the columns of the main query table.
400 To retrieve the extra data, call the usual relationship accessor:
402 while( my $row = $sorted_users->next) {
403 print "user/post: ", $row->username;
404 print $_->title for $row->posts;
408 =head2 SELECT with HAVING
410 SELECT users.id, username, dob
412 JOIN posts posts ON posts.used_id = users.id
413 GROUP BY users.id, username, dob
414 HAVING count(posts.id) = 1
416 To add a B<having> clause to your query, use the corresponding B<having> attribute.
420 =item 1. Create a Schema object representing the database you are working with:
422 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
424 =item 2. Call the B<search> method on the resultset of the L<ResultSource|DBIx::Class::ResultSource> you wish to filter data on:
426 my $filtered_users = $schema->resultset('User')->search(
428 { 'columns' => [ qw/me.id me.username me.dob/ ],
430 group_by => [qw/me.id me.username me.dob/],
431 having => [{ 'posts.id' => 1 }],
437 Here "posts" refers to the name of the L<Relationship|DBIx::Class::Relationship> between the "User" source and the "Post" source.
439 The results will be filtered by the HAVING clause.
441 =head2 SELECT with DISTINCT
443 SELECT DISTINCT(posts.title)
446 To produce DISTINCT clauses, we need to use a hashref argument to the list of items passed to the B<columns> attribute.
450 =item 1. Create a Schema object representing the database you are working with:
452 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
454 =item 2. Call the B<search> method on the resultset of the L<ResultSource|DBIx::Class::ResultSource> you wish to find distinct rows on:
456 my $distinct_posts = $schema->resultset('Post')->search(
458 { columns => [{ 'd_title' => { distinct => 'me.title' } }],
464 This can also be achieved by using the ResultSet method B<get_column>. The method returns a ResultSetColumn object based on the given column name argument, which can call SQL aggregate functions based upon the column of that data.
466 So we can also do this, for single column DISTINCT clauses:
470 =item 1. Create a Schema object representing the database you are working with:
472 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
474 =item 2. Call the B<get_column> method on the resultset of the L<ResultSource|DBIx::Class::ResultSource> you wish to find distinct rows on:
476 my $rs_column = $schema->resultset('Post')->get_column('title');
478 =item 3. Call the B<func> method on the resultset column object and pass it the name of the function to apply:
480 my $titles = $rs_column->func('distinct');
484 The result will be an arrayref of the actual values. If a ResultSet object is needed for further refinement, use B<func_rs> instead.
486 =head2 SELECT ... FOR UPDATE
488 SELECT users.id, users.username, users.dob
492 To fetch data and lock it for updating from other transactions, use the B<for> attribute and pass it the value B<update>. This should be done inside a L<Transaction|DBIx::Class::Manual::SQLHackers::Transaction>.
496 =item 1. Create a Schema object representing the database you are working with:
498 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
500 =item 2. Call the B<search> method on the resultset of the L<ResultSource|DBIx::Class::ResultSource> you wish to lock data on:
502 my $locked_posts = $schema->resultset('User')->search(
504 { columns => [qw/me.id me.username me.dob/],
511 The resultset and rows will be returned as normal, and can be used to update the rows without worrying about other
513 =head2 SELECT with LIMIT and OFFSET
515 SELECT users.id, users.username
517 ORDER BY user.dob DESC
520 To reduce the set of rows fetched, use the B<rows> and B<page> attributes. The value of B<page> will default to 1, which means no OFFSET will be applied.
524 =item 1. Create a Schema object representing the database you are working with:
526 my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db');
528 =item 2. Call the B<search> method on the resultset of the L<ResultSource|DBIx::Class::ResultSource> you wish to limit data on:
530 my $limited_posts = $schema->resultset('User')->search(
532 { columns => [qw/me.id me.username/],
533 order_by => { '-desc' => ['user.dob'] },
539 This will return exactly 10 row objects, sorted by descending date of birth of the users, starting at the 11th row of the sorted result.