Skip to content
Cloudflare Docs

SQL reference

This page documents the R2 SQL syntax based on the currently supported grammar in public beta.


Query Syntax

SELECT column_list | aggregation_function
FROM table_name
WHERE conditions --optional
[GROUP BY column_list]
[HAVING conditions]
[ORDER BY column_name [DESC | ASC]]
[LIMIT number]

Schema Discovery Commands

R2 SQL supports metadata queries to explore available namespaces and tables.

SHOW DATABASES

Lists all available namespaces.

SHOW DATABASES;

SHOW NAMESPACES

Alias for SHOW DATABASES. Lists all available namespaces.

SHOW NAMESPACES;

SHOW TABLES

Lists all tables within a specific namespace.

SHOW TABLES IN namespace_name;

DESCRIBE

Describes the structure of a table, showing column names and data types.

DESCRIBE namespace_name.table_name;

SELECT Clause

Syntax

SELECT column_specification [, column_specification, ...]

Column Specification

  • Column name: column_name
  • All columns: *

Examples

SELECT * FROM namespace_name.table_name
SELECT user_id FROM namespace_name.table_name
SELECT user_id, timestamp, status FROM namespace_name.table_name
SELECT timestamp, user_id, response_code FROM namespace_name.table_name

Aggregation Functions

Syntax

SELECT aggregation_function(column_name)
FROM table_name
GROUP BY column_list

Supported Functions

  • COUNT(*): Counts total rows note: only * is supported
  • SUM(column): Sums numeric values
  • AVG(column): Calculates average of numeric values
  • MIN(column): Finds minimum value
  • MAX(column): Finds maximum value

Examples

-- Count rows by department
SELECT department, COUNT(*)
FROM my_namespace.sales_data
GROUP BY department
-- Sum decimal values
SELECT region, SUM(total_amount)
FROM my_namespace.sales_data
GROUP BY region
-- Average by category
SELECT category, AVG(price)
FROM my_namespace.products
GROUP BY category
-- Min and Max
SELECT department, MIN(salary), MAX(salary)
FROM my_namespace.employees
GROUP BY department
-- Invalid: No aliases
SELECT department, COUNT(*) AS total FROM my_namespace.sales_data GROUP BY department
-- Invalid: COUNT column name
SELECT COUNT(department) FROM my_namespace.sales_data

FROM Clause

Syntax

SELECT * FROM table_name

WHERE Clause

Syntax

SELECT * WHERE condition [AND|OR condition ...]

Conditions

Null Checks

  • column_name IS NULL
  • column_name IS NOT NULL

Value Comparisons

  • column_name BETWEEN value' AND 'value
  • column_name = value
  • column_name >= value
  • column_name > value
  • column_name <= value
  • column_name < value
  • column_name != value
  • column_name LIKE 'value%'

Logical Operators

  • AND - Logical AND
  • OR - Logical OR

Data Types

  • integer - Whole numbers
  • float - Decimal numbers
  • string - Text values (quoted)
  • timestamp - RFC3339 format ('YYYY-DD-MMT-HH:MM:SSZ')
  • date - Date32/Data64 expressed as a string ('YYYY-MM-DD')
  • boolean - Explicitly valued (true, false)

Examples

SELECT * FROM namespace_name.table_name WHERE timestamp BETWEEN '2025-09-24T01:00:00Z' AND '2025-09-25T01:00:00Z'
SELECT * FROM namespace_name.table_name WHERE status = 200
SELECT * FROM namespace_name.table_name WHERE response_time > 1000
SELECT * FROM namespace_name.table_name WHERE user_id IS NOT NULL
SELECT * FROM namespace_name.table_name WHERE method = 'GET' AND status >= 200 AND status < 300
SELECT * FROM namespace_name.table_name WHERE (status = 404 OR status = 500) AND timestamp > '2024-01-01'

GROUP BY Clause

Syntax

SELECT column_list, aggregation_function
FROM table_name
[WHERE conditions]
GROUP BY column_list

Examples

-- Single column grouping
SELECT department, COUNT(*)
FROM my_namespace.sales_data
GROUP BY department
-- Multiple column grouping
SELECT department, category, COUNT(*)
FROM my_namespace.sales_data
GROUP BY department, category
-- With WHERE filter
SELECT region, COUNT(*)
FROM my_namespace.sales_data
WHERE status = 'completed'
GROUP BY region
-- With ORDER BY (COUNT only)
SELECT region, COUNT(*)
FROM my_namespace.sales_data
GROUP BY region
ORDER BY COUNT(*) DESC
LIMIT 10
-- ORDER BY SUM
SELECT department, SUM(amount)
FROM my_namespace.sales_data
GROUP BY department
ORDER BY SUM(amount) DESC

HAVING Clause

Syntax

SELECT column_list, COUNT(*)
FROM table_name
GROUP BY column_list
HAVING SUM/COUNT/MIN/MAX/AVG(column_name) comparison_operator value

Examples

-- Filter by count threshold
SELECT department, COUNT(*)
FROM my_namespace.sales_data
GROUP BY department
HAVING COUNT(*) > 1000
-- Multiple conditions
SELECT region, COUNT(*)
FROM my_namespace.sales_data
GROUP BY region
HAVING COUNT(*) >= 100
-- HAVING with SUM
SELECT department, SUM(amount)
FROM my_namespace.sales_data
GROUP BY department
HAVING SUM(amount) > 1000000

ORDER BY Clause

Syntax

--Note: ORDER BY only supports ordering by the partition key
ORDER BY partition_key [DESC]
  • ASC: Ascending order
  • DESC: Descending order
  • Default: DESC on all columns of the partition key
  • Can contain any columns from the partition key

Examples

SELECT * FROM namespace_name.table_name WHERE ... ORDER BY partition_key_A
SELECT * FROM namespace_name.table_name WHERE ... ORDER BY partition_key_B DESC
SELECT * FROM namespace_name.table_name WHERE ... ORDER BY partition_key_A ASC

LIMIT Clause

Syntax

LIMIT number
  • Range: 1 to 10,000
  • Type: Integer only
  • Default: 500

Examples

SELECT * FROM namespace_name.table_name WHERE ... LIMIT 100

Complete Query Examples

Basic Query

SELECT *
FROM my_namespace.http_requests
WHERE timestamp BETWEEN '2025-09-24T01:00:00Z' AND '2025-09-25T01:00:00Z'
LIMIT 100

Filtered Query with Sorting

SELECT user_id, timestamp, status, response_time
FROM my_namespace.access_logs
WHERE status >= 400 AND response_time > 5000
ORDER BY response_time DESC
LIMIT 50

Complex Conditions

SELECT timestamp, method, status, user_agent
FROM my_namespace.http_requests
WHERE (method = 'POST' OR method = 'PUT')
AND status BETWEEN 200 AND 299
AND user_agent IS NOT NULL
ORDER BY timestamp DESC
LIMIT 1000

Null Handling

SELECT user_id, session_id, date_column
FROM my_namespace.user_events
WHERE session_id IS NOT NULL
AND date_column >= '2024-01-01'
ORDER BY timestamp
LIMIT 500

Aggregation Query

SELECT department, COUNT(*)
FROM my_namespace.sales_data
WHERE sale_date >= '2024-01-01'
GROUP BY department
ORDER BY COUNT(*) DESC
LIMIT 10

Aggregation with HAVING

SELECT region, COUNT(*)
FROM my_namespace.sales_data
WHERE status = 'completed'
GROUP BY region
HAVING COUNT(*) > 1000
LIMIT 20

Multiple Column Grouping

SELECT department, category, MIN(price), MAX(price)
FROM my_namespace.products
GROUP BY department, category
LIMIT 100

Data Type Reference

Supported Types

TypeDescriptionExample Values
integerWhole numbers1, 42, -10, 0
floatDecimal numbers1.5, 3.14, -2.7, 0.0
stringText values'hello', 'GET', '2024-01-01'
booleanBoolean valuestrue, false
timestampRFC3339'2025-09-24T01:00:00Z'
date'YYYY-MM-DD''2025-09-24'

Type Usage in Conditions

-- Integer comparisons
SELECT * FROM namespace_name.table_name WHERE status = 200
SELECT * FROM namespace_name.table_name WHERE response_time > 1000
-- Float comparisons
SELECT * FROM namespace_name.table_name WHERE cpu_usage >= 85.5
SELECT * FROM namespace_name.table_name WHERE memory_ratio < 0.8
-- String comparisons
SELECT * FROM namespace_name.table_name WHERE method = 'POST'
SELECT * FROM namespace_name.table_name WHERE user_agent != 'bot'
SELECT * FROM namespace_name.table_name WHERE country_code = 'US'

Operator Precedence

  1. Comparison operators: =, !=, <, <=, >, >=, LIKE, BETWEEN, IS NULL, IS NOT NULL
  2. AND (higher precedence)
  3. OR (lower precedence)

Use parentheses to override default precedence:

SELECT * FROM namespace_name.table_name WHERE (status = 404 OR status = 500) AND method = 'GET'