A Batch Query enables you to request queries with long-running CPU processing times. Typically, these kind of requests raise timeout errors when using the SQL API. In order to avoid timeouts, you can use Batch Queries to [create](#create-a-job), [read](#read-a-job), [list](#list-jobs), [update](#update-a-job) and [cancel](#cancel-a-job) queries. You can also run a [chained batch query](#chaining-batch-queries) to chain several SQL queries into one job. A Batch Query schedules the incoming jobs and allows you to request the job status for each query.
_Batch Queries are not intended to be used for large query payloads that contain over 8192 characters (8kb). For instance, if you are inserting a large number of rows into your table, you still need to use the [Import API](https://carto.com/docs/carto-engine/import-api/) or [SQL API](https://carto.com/docs/carto-engine/sql-api/) for this type of data management. Batch Queries are specific to queries and CPU usage._
An API Key is required to manage your jobs. The following error message appears if you are not [authenticated](https://carto.com/docs/carto-engine/sql-api/authentication/):
A Batch Query request to your CARTO account includes the following job schema elements. _Only the `query` element can be modified._ All other elements of the job schema are defined by the Batch Query and are read-only.
`query` | the SQL statement to be executed in a database. _You can modify the select SQL statement to be used in the job schema._<br/><br/>**Tip:** In some scenarios, you may need to retrieve the query results from a finished job. See [Fetching Job Results](#fetching-job-results) for details.
"query": "CREATE TABLE world_airports AS SELECT a.cartodb_id, a.the_geom, a.the_geom_webmercator, a.name airport, b.name country FROM world_borders b JOIN airports a ON ST_Contains(b.the_geom, a.the_geom)"
query: "CREATE TABLE world_airports AS SELECT a.cartodb_id, a.the_geom, a.the_geom_webmercator, a.name airport, b.name country FROM world_borders b JOIN airports a ON ST_Contains(b.the_geom, a.the_geom)"
"query": "CREATE TABLE world_airports AS SELECT a.cartodb_id, a.the_geom, a.the_geom_webmercator, a.name airport, b.name country FROM world_borders b JOIN airports a ON ST_Contains(b.the_geom, a.the_geom)",
**Note:** Jobs can only be updated while the `status: "pending"`, otherwise the Batch Query update operation is not allowed. You will receive an error if the job status is anything but "pending".
**Note:** Jobs can only be canceled while the `status: "running"` or `status: "pending"`, otherwise the Batch Query operation is not allowed. You will receive an error if the job status is anything but "running" or "pending".
In some cases, you may need to chain queries into one job. The Chaining Batch Query option enables you run an array of SQL statements, and define the order in which the queries are executed. You can use any of the operations (create, read, list, update, cancel) for the queries in a chained batch query.
"CREATE TABLE world_airports AS SELECT a.cartodb_id, a.the_geom, a.the_geom_webmercator, a.name airport, b.name country FROM world_borders b JOIN airports a ON ST_Contains(b.the_geom, a.the_geom)",
"query": "CREATE TABLE world_airports AS SELECT a.cartodb_id, a.the_geom, a.the_geom_webmercator, a.name airport, b.name country FROM world_borders b JOIN airports a ON ST_Contains(b.the_geom, a.the_geom)",
**Note:** The Batch Query returns a job status for both the parent Chained Batch Query request, and for each child query within the request. The order in which each query is executed is guaranteed. Here are the possible status results for Chained Batch Queries:
- If one query within the Chained Batch Query fails, the `"status": "failed"` is returned for both the job and the query, and any "pending" queries will not be processed
- If you cancel the Chained Batch Query job, the job status changes to `"status": "cancelled"`. Any running queries within the job will be stopped and changed to `"status": "pending"`, and will not be processed
- Suppose the first query job status is `"status": "done"`, the second query is `"status": "running"`, and the third query `"status": "pending"`. If the second query fails for some reason, the job status changes to `"status": "failed"` and the last query will not be processed. It is indicated which query failed in the Chained Batch Query job
"CREATE TABLE world_airports AS SELECT a.cartodb_id, a.the_geom, a.the_geom_webmercator, a.name airport, b.name country FROM world_borders b JOIN airports a ON ST_Contains(b.the_geom, a.the_geom)",
"CREATE TABLE world_airports AS SELECT a.cartodb_id, a.the_geom, a.the_geom_webmercator, a.name airport, b.name country FROM world_borders b JOIN airports a ON ST_Contains(b.the_geom, a.the_geom)",
"CREATE TABLE world_airports AS SELECT a.cartodb_id, a.the_geom, a.the_geom_webmercator, a.name airport, b.name country FROM world_borders b JOIN airports a ON ST_Contains(b.the_geom, a.the_geom)",
"CREATE TABLE world_airports AS SELECT a.cartodb_id, a.the_geom, a.the_geom_webmercator, a.name airport, b.name country FROM world_borders b JOIN airports a ON ST_Contains(b.the_geom, a.the_geom)",
Batch Queries enables you to define `onerror` and `onsuccess` fallbacks when you need to run an extra query depending on how a _chaining query_ finishes. This feature is powerful and opens a huge range of possibilities, for instance, you can create jobs periodically in order to get updated your data and you want to have a place where you can check quickly if your tables are updated or not and when was the last time that your table was updated. You may want to create a the following job:
```bash
curl -X POST -H "Content-Type: application/json" -d '{
"query": {
"query": [{
"query": "UPDATE nasdaq SET price = '100.00' WHERE company = 'CARTO'",
"onsuccess": "UPDATE market_registry SET status = 'updated', updated_at = NOW() WHERE table_name = 'nasdaq_index'"
"onerror": "UPDATE market_registry SET status = 'outdated' WHERE table_name = 'nasdaq_index'"
}]
}
}' "http://{username}.carto.com/api/v2/sql/job"
```
If `query` finishes successfully then `onsuccess` fallback is fired otherwise `onerror` will be fired. You can define fallbacks per query:
```bash
curl -X POST -H "Content-Type: application/json" -d '{
"query": {
"query": [{
"query": "UPDATE nasdaq SET price = '100.00' WHERE company = 'Esri'",
"onsuccess": "UPDATE market_status SET status = 'updated', updated_at = NOW() WHERE table_name = 'nasdaq'",
"onerror": "UPDATE market_status SET status = 'outdated' WHERE table_name = 'nasdaq'"
}, {
"query": "UPDATE down_jones SET price = '101.00' WHERE company = 'CARTO'",
"onsuccess": "UPDATE market_status SET status = 'updated', updated_at = NOW() WHERE table_name = 'down_jones'",
"onerror": "UPDATE market_status SET status = 'outdated' WHERE table_name = 'down_jones'"
}]
}
}' "http://{username}.carto.com/api/v2/sql/job"
```
Also, you can define fallbacks at job level:
```bash
curl -X POST -H "Content-Type: application/json" -d '{
"query": {
"query": [{
"query": "UPDATE down_jones SET price = '100.00' WHERE company = 'Esri'"
}, {
"query": "UPDATE nasdaq SET price = '101.00' WHERE company = 'CARTO'"
}],
"onsuccess": "UPDATE market_status SET status = 'ok', updated_at = NOW()",
"onerror": "UPDATE market_status SET status = 'outdated'"
}
}' "http://{username}.carto.com/api/v2/sql/job"
```
If a `query` of a job fails and `onerror` fallbacks for that query and job are defined then Batch Queries runs first the fallback for that query, then runs the fallback for the job and finally sets the job as failed, remaining queries won't be executed. Furthermore, Batch Queries will run the `onsuccess` fallback at job level if and only if every query of that job has finished successfully.
### Templates
Batch Queries provides a flexible way to get the `error message` and the `job identifier` to be used in your fallbacks using a the following templates:
-`<%= error_message %>`: will be replaced by the error message that the database provides.
-`<%= job_id %>`: will be replaced by the job identifier that Batch Queries provides.
This is helpful when you want to save into a table the error thrown by any query:
```bash
curl -X POST -H "Content-Type: application/json" -d '{
"query": {
"query": [{
"query": "UPDATE wrong_table SET price = '100.00' WHERE company = 'CARTO'"
In some scenarios, you may need to fetch the output of a job. If that is the case, wrap the query with `SELECT * INTO`, or `CREATE TABLE AS`. The output is stored in a new table in your database. For example, if using the query `SELECT * FROM airports`:
**Note:** If you need to create a map or analysis with the new table, use the [CDB_CartodbfyTable function](https://github.com/CartoDB/cartodb-postgresql/blob/master/doc/cartodbfy-requirements.rst).
- Batch Queries are not intended for large query payloads (e.g: inserting thousands of rows), use the [Import API](https://carto.com/docs/carto-engine/import-api/) for this type of data management
- Have in mind that creating several jobs not guarantees that jobs are going to be executed in the same order that were created. If you need run queries in a specific order you may want use [Chaining Batch Queries](https://carto.com/docs/carto-engine/sql-api/batch-queries/#chaining-batch-queries).