Improve docs for insert-multi! / execute-batch!

Call out the caveats more clearly. Note that Oracle doesn't support the 
`insert-multi!` syntax(!).
This commit is contained in:
Sean Corfield 2019-08-22 13:09:07 -07:00
parent 9a76e4c25a
commit f95467a34c
4 changed files with 19 additions and 4 deletions

View file

@ -53,7 +53,11 @@ Given a table name (as a keyword), a vector of column names, and a vector of row
Note: this expands to a single SQL statement with placeholders for every
value being inserted -- for large sets of rows, this may exceed the limits
on SQL string size and/or number of parameters for your JDBC driver or your
database! You should look at [`next.jdbc.prepare/execute-batch!'](https://cljdoc.org/d/seancorfield/next.jdbc/CURRENT/api/next.jdbc.prepare#execute-batch!) for an alternative approach.
database. Several databases have a limit of 1,000 parameter placeholders.
Oracle does not support this form of multi-row insert, requiring a different
syntax altogether.
You should look at [`next.jdbc.prepare/execute-batch!'](https://cljdoc.org/d/seancorfield/next.jdbc/CURRENT/api/next.jdbc.prepare#execute-batch!) for an alternative approach.
## `query`

View file

@ -95,6 +95,8 @@ Both of those are somewhat ugly and contain a fair bit of boilerplate and Java i
By default, this adds all the parameter groups and executes one batched command. It returns a (Clojure) vector of update counts (rather than `int[]`). If you provide an options hash map, you can specify a `:batch-size` and the parameter groups will be partitioned and executed as multiple batched commands. This is intended to allow very large sequences of parameter groups to be executed without running into limitations that may apply to a single batched command. If you expect the update counts to be very large (more than `Integer/MAX_VALUE`), you can specify `:large true` so that `.executeLargeBatch` is called instead of `.executeBatch`. Note: not all databases support `.executeLargeBatch`.
### Caveats
There are several caveats around using batched parameters. Some JDBC drivers need a "hint" in order to perform the batch operation as a single command for the database. In particular, PostgreSQL requires the `:reWriteBatchedInserts true` option and MySQL requires `:rewriteBatchedStatement true` (both non-standard JDBC options, of course!). These should be provided as part of the db-spec hash map when the datasource is created.
In addition, if the batch operation fails for a group of parameters, it is database-specific whether the remaining groups of parameters are used, i.e., whether the operation is performed for any further groups of parameters after the one that failed. The result of calling `execute-batch!` is a vector of integers. Each element of the vector is the number of rows affected by the operation for each group of parameters. `execute-batch!` may throw a `BatchUpdateException` and calling `.getUpdateCounts` (or `.getLargeUpdateCounts`) on the exception may return an array containing a mix of update counts and error values (a Java `int[]` or `long[]`). Some databases don't always return an update count but instead a value indicating the number of rows is not known (but sometimes you can still get the update counts).

View file

@ -9,6 +9,10 @@
* `PreparedStatement` -- SQL and parameters combined, from a connection,
and the following functions and a macro:
* `get-datasource` -- given a hash map describing a database or a JDBC
connection string, construct a `javax.sql.DataSource` and return it,
* `get-connection` -- given a connectable, obtain a new `java.sql.Connection`
from it and return that,
* `plan` -- given a connectable and SQL + parameters or a statement,
return a reducible that, when reduced will execute the SQL and consume
the `ResultSet` produced,

View file

@ -140,8 +140,8 @@
(defn execute-batch!
"Given a `PreparedStatement` and a vector containing parameter groups,
i.e., a vector of vector of parameters, use `.addBatch` to add each group
of parameters to the prepared statement and then call `.executeBatch`.
A vector of update counts is returned.
of parameters to the prepared statement (via `set-parameters`) and then
call `.executeBatch`. A vector of update counts is returned.
An options hash map may also be provided, containing `:batch-size` which
determines how to partition the parameter groups for submission to the
@ -154,7 +154,12 @@
May throw `java.sql.BatchUpdateException` if any part of the batch fails.
You may be able to call `.getUpdateCounts` on that exception object to
get more information about which parts succeeded and which failed."
get more information about which parts succeeded and which failed.
For additional caveats and database-specific options you may need, see:
https://cljdoc.org/d/seancorfield/next.jdbc/CURRENT/doc/getting-started/prepared-statements#caveats
Not all databases support batch execution."
([ps param-groups]
(execute-batch! ps param-groups {}))
([^PreparedStatement ps param-groups opts]