Added some sections to the manual
This commit is contained in:
parent
5d6eea5bde
commit
332f2df64d
@ -16,13 +16,6 @@ body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
height: 5px;
|
||||
color: #000;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: 'Georgia',Serif;
|
||||
font-weight: normal;
|
||||
|
||||
@ -83,9 +83,8 @@
|
||||
</div>
|
||||
|
||||
<div id="footer">
|
||||
<p>jOOQ is brought to you by <a href="http://lukaseder.wordpress.com" title="Lukas's Blog about Java, SQL, and jOOQ">Lukas Eder</a>.
|
||||
<p class="right">jOOQ is brought to you by <a href="http://lukaseder.wordpress.com" title="Lukas's Blog about Java, SQL, and jOOQ">Lukas Eder</a>.
|
||||
Distributed under the <a href="http://www.apache.org/licenses/LICENSE-2.0" title="Apache 2 License">Apache 2 licence</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -7,7 +7,12 @@ function printH1() {
|
||||
print "Complete SELECT syntax";
|
||||
}
|
||||
function getSlogan() {
|
||||
return "";
|
||||
return "
|
||||
A SELECT statement is more than just the R in CRUD. It allows for
|
||||
transforming your relational data into any other form using concepts
|
||||
such as equi-join, semi-join, anti-join, outer-join and much more. jOOQ
|
||||
helps you think in precisely those relational concepts.
|
||||
";
|
||||
}
|
||||
function printContent() {
|
||||
global $root;
|
||||
@ -16,7 +21,271 @@ function printContent() {
|
||||
<tr>
|
||||
<td align="left" valign="top"><a href="<?=$root?>/manual/">The jOOQ User Manual</a> : <a href="<?=$root?>/manual/DSL/">DSL or fluent API. Where SQL meets Java</a> : <a href="<?=$root?>/manual/DSL/SELECT/">Complete SELECT syntax</a></td><td align="right" valign="top" style="white-space: nowrap"><a href="<?=$root?>/manual/DSL/" title="Previous section: DSL or fluent API. Where SQL meets Java">previous</a> : <a href="<?=$root?>/manual/DSL/CONDITION/" title="Next section: Conditions">next</a></td>
|
||||
</tr>
|
||||
</table><br><table cellpadding="0" cellspacing="0" border="0" width="100%">
|
||||
</table>
|
||||
<h2>SELECT from anonymous or ad-hoc types</h2>
|
||||
<p>When you don't just perform CRUD (i.e. SELECT * FROM your_table WHERE ID = ?),
|
||||
you're usually generating new types using custom projections. With jOOQ, this is
|
||||
as intuitive, as if using SQL directly. A more or less complete example of the "standard" SQL syntax, plus
|
||||
some extensions, is provided by a query like this:
|
||||
</p>
|
||||
|
||||
<pre class="prettyprint lang-sql">
|
||||
-- get all authors' first and last names, and the number
|
||||
-- of books they've written in German, if they have written
|
||||
-- more than five books in German in the last three years
|
||||
-- (from 2011), and sort those authors by last names
|
||||
-- limiting results to the second and third row, locking
|
||||
-- the rows for a subsequent update... whew!
|
||||
|
||||
SELECT T_AUTHOR.FIRST_NAME, T_AUTHOR.LAST_NAME, COUNT(*)
|
||||
FROM T_AUTHOR
|
||||
JOIN T_BOOK ON T_AUTHOR.ID = T_BOOK.AUTHOR_ID
|
||||
WHERE T_BOOK.LANGUAGE = 'DE'
|
||||
AND T_BOOK.PUBLISHED > '2008-01-01'
|
||||
GROUP BY T_AUTHOR.FIRST_NAME, T_AUTHOR.LAST_NAME
|
||||
HAVING COUNT(*) > 5
|
||||
ORDER BY T_AUTHOR.LAST_NAME ASC NULLS FIRST
|
||||
LIMIT 2
|
||||
OFFSET 1
|
||||
FOR UPDATE</pre>
|
||||
|
||||
<p>So that's daily business. How to do it with jOOQ: When you first create a SELECT statement using the Factory's select() methods </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectFromStep select(Field<?>... fields);
|
||||
|
||||
// Example:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count());</pre>
|
||||
|
||||
<p>
|
||||
jOOQ will return an "intermediary" type to you, representing the
|
||||
SELECT statement about to be created (by the way, check out the
|
||||
section on <a href="<?=$root?>/manual/DSL/FUNCTIONS/" title="jOOQ Manual reference: Functions, aggregate operators, and window functions">aggregate operators</a>
|
||||
to learn more about the COUNT(*)
|
||||
function). This type is the
|
||||
<a href="https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/SelectFromStep.java" title="Internal API reference: org.jooq.SelectFromStep">org.jooq.SelectFromStep</a>.
|
||||
When you have a reference
|
||||
to this type, you may add a FROM clause, although that clause is
|
||||
optional. This is reflected by the fact, that the SelectFromStep type
|
||||
extends
|
||||
<a href="https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/SelectJoinStep.java" title="Internal API reference: org.jooq.SelectJoinStep">org.jooq.SelectJoinStep</a>,
|
||||
which allows for adding the subsequent
|
||||
clauses. Let's say you do decide to add a FROM clause, then you can
|
||||
use this method for instance:
|
||||
</p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectJoinStep from(TableLike<?>... table);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR);</pre>
|
||||
|
||||
<p>After adding the table-like structures (mostly just Tables) to
|
||||
select from, you may optionally choose to add a JOIN clause, as the
|
||||
type returned by jOOQ is the step where you can add JOINs. Again,
|
||||
adding these clauses is optional, as the
|
||||
<a href="https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/SelectJoinStep.java" title="Internal API reference: org.jooq.SelectJoinStep">org.jooq.SelectJoinStep</a> extends
|
||||
<a href="https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/SelectWhereStep.java" title="Internal API reference: org.jooq.SelectWhereStep">org.jooq.SelectWhereStep</a>.
|
||||
But let's say we add a JOIN: </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
// These join types are supported
|
||||
SelectOnStep join(Table<?> table);
|
||||
SelectOnStep leftOuterJoin(Table<?> table);
|
||||
SelectOnStep rightOuterJoin(Table<?> table);
|
||||
SelectOnStep fullOuterJoin(Table<?> table);
|
||||
SelectJoinStep crossJoin(Table<?> table);
|
||||
SelectJoinStep naturalJoin(Table<?> table);
|
||||
SelectJoinStep naturalLeftOuterJoin(Table<?> table);
|
||||
SelectJoinStep naturalRightOuterJoin(Table<?> table);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK);</pre>
|
||||
|
||||
<p>Now, if you do add a JOIN clause, you have to specify the JOIN .. ON
|
||||
condition before you can add more clauses. That's not an optional step
|
||||
for some JOIN types. This is reflected by the fact that
|
||||
<a href="https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/SelectOnStep.java" title="Internal API reference: org.jooq.SelectOnStep">org.jooq.SelectOnStep</a>
|
||||
is a top-level interface. </p>
|
||||
|
||||
<pre class="prettyprint lang-java">
|
||||
// These join conditions are supported
|
||||
SelectJoinStep on(Condition... conditions);
|
||||
SelectJoinStep using(Field<?>... fields);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID));</pre>
|
||||
|
||||
<p>See the section about
|
||||
<a href="<?=$root?>/manual/DSL/CONDITION/" title="jOOQ Manual reference: Conditions">Conditions</a>
|
||||
to learn more about the many ways
|
||||
to create Conditions in jOOQ. Now we're half way through. As you can
|
||||
see above, we're back to the SelectJoinStep. This means, we can
|
||||
re-iterate and add another JOIN clause, just like in SQL. Or we go on
|
||||
to the next step, adding conditions in the
|
||||
<a href="https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/SelectWhereStep.java" title="Internal API reference: org.jooq.SelectWhereStep">org.jooq.SelectWhereStep</a>: </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectConditionStep where(Condition... conditions);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"));</pre>
|
||||
|
||||
<p>Now the returned type
|
||||
<a href="https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/SelectConditionStep.java" title="Internal API reference: org.jooq.SelectConditionStep">org.jooq.SelectConditionStep</a> is a special one, where
|
||||
you can add more conditions to the already existing WHERE clause.
|
||||
Every time you add a condition, you will return to that
|
||||
SelectConditionStep, as the number of additional conditions is
|
||||
unlimited. Note that of course you can also just add a single combined
|
||||
condition, if that is more readable or suitable for your use-case.
|
||||
Here's how we add another condition: </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectConditionStep and(Condition condition);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')));</pre>
|
||||
|
||||
<p>Let's assume we have that method parseDate() creating a
|
||||
<a href="http://download.oracle.com/javase/6/docs/api/java/sql/Date.html" title="External API reference: java.sql.Date">java.sql.Date</a> for us.
|
||||
Then we'll continue adding the GROUP BY clause
|
||||
</p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectHavingStep groupBy(Field<?>... fields);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
|
||||
.groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME);</pre>
|
||||
|
||||
<p>and the HAVING clause: </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectOrderByStep having(Condition... conditions);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
|
||||
.groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
|
||||
.having(create.count().greaterThan(5));</pre>
|
||||
|
||||
<p>and the ORDER BY clause. Some RDBMS support NULLS FIRST and NULLS
|
||||
LAST extensions to the ORDER BY clause. If this is not supported by
|
||||
the RDBMS, then the behaviour is simulated with an additional CASE
|
||||
WHEN ... IS NULL THEN 1 ELSE 0 END clause. </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectLimitStep orderBy(Field<?>... fields);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
|
||||
.groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
|
||||
.having(create.count().greaterThan(5))
|
||||
.orderBy(TAuthor.LAST_NAME.asc().nullsFirst());</pre>
|
||||
|
||||
<p>and finally the LIMIT clause. Most dialects have a means of limiting
|
||||
the number of result records (except Oracle). Some even support having
|
||||
an OFFSET to the LIMIT clause. Even if your RDBMS does not support the
|
||||
full LIMIT ... OFFSET ... clause, jOOQ
|
||||
will simulate the LIMIT clause using nested selects and filtering on
|
||||
ROWNUM (for Oracle), or on ROW_NUMBER() (for DB2 and SQL
|
||||
Server): </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectFinalStep limit(int offset, int numberOfRows);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
|
||||
.groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
|
||||
.having(create.count().greaterThan(5))
|
||||
.orderBy(TAuthor.LAST_NAME.asc().nullsFirst())
|
||||
.limit(1, 2);</pre>
|
||||
|
||||
<p>In the final step, there are some proprietary extensions available
|
||||
only in some RDBMS. One of those extensions are the FOR UPDATE
|
||||
(supported in most RDBMS) and FOR SHARE clauses (supported only in
|
||||
MySQL and Postgres): </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectFinalStep forUpdate();
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
|
||||
.groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
|
||||
.having(create.count().greaterThan(5))
|
||||
.orderBy(TAuthor.LAST_NAME.asc().nullsFirst())
|
||||
.limit(1, 2)
|
||||
.forUpdate();</pre>
|
||||
|
||||
<p>
|
||||
Now the most relevant super-type of the object we have just created is
|
||||
<a href="https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/Select.java" title="Internal API reference: org.jooq.Select">org.jooq.Select</a><Record>.
|
||||
This type can be reused in various expressions such as in the
|
||||
<a href="<?=$root?>/manual/DSL/UNION/" title="jOOQ Manual reference: UNION and other set operations">UNION and other set operations</a>,
|
||||
<a href="<?=$root?>/manual/DSL/EXISTS/" title="jOOQ Manual reference: Nested select statements using the EXISTS operator">Nested select statements using the EXISTS operator</a>,
|
||||
etc. If you just want to execute this select
|
||||
statement, you can choose any of these methods as discussed in the
|
||||
section about the <a href="<?=$root?>/manual/JOOQ/ResultQuery/" title="jOOQ Manual reference: ResultQuery and various ways of fetching data">ResultQuery</a>:
|
||||
</p>
|
||||
|
||||
<pre class="prettyprint lang-java">
|
||||
// Just execute the query.
|
||||
int execute() throws SQLException;
|
||||
|
||||
// Execute the query and retrieve the results
|
||||
Result<Record> fetch() throws SQLException;
|
||||
|
||||
// Execute the query and retrieve the first Record
|
||||
Record fetchAny() throws SQLException;
|
||||
|
||||
// Execute the query and retrieve the single Record
|
||||
// An Exception is thrown if more records were available
|
||||
Record fetchOne() throws SQLException;
|
||||
|
||||
// [...]</pre>
|
||||
|
||||
|
||||
<h2>SELECT from single physical tables</h2>
|
||||
<p>A very similar API is available, if you want to select from single
|
||||
physical tables in order to retrieve TableRecords or even
|
||||
UpdatableRecords (see also the manual's section on
|
||||
<a href="<?=$root?>/manual/JOOQ/Query/" title="jOOQ Manual reference: The Query and its various subtypes">SelectQuery vs SimpleSelectQuery</a>).
|
||||
The decision, which type of select to create is
|
||||
already made at the very first step, when you create the SELECT
|
||||
statement with the Factory: </p>
|
||||
|
||||
<pre class="prettyprint lang-java">public <R extends Record> SimpleSelectWhereStep<R> selectFrom(Table<R> table);</pre>
|
||||
<p>As you can see, there is no way to further restrict/project the selected
|
||||
fields. This just selects all known TableFields in the supplied Table,
|
||||
and it also binds <R extends Record> to your Table's associated
|
||||
Record. An example of such a Query would then be: </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
TBook book = create.selectFrom(T_BOOK)
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.orderBy(TBook.TITLE)
|
||||
.fetchAny();</pre>
|
||||
<br><table cellpadding="0" cellspacing="0" border="0" width="100%">
|
||||
<tr>
|
||||
<td align="left" valign="top"><a href="<?=$root?>/manual/">The jOOQ User Manual</a> : <a href="<?=$root?>/manual/DSL/">DSL or fluent API. Where SQL meets Java</a> : <a href="<?=$root?>/manual/DSL/SELECT/">Complete SELECT syntax</a></td><td align="right" valign="top" style="white-space: nowrap"><a href="<?=$root?>/manual/DSL/" title="Previous section: DSL or fluent API. Where SQL meets Java">previous</a> : <a href="<?=$root?>/manual/DSL/CONDITION/" title="Next section: Conditions">next</a></td>
|
||||
</tr>
|
||||
|
||||
@ -2060,40 +2060,335 @@ create.select()
|
||||
<sections>
|
||||
<section id="SELECT">
|
||||
<title>Complete SELECT syntax</title>
|
||||
<slogan>
|
||||
A SELECT statement is more than just the R in CRUD. It allows for
|
||||
transforming your relational data into any other form using concepts
|
||||
such as equi-join, semi-join, anti-join, outer-join and much more. jOOQ
|
||||
helps you think in precisely those relational concepts.
|
||||
</slogan>
|
||||
<content>
|
||||
<h2>SELECT from anonymous or ad-hoc types</h2>
|
||||
<p>When you don't just perform CRUD (i.e. SELECT * FROM your_table WHERE ID = ?),
|
||||
you're usually generating new types using custom projections. With jOOQ, this is
|
||||
as intuitive, as if using SQL directly. A more or less complete example of the "standard" SQL syntax, plus
|
||||
some extensions, is provided by a query like this:
|
||||
</p>
|
||||
|
||||
<pre class="prettyprint lang-sql">
|
||||
-- get all authors' first and last names, and the number
|
||||
-- of books they've written in German, if they have written
|
||||
-- more than five books in German in the last three years
|
||||
-- (from 2011), and sort those authors by last names
|
||||
-- limiting results to the second and third row, locking
|
||||
-- the rows for a subsequent update... whew!
|
||||
|
||||
SELECT T_AUTHOR.FIRST_NAME, T_AUTHOR.LAST_NAME, COUNT(*)
|
||||
FROM T_AUTHOR
|
||||
JOIN T_BOOK ON T_AUTHOR.ID = T_BOOK.AUTHOR_ID
|
||||
WHERE T_BOOK.LANGUAGE = 'DE'
|
||||
AND T_BOOK.PUBLISHED > '2008-01-01'
|
||||
GROUP BY T_AUTHOR.FIRST_NAME, T_AUTHOR.LAST_NAME
|
||||
HAVING COUNT(*) > 5
|
||||
ORDER BY T_AUTHOR.LAST_NAME ASC NULLS FIRST
|
||||
LIMIT 2
|
||||
OFFSET 1
|
||||
FOR UPDATE</pre>
|
||||
|
||||
<p>So that's daily business. How to do it with jOOQ: When you first create a SELECT statement using the Factory's select() methods </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectFromStep select(Field<?>... fields);
|
||||
|
||||
// Example:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count());</pre>
|
||||
|
||||
<p>
|
||||
jOOQ will return an "intermediary" type to you, representing the
|
||||
SELECT statement about to be created (by the way, check out the
|
||||
section on <reference id="FUNCTIONS" title="aggregate operators"/>
|
||||
to learn more about the COUNT(*)
|
||||
function). This type is the
|
||||
<reference class="org.jooq.SelectFromStep"/>.
|
||||
When you have a reference
|
||||
to this type, you may add a FROM clause, although that clause is
|
||||
optional. This is reflected by the fact, that the SelectFromStep type
|
||||
extends
|
||||
<reference class="org.jooq.SelectJoinStep"/>,
|
||||
which allows for adding the subsequent
|
||||
clauses. Let's say you do decide to add a FROM clause, then you can
|
||||
use this method for instance:
|
||||
</p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectJoinStep from(TableLike<?>... table);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR);</pre>
|
||||
|
||||
<p>After adding the table-like structures (mostly just Tables) to
|
||||
select from, you may optionally choose to add a JOIN clause, as the
|
||||
type returned by jOOQ is the step where you can add JOINs. Again,
|
||||
adding these clauses is optional, as the
|
||||
<reference class="org.jooq.SelectJoinStep"/> extends
|
||||
<reference class="org.jooq.SelectWhereStep"/>.
|
||||
But let's say we add a JOIN: </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
// These join types are supported
|
||||
SelectOnStep join(Table<?> table);
|
||||
SelectOnStep leftOuterJoin(Table<?> table);
|
||||
SelectOnStep rightOuterJoin(Table<?> table);
|
||||
SelectOnStep fullOuterJoin(Table<?> table);
|
||||
SelectJoinStep crossJoin(Table<?> table);
|
||||
SelectJoinStep naturalJoin(Table<?> table);
|
||||
SelectJoinStep naturalLeftOuterJoin(Table<?> table);
|
||||
SelectJoinStep naturalRightOuterJoin(Table<?> table);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK);</pre>
|
||||
|
||||
<p>Now, if you do add a JOIN clause, you have to specify the JOIN .. ON
|
||||
condition before you can add more clauses. That's not an optional step
|
||||
for some JOIN types. This is reflected by the fact that
|
||||
<reference class="org.jooq.SelectOnStep"/>
|
||||
is a top-level interface. </p>
|
||||
|
||||
<pre class="prettyprint lang-java">
|
||||
// These join conditions are supported
|
||||
SelectJoinStep on(Condition... conditions);
|
||||
SelectJoinStep using(Field<?>... fields);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID));</pre>
|
||||
|
||||
<p>See the section about
|
||||
<reference id="CONDITION" title="Conditions"/>
|
||||
to learn more about the many ways
|
||||
to create Conditions in jOOQ. Now we're half way through. As you can
|
||||
see above, we're back to the SelectJoinStep. This means, we can
|
||||
re-iterate and add another JOIN clause, just like in SQL. Or we go on
|
||||
to the next step, adding conditions in the
|
||||
<reference class="org.jooq.SelectWhereStep"/>: </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectConditionStep where(Condition... conditions);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"));</pre>
|
||||
|
||||
<p>Now the returned type
|
||||
<reference class="org.jooq.SelectConditionStep"/> is a special one, where
|
||||
you can add more conditions to the already existing WHERE clause.
|
||||
Every time you add a condition, you will return to that
|
||||
SelectConditionStep, as the number of additional conditions is
|
||||
unlimited. Note that of course you can also just add a single combined
|
||||
condition, if that is more readable or suitable for your use-case.
|
||||
Here's how we add another condition: </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectConditionStep and(Condition condition);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')));</pre>
|
||||
|
||||
<p>Let's assume we have that method parseDate() creating a
|
||||
<reference class="java.sql.Date"/> for us.
|
||||
Then we'll continue adding the GROUP BY clause
|
||||
</p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectHavingStep groupBy(Field<?>... fields);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
|
||||
.groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME);</pre>
|
||||
|
||||
<p>and the HAVING clause: </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectOrderByStep having(Condition... conditions);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
|
||||
.groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
|
||||
.having(create.count().greaterThan(5));</pre>
|
||||
|
||||
<p>and the ORDER BY clause. Some RDBMS support NULLS FIRST and NULLS
|
||||
LAST extensions to the ORDER BY clause. If this is not supported by
|
||||
the RDBMS, then the behaviour is simulated with an additional CASE
|
||||
WHEN ... IS NULL THEN 1 ELSE 0 END clause. </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectLimitStep orderBy(Field<?>... fields);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
|
||||
.groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
|
||||
.having(create.count().greaterThan(5))
|
||||
.orderBy(TAuthor.LAST_NAME.asc().nullsFirst());</pre>
|
||||
|
||||
<p>and finally the LIMIT clause. Most dialects have a means of limiting
|
||||
the number of result records (except Oracle). Some even support having
|
||||
an OFFSET to the LIMIT clause. Even if your RDBMS does not support the
|
||||
full LIMIT ... OFFSET ... clause, jOOQ
|
||||
will simulate the LIMIT clause using nested selects and filtering on
|
||||
ROWNUM (for Oracle), or on ROW_NUMBER() (for DB2 and SQL
|
||||
Server): </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectFinalStep limit(int offset, int numberOfRows);
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
|
||||
.groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
|
||||
.having(create.count().greaterThan(5))
|
||||
.orderBy(TAuthor.LAST_NAME.asc().nullsFirst())
|
||||
.limit(1, 2);</pre>
|
||||
|
||||
<p>In the final step, there are some proprietary extensions available
|
||||
only in some RDBMS. One of those extensions are the FOR UPDATE
|
||||
(supported in most RDBMS) and FOR SHARE clauses (supported only in
|
||||
MySQL and Postgres): </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
SelectFinalStep forUpdate();
|
||||
|
||||
// The example, continued:
|
||||
create.select(TAuthor.FIRST_NAME, TAuthor.LAST_NAME, create.count())
|
||||
.from(T_AUTHOR)
|
||||
.join(T_BOOK).on(TBook.AUTHOR_ID.equal(TAuthor.ID))
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.and(TBook.PUBLISHED.greaterThan(parseDate('2008-01-01')))
|
||||
.groupBy(TAuthor.FIRST_NAME, TAuthor.LAST_NAME)
|
||||
.having(create.count().greaterThan(5))
|
||||
.orderBy(TAuthor.LAST_NAME.asc().nullsFirst())
|
||||
.limit(1, 2)
|
||||
.forUpdate();</pre>
|
||||
|
||||
<p>
|
||||
Now the most relevant super-type of the object we have just created is
|
||||
<reference class="org.jooq.Select"/><Record>.
|
||||
This type can be reused in various expressions such as in the
|
||||
<reference id="UNION" title="UNION and other set operations"/>,
|
||||
<reference id="EXISTS" title="Nested select statements using the EXISTS operator"/>,
|
||||
etc. If you just want to execute this select
|
||||
statement, you can choose any of these methods as discussed in the
|
||||
section about the <reference id="ResultQuery" title="ResultQuery"/>:
|
||||
</p>
|
||||
|
||||
<pre class="prettyprint lang-java">
|
||||
// Just execute the query.
|
||||
int execute() throws SQLException;
|
||||
|
||||
// Execute the query and retrieve the results
|
||||
Result<Record> fetch() throws SQLException;
|
||||
|
||||
// Execute the query and retrieve the first Record
|
||||
Record fetchAny() throws SQLException;
|
||||
|
||||
// Execute the query and retrieve the single Record
|
||||
// An Exception is thrown if more records were available
|
||||
Record fetchOne() throws SQLException;
|
||||
|
||||
// [...]</pre>
|
||||
|
||||
|
||||
<h2>SELECT from single physical tables</h2>
|
||||
<p>A very similar API is available, if you want to select from single
|
||||
physical tables in order to retrieve TableRecords or even
|
||||
UpdatableRecords (see also the manual's section on
|
||||
<reference id="Query" title="SelectQuery vs SimpleSelectQuery"/>).
|
||||
The decision, which type of select to create is
|
||||
already made at the very first step, when you create the SELECT
|
||||
statement with the Factory: </p>
|
||||
|
||||
<pre class="prettyprint lang-java">public <R extends Record> SimpleSelectWhereStep<R> selectFrom(Table<R> table);</pre>
|
||||
<p>As you can see, there is no way to further restrict/project the selected
|
||||
fields. This just selects all known TableFields in the supplied Table,
|
||||
and it also binds <R extends Record> to your Table's associated
|
||||
Record. An example of such a Query would then be: </p>
|
||||
<pre class="prettyprint lang-java">
|
||||
TBook book = create.selectFrom(T_BOOK)
|
||||
.where(TBook.LANGUAGE.equal("DE"))
|
||||
.orderBy(TBook.TITLE)
|
||||
.fetchAny();</pre>
|
||||
</content>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="CONDITION">
|
||||
<title>Conditions</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="ALIAS">
|
||||
<title>Aliased tables and fields</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="IN">
|
||||
<title>Nested select statements using the IN operator</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="EXISTS">
|
||||
<title>Nested select statements using the EXISTS operator</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="NESTED">
|
||||
<title>Other types of nested selects</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="UNION">
|
||||
<title>UNION and other set operations</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="FUNCTIONS">
|
||||
<title>Functions, aggregate operators, and window functions</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="PROCEDURES">
|
||||
<title>Stored procedures and functions</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="ARITHMETIC">
|
||||
<title>Arithmetic operations</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="CASE">
|
||||
<title>The CASE clause</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="CAST">
|
||||
<title>Type casting</title>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="SQL">
|
||||
<title>When it's just much easier: Plain SQL</title>
|
||||
</section>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user