Querying
Execute SQL queries against databases using queryExecute() or bx:query component
BoxLang provides powerful and flexible ways to execute SQL queries against your databases. You can use either the queryExecute() Built-In Function (BIF) or the bx:query component, both offering the same capabilities with different syntax styles.
📋 Overview
Database querying in BoxLang supports:
Parameterized Queries - Prevent SQL injection with bound parameters
Multiple Return Types - Get results as query objects, arrays, or structs
Query Caching - Cache frequently-used queries for performance
Query of Queries (QoQ) - Execute SQL against in-memory result sets
Flexible Syntax - Choose between BIF and component styles
Connection Pooling - Automatic connection management via HikariCP
🔧 Query Execution Methods
Using queryExecute() BIF
The queryExecute() function is the preferred method for script-based code:
// Basic query
employees = queryExecute( "SELECT * FROM employees" );
// With positional parameters
employee = queryExecute(
"SELECT * FROM employees WHERE id = ?",
[ 42 ]
);
// With named parameters
salesTeam = queryExecute(
"SELECT * FROM employees WHERE department = :dept AND salary > :minSalary",
{
dept: "Sales",
minSalary: 50000
}
);
// With options
result = queryExecute(
"SELECT * FROM products WHERE category = ?",
[ "Electronics" ],
{
datasource: "myDB",
returntype: "array",
maxrows: 100
}
);Using bx:query Component
The bx:query component is ideal for template-based code islands, or when you prefer XML-style syntax. Please also note that you can also use the bx:query component inside script code as well.
🛡️ Parameterized Queries
Always use query parameters for user input to prevent SQL injection attacks.
Positional Parameters
Use ? placeholders and provide values in an array:
Named Parameters
Use :paramName placeholders and provide values in a struct:
bx:queryParam Component
For template syntax, use bx:queryParam for type-safe parameter binding:
Advanced Parameter Options
Parameters can include additional options for fine-grained control:
Parameter Options:
value- The parameter valuetype- SQL type (varchar, integer, decimal, date, timestamp, bit, etc.)null- Set to true for NULL valueslist- Set to true for IN clause listsseparator- List separator (default: ",")maxLength- Maximum length for string typesscale- Decimal scale for numeric types
📊 Return Types
Control how query results are returned using the returntype option.
Query Object (Default)
Returns a BoxLang Query object with rows accessible via array notation:
Array of Structs
Returns an array where each element is a struct representing a row:
Struct (Keyed by Column)
Returns a struct keyed by a specific column, with each value being a struct of the row data:
⚡ Query Caching
Cache frequently-executed queries to improve performance:
Cache Options:
cache- Enable caching (boolean)cacheKey- Custom cache key (defaults to SQL hash)cacheTimeout- Time-to-live durationcacheLastAccessTimeout- Idle timeoutcacheProvider- Named cache provider to use
Be cautious caching queries with user-specific data. Cache keys should include relevant user identifiers when needed.
🔄 Query of Queries (QoQ)
Execute SQL queries against in-memory query objects without hitting the database:
QoQ Features:
Standard SQL syntax (SELECT, WHERE, ORDER BY, GROUP BY, JOIN)
Aggregation functions (COUNT, SUM, AVG, MIN, MAX)
No database round-trips
Ideal for filtering, sorting, and transforming result sets
QoQ Limitations:
Limited SQL function support compared to full databases
No transaction support
Performance depends on result set size
📈 Query Result Information
Capture metadata about query execution using the result option:
Result Struct Properties:
recordCount- Number of rows returnedcolumnList- Comma-delimited list of columnsexecutionTime- Query execution time in millisecondscached- Boolean indicating if result was cachedsql- The SQL statement executedsqlParameters- Array of bound parameter values
🎛️ Query Options
Complete list of options available for queryExecute() and bx:query:
datasource
string
Datasource name or inline struct
dbtype
string
"query" for QoQ, "hql" for Hibernate
returntype
string
"query", "array", or "struct"
columnKey
string
Column to use as struct key (when returntype="struct")
maxrows
integer
Maximum rows to return
timeout
integer
Query timeout in seconds
cache
boolean
Enable query caching
cacheKey
string
Custom cache key
cacheTimeout
duration
Cache time-to-live
cacheLastAccessTimeout
duration
Cache idle timeout
cacheProvider
string
Named cache provider
result
string
Variable name to store execution metadata
username
string
Override datasource username
password
string
Override datasource password
fetchsize
integer
Number of rows to fetch at once
📊 Query Metadata
Every query result has metadata that provides information about the query execution, columns, and result set. You can access this metadata using the getMetadata() function or the query's $bx.meta property.
Accessing Query Metadata
Metadata Structure
Query metadata includes the following keys:
type
string
Always "Query"
recordCount
integer
Number of rows in the result set
columnList
string
Comma-delimited list of column names
columnMetadata
struct
Detailed information about each column
executionTime
integer
Query execution time in milliseconds
cached
boolean
Whether the result was retrieved from cache
cacheKey
string
Cache key if query was cached
cacheProvider
string
Cache provider name if cached
cacheTimeout
duration
Cache time-to-live duration
cacheLastAccessTimeout
duration
Cache idle timeout duration
sql
string
The executed SQL statement (when available)
sqlParameters
array
Bound parameter values (when available)
_HASHCODE
integer
Java hashcode of the query object
Column Metadata
The columnMetadata key contains detailed information about each column:
Each column has the following properties:
name
string
Column name
type
string
BoxLang type (String, Integer, Double, DateTime, etc.)
sqltype
string
JDBC SQL type (VARCHAR, INTEGER, DECIMAL, TIMESTAMP, etc.)
index
integer
Zero-based column index in the result set
Practical Examples
Display Query Information
Debug Query Columns
Cache Performance Monitoring
Dynamic Column Mapping
Query Comparison Tool
Metadata in Result Variable
When using the result parameter, execution metadata is automatically captured:
Best Practices for Metadata
✅ Use metadata for debugging - Check execution times and column information during development
✅ Monitor cache performance - Log cache hits/misses in production
✅ Validate data structures - Compare expected vs actual column types
✅ Dynamic data handling - Use column metadata for generic data processors
❌ Don't access metadata unnecessarily - Small performance cost for metadata generation
❌ Don't store metadata long-term - Query structure may change over time
💡 Best Practices
Security
✅ Always use query parameters for user input
✅ Never concatenate user input into SQL strings
✅ Validate input before querying
✅ Use environment variables for credentials
Performance
✅ Use connection pooling (automatic with datasources)
✅ Cache static queries (categories, lookups, etc.)
✅ Limit result sets with
maxrowswhen appropriate✅ Use QoQ for in-memory filtering instead of multiple DB queries
✅ Index database columns used in WHERE clauses
Code Quality
✅ Use consistent syntax (BIF or component, not mixed)
✅ Name result variables descriptively
✅ Capture execution metadata for debugging
✅ Handle empty result sets gracefully
Anti-Patterns
❌ Don't use string concatenation for SQL building
❌ Don't cache user-specific data without proper keying
❌ Don't fetch all rows when you only need a few
❌ Don't ignore errors - wrap in try/catch for critical operations
🔗 Related Documentation
Datasources - Configure database connections
Transactions - Manage database transactions
Query Type Reference - Query object methods
queryExecute() BIF - Complete BIF reference
bx:query Component - Complete component reference
📚 Examples
Pagination
Dynamic WHERE Clauses
Batch Processing
Last updated
Was this helpful?
