| name | server-querying-python | |||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| summary | Write and execute SQL++ (N1QL) queries from Python against Couchbase — SELECT, DML, parameterization, scan consistency, prepared statements, and query_context | |||||||||||||||||||||||||||||||||||||||||
| description | Write and execute SQL++ (N1QL) queries from Python against Couchbase — SELECT, DML, parameterization, scan consistency, prepared statements, and query_context | |||||||||||||||||||||||||||||||||||||||||
| compatibility | Python SDK 4.x. Requires couchbase>=4.0. | |||||||||||||||||||||||||||||||||||||||||
| metadata |
|
from couchbase.options import QueryOptions
result = cluster.query(
"SELECT META().id, o.status, o.total FROM `myapp`._default.orders o WHERE o.status = $status LIMIT 10",
QueryOptions(named_parameters={"status": "pending"})
)
for row in result:
print(row)Always use named parameters ($name) or positional parameters ($1) — never string-format user input into queries.
result = cluster.query(
"SELECT * FROM `myapp`._default.orders WHERE status = $1 AND total > $2",
QueryOptions(positional_parameters=["pending", 100])
)from couchbase.options import QueryOptions
from couchbase.n1ql import QueryScanConsistency
from couchbase.mutation_state import MutationState
# Read your own writes
upsert_result = collection.upsert("order_1", doc)
result = cluster.query(
"SELECT * FROM `myapp`._default.orders WHERE META().id = 'order_1'",
QueryOptions(
scan_consistency=QueryScanConsistency.AT_PLUS,
consistent_with=MutationState(upsert_result)
)
)
# Strict read-after-write (slower)
result = cluster.query("SELECT ...",
QueryOptions(scan_consistency=QueryScanConsistency.REQUEST_PLUS))# adhoc=False — SDK prepares on first call, caches plan, executes subsequent calls directly
result = cluster.query(
"SELECT * FROM `myapp`._default.orders WHERE customerId = $cid",
QueryOptions(named_parameters={"cid": "c500"}, adhoc=False)
)# Omit bucket/scope prefix in query text
result = cluster.query(
"SELECT * FROM orders WHERE status = 'pending'",
QueryOptions(query_context="default:myapp._default")
)Boundary note: This section covers SDK execution of DML statements. For SQL++ DML syntax (INSERT, UPDATE, DELETE, UPSERT, MERGE), see
sqlpp-language.
# INSERT
cluster.query(
"INSERT INTO `myapp`._default.orders (KEY, VALUE) VALUES ($id, $doc)",
QueryOptions(named_parameters={"id": "order::1", "doc": {"status": "pending"}})
)
# UPDATE
cluster.query(
"UPDATE `myapp`._default.orders SET status = $s WHERE META().id = $id",
QueryOptions(named_parameters={"s": "shipped", "id": "order::1"})
)
# DELETE
cluster.query(
"DELETE FROM `myapp`._default.orders WHERE META().id = $id",
QueryOptions(named_parameters={"id": "order::1"})
)When working within a named scope, use scope.query() to omit the bucket/scope prefix from every statement:
scope = cluster.bucket("myapp").scope("inventory")
result = scope.query("SELECT * FROM orders WHERE status = $s",
QueryOptions(named_parameters={"s": "pending"}))
for row in result.rows():
print(row)See ../../shared/server/sql-syntax.md for SELECT syntax, JOINs, MERGE, WITH RECURSIVE, window functions, and built-in functions.