Skip to content

Commit ba5fbde

Browse files
committed
Cleaning up the structure by method hierarchy.
1 parent d3cdce6 commit ba5fbde

File tree

5 files changed

+284
-274
lines changed

5 files changed

+284
-274
lines changed

src/content/docs/d1/sql-api/sql-statements.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Details, Render } from "~/components";
99

1010
D1 is compatible with most SQLite's SQL convention since it leverages SQLite's query engine. D1 supports a number of database-level statements that allow you to list tables, indexes, and inspect the schema for a given table or index.
1111

12-
You can execute any of these statements via the D1 console in the Cloudflare dashboard, [`wrangler d1 execute`](/workers/wrangler/commands/#d1), or with the [D1 Worker Bindings API](/d1/worker-api/prepare-a-statement).
12+
You can execute any of these statements via the D1 console in the Cloudflare dashboard, [`wrangler d1 execute`](/workers/wrangler/commands/#d1), or with the [D1 Worker Bindings API](/d1/worker-api/d1-binding).
1313

1414
## Supported SQLite extensions
1515

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
---
2+
title: D1 binding
3+
pcx_content_type: concept
4+
sidebar:
5+
order: 1
6+
---
7+
8+
import { Type, MetaInfo, Details } from "~/components";
9+
10+
To interact with your D1 database from your Worker, you need to access it through the environment bindings provided to the Worker (`env`).
11+
12+
```js
13+
async fetch(request, env) {
14+
// D1 database is 'env.DB', where "DB" is the binding name from the Wrangler.toml file.
15+
}
16+
```
17+
18+
A D1 binding has the type `D1Database`, and supports a number of methods, as listed below.
19+
20+
## Methods
21+
22+
### `db.prepare()`
23+
24+
Prepares a query statement to be later executed.
25+
26+
```js
27+
const someVariable = `Bs Beverages`;
28+
const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(someVariable);
29+
```
30+
31+
#### Parameters
32+
33+
- <code>sqlQuery</code>: <Type text="String"/> <MetaInfo text="Required"/>
34+
- The SQL query you wish to execute on the database.
35+
36+
#### Return values
37+
38+
- None.
39+
40+
#### Guidance
41+
42+
- D1 follows the [SQLite convention](https://www.sqlite.org/lang_expr.html#varparam) for prepared statements parameter binding. Currently, D1 only supports Ordered (`?NNNN`) and Anonymous (`?`) parameters. In the future, D1 will support named parameters as well.
43+
44+
| Syntax | Type | Description |
45+
| ------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
46+
| `?NNN` | Ordered | A question mark followed by a number `NNN` holds a spot for the `NNN`-th parameter. `NNN` must be between `1` and `SQLITE_MAX_VARIABLE_NUMBER` |
47+
| `?` | Anonymous | A question mark that is not followed by a number creates a parameter with a number one greater than the largest parameter number already assigned. If this means the parameter number is greater than `SQLITE_MAX_VARIABLE_NUMBER`, it is an error. This parameter format is provided for compatibility with other database engines. But because it is easy to miscount the question marks, the use of this parameter format is discouraged. Programmers are encouraged to use one of the symbolic formats below or the `?NNN` format above instead. |
48+
49+
To bind a parameter, use the `stmt.bind()` method.
50+
51+
Order and anonymous examples:
52+
53+
```js
54+
const stmt = db.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind("");
55+
```
56+
57+
```js
58+
const stmt = db
59+
.prepare("SELECT * FROM Customers WHERE CompanyName = ? AND CustomerId = ?")
60+
.bind("Alfreds Futterkiste", 1);
61+
```
62+
63+
```js
64+
const stmt = db
65+
.prepare("SELECT * FROM Customers WHERE CompanyName = ?2 AND CustomerId = ?1")
66+
.bind(1, "Alfreds Futterkiste");
67+
```
68+
69+
#### Static statements
70+
71+
D1 API supports static statements. Static statements are SQL statements where the variables have been hard coded. When writing a static statement, you manually type the variable within the statement string.
72+
73+
:::note
74+
The recommended approach is to bind parameters to create a prepared statement (which are precompiled objects used by the database) to run the SQL. Prepared statements lead to faster overall execution and prevent SQL injection attacks.
75+
:::
76+
77+
Example of a prepared statement with dynamically bound value:
78+
79+
```js
80+
const someVariable = `Bs Beverages`;
81+
const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(someVariable);
82+
// A variable (someVariable) will replace the placeholder '?' in the query.
83+
// `stmt` is a prepared statement.
84+
```
85+
86+
Example of a static statement:
87+
88+
```js
89+
const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = Bs Beverages");
90+
// "Bs Beverages" is hard-coded into the query.
91+
// `stmt` is a static statement.
92+
```
93+
94+
### `db.batch()`
95+
96+
Sends multiple SQL statements inside a single call to the database. This can have a huge performance impact as it reduces latency from network round trips to D1. D1 operates in auto-commit. Our implementation guarantees that each statement in the list will execute and commit, sequentially, non-concurrently.
97+
98+
Batched statements are [SQL transactions](https://www.sqlite.org/lang_transaction.html). If a statement in the sequence fails, then an error is returned for that specific statement, and it aborts or rolls back the entire sequence.
99+
100+
To send batch statements, provide `.batch()` a list of prepared statements and get the results in the same order.
101+
102+
```js
103+
const companyName1 = `Bs Beverages`;
104+
const companyName2 = `Around the Horn`;
105+
const stmt = env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`);
106+
const batchResult = await env.DB.batch([
107+
stmt.bind(companyName1),
108+
stmt.bind(companyName2)
109+
]);
110+
```
111+
112+
#### Parameters
113+
114+
- <code>statements</code>: <Type text="Array"/>
115+
- An array of `db.prepare()` statements.
116+
117+
#### Return values
118+
119+
- <code>results</code>: <Type text="Array"/>
120+
- An array of `D1Result` objects containing the results of the `.db.prepare()` statements. Each object is in the array position corresponding to the array position of the initial `db.prepare()` statement within the `statementArray`.
121+
- Refer to [`D1Result`](/d1/worker-api/return-object/#d1result) for more information about this object.
122+
123+
<Details header="Example of return values" open={false}>
124+
125+
```js
126+
const companyName1 = `Bs Beverages`;
127+
const companyName2 = `Around the Horn`;
128+
const stmt = await env.DB.batch([
129+
env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`).bind(companyName1),
130+
env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`).bind(companyName2)
131+
]);
132+
return Response.json(stmt)
133+
```
134+
```js output
135+
[
136+
{
137+
"success": true,
138+
"meta": {
139+
"served_by": "miniflare.db",
140+
"duration": 0,
141+
"changes": 0,
142+
"last_row_id": 0,
143+
"changed_db": false,
144+
"size_after": 8192,
145+
"rows_read": 4,
146+
"rows_written": 0
147+
},
148+
"results": [
149+
{
150+
"CustomerId": 11,
151+
"CompanyName": "Bs Beverages",
152+
"ContactName": "Victoria Ashworth"
153+
},
154+
{
155+
"CustomerId": 13,
156+
"CompanyName": "Bs Beverages",
157+
"ContactName": "Random Name"
158+
}
159+
]
160+
},
161+
{
162+
"success": true,
163+
"meta": {
164+
"served_by": "miniflare.db",
165+
"duration": 0,
166+
"changes": 0,
167+
"last_row_id": 0,
168+
"changed_db": false,
169+
"size_after": 8192,
170+
"rows_read": 4,
171+
"rows_written": 0
172+
},
173+
"results": [
174+
{
175+
"CustomerId": 4,
176+
"CompanyName": "Around the Horn",
177+
"ContactName": "Thomas Hardy"
178+
}
179+
]
180+
}
181+
]
182+
```
183+
```js
184+
console.log(stmt[1].results);
185+
```
186+
```js output
187+
[
188+
{
189+
"CustomerId": 4,
190+
"CompanyName": "Around the Horn",
191+
"ContactName": "Thomas Hardy"
192+
}
193+
]
194+
```
195+
</Details>
196+
197+
#### Guidance
198+
199+
- You can construct batches reusing the same prepared statement:
200+
201+
```js
202+
const companyName1 = `Bs Beverages`;
203+
const companyName2 = `Around the Horn`;
204+
const stmt = env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`);
205+
const batchResult = await env.DB.batch([
206+
stmt.bind(companyName1),
207+
stmt.bind(companyName2)
208+
]);
209+
return Response.json(batchResult);
210+
```
211+
212+
### `db.exec()`
213+
214+
Executes one or more queries directly without prepared statements or parameter bindings.
215+
216+
```js
217+
const returnValue = await env.DB.exec(`SELECT * FROM Customers WHERE CompanyName = "Bs Beverages"`);
218+
```
219+
220+
#### Parameters
221+
222+
- <code>queryString</code>: <Type text="String"/> <MetaInfo text="Required"/>
223+
- The SQL query statement without parameter binding.
224+
225+
#### Return values
226+
227+
- <code>D1ExecResult</code>: <Type text="Object"/>
228+
- The `count` property contains the number of executed queries.
229+
- The `duration` property contains the duration of operation in milliseconds.
230+
- Refer to [`D1ExecResult`](/d1/worker-api/return-object/#d1execresult) for more information.
231+
232+
<Details header="Example of return values" open={false}>
233+
```js
234+
const returnValue = await env.DB.exec(`SELECT * FROM Customers WHERE CompanyName = "Bs Beverages"`);
235+
return Response.json(returnValue);
236+
```
237+
```js output
238+
{
239+
"count": 1,
240+
"duration": 1
241+
}
242+
```
243+
</Details>
244+
245+
#### Guidance
246+
247+
- If an error occurs, an exception is thrown with the query and error messages, execution stops and further statements are not executed. Refer to [Errors](/d1/build-with-d1/d1-client-api/#errors) to learn more.
248+
- This method can have poorer performance (prepared statements can be reused in some cases) and, more importantly, is less safe.
249+
- Only use this method for maintenance and one-shot tasks (for example, migration jobs).
250+
- The input can be one or multiple queries separated by `\n`.
251+
252+
### `db.dump`
253+
254+
:::caution
255+
This API only works on databases created during D1's alpha period. Check which version your database uses with `wrangler d1 info <DATABASE_NAME>`.
256+
:::
257+
258+
Dumps the entire D1 database to an SQLite compatible file inside an ArrayBuffer.
259+
260+
```js
261+
const dump = await db.dump();
262+
return new Response(dump, {
263+
status: 200,
264+
headers: {
265+
"Content-Type": "application/octet-stream",
266+
},
267+
});
268+
```
269+
270+
#### Parameters
271+
272+
- None.
273+
274+
#### Return values
275+
276+
- None.

src/content/docs/d1/worker-api/index.mdx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@ import { DirectoryListing, Details, Steps } from "~/components";
99

1010
You can execute SQL queries on your D1 database from a Worker using the Worker Binding API. To do this, you can perform the following steps:
1111

12-
1. [Prepare a statement](/d1/worker-api/prepare-a-statement).
13-
2. [Run the prepared statement](/d1/worker-api/run-a-statement).
14-
3. Analyze the [return object](/d1/worker-api/return-object) (if necessary).
12+
1. [Bind the D1 Database](/d1/worker-api/d1-binding).
13+
2. [Prepare a statement](/d1/worker-api/d1-binding/#dbprepare).
14+
3. [Run the prepared statement](/d1/worker-api/prepared-statements).
15+
4. Analyze the [return object](/d1/worker-api/return-object) (if necessary).
1516

1617
Refer to the relevant sections for the API documentation.
1718

1819
## TypeScript support
1920

2021
D1 Worker Bindings API is fully-typed via the [`@cloudflare/workers-types`](/workers/languages/typescript/#typescript) package, and also supports [generic types](https://www.typescriptlang.org/docs/handbook/2/generics.html#generic-types) as part of its TypeScript API. A generic type allows you to provide an optional `type parameter` so that a function understands the type of the data it is handling.
2122

22-
When using the [query statement methods](/d1/worker-api/run-a-statement) `stmt.run()`, `stmt.raw()` and `stmt.first()`, you can provide a type representing each database row. D1's API will [return the result object](#return-object) with the correct type.
23+
When using the [query statement methods](/d1/worker-api/prepared-statements) `stmt.run()`, `stmt.raw()` and `stmt.first()`, you can provide a type representing each database row. D1's API will [return the result object](#return-object) with the correct type.
2324

2425
For example, providing an `OrderRow` type as a type parameter to `stmt.run()` will return a typed `Array<OrderRow>` object instead of the default `Record<string, unknown>` type:
2526

src/content/docs/d1/worker-api/prepare-a-statement.mdx

Lines changed: 0 additions & 84 deletions
This file was deleted.

0 commit comments

Comments
 (0)