Module sql




This module provides the generic interface and functionality to interact with an SQL database. The corresponding database clients can be created by using specific database modules such as mysql or using the Java Database Connectivity module jdbc.

List of database modules

Ballerina now has the jdbc module as the generic DB connector module to connect to any relational database by simply providing the JDBC URL and the other related properties.

Ballerina also provides specially designed various database-specific DB connectors so that you can work with different databases, and you can access their DB-specific functionalities.


A database client can be created using any of the above-listed database libraries. The operations and functionality explained below can be used with the newly created client.

Tip : The client should be used throughout the application lifetime.

Handle connection pools

All database modules share the same connection pooling concept and there are three possible scenarios for connection pool handling. For its properties and possible values, see the sql:ConnectionPool.

Note: Connection pooling is used to optimize opening and closing connections to the database. However, the pool comes with an overhead. It is best to configure the connection pool properties as per the application need to get the best performance.

  1. Global, shareable, default connection pool

    If you do not provide the poolOptions field when creating the database client, a globally-shareable pool will be created for your database unless a connection pool matching with the properties you provided already exists. The jdbc module sample below shows how the global connection pool is used.

  2. Client-owned, unsharable connection pool

    If you define the connectionPool field inline when creating the database client with the sql:ConnectionPool type, an unsharable connection pool will be created. The jdbc module sample below shows how the global connection pool is used.

  3. Local, shareable connection pool

    If you create a record of the sql:ConnectionPool type and reuse that in the configuration of multiple clients, a shared connection pool will be created for each set of clients that connects to the same database instance with the same set of properties. The jdbc module sample below shows how the global connection pool is used.


Close the client

Once all the database operations are performed, you can close the database client you have created by invoking the close() operation. This will close the corresponding connection pool if it is not shared by any other database clients.

Note : The client must be closed only at the end of the application lifetime (or closed for graceful stops in a service).




Database operations

Once the client is created, database operations can be executed through that client. This module defines the interface and generic properties that are shared among multiple database clients. It also supports querying, inserting, deleting, updating, and batch updating data.

Parameterized query

The sql:ParameterizedQuery is used to construct the SQL query to be executed by the client. You can create a query with constant or dynamic input data as follows.

Query with constant values


Query with dynamic values


Moreover, the SQL package has sql:queryConcat() and sql:arrayFlattenQuery() util functions which make it easier to create a dynamic/constant complex query.

The sql:queryConcat() is used to create a parameterized query by concatenating a set of parameterized queries. The sample below shows how to concatenate queries.


The query with the IN operator can be created using the sql:ParameterizedQuery like below. Here you need to flatten the array and pass each element separated by a comma.


The util function sql:arrayFlattenQuery() is introduced to make the array flatten easier. It makes the inclusion of varying array elements into the query easier by flattening the array to return a parameterized query. You can construct the complex dynamic query with the IN operator by using both functions like below.


Create tables

This sample creates a table with two columns. One column is of type int and the other is of type varchar. The CREATE statement is executed via the execute remote method of the client.


Insert data

These samples show the data insertion by executing an INSERT statement using the execute remote method of the client.

In this sample, the query parameter values are passed directly into the query statement of the execute remote method.


In this sample, the parameter values, which are assigned to local variables are used to parameterize the SQL query in the execute remote method. This parameterization can be performed with any primitive Ballerina type like string, int, float, or boolean and in that case, the corresponding SQL type of the parameter is derived from the type of the Ballerina variable that is passed in.


In this sample, the parameter values are passed as a sql:TypedValue to the execute remote method. Use the corresponding subtype of the sql:TypedValue such as sql:VarcharValue, sql:CharValue, sql:IntegerValue, etc., when you need to provide more details such as the exact SQL type of the parameter.


Insert data with auto-generated keys

This sample demonstrates inserting data while returning the auto-generated keys. It achieves this by using the execute remote method to execute the INSERT statement.


Query data

These samples show how to demonstrate the different usages of the query operation to query the database table and obtain the result as a stream.

Note: When processing the stream, make sure to consume all fetched data or close the stream.

This sample demonstrates querying data from a table in a database. First, a type is created to represent the returned result set. This record can be defined as an open or a closed record according to the requirement. If an open record is defined, the returned stream type will include both defined fields in the record and additional database columns fetched by the SQL query which are not defined in the record. Note the mapping of the database column to the returned record's property is case-insensitive if it is defined in the record(i.e., the ID column in the result can be mapped to the id property in the record). Additional column names are added to the returned record as in the SQL query. If the record is defined as a closed record, only defined fields in the record are returned or gives an error when additional columns present in the SQL query. Next, the SELECT query is executed via the query remote method of the client. Once the query is executed, each data record can be retrieved by iterating through the result set. The stream returned by the SELECT operation holds a pointer to the actual data in the database, and it loads data from the table only when it is accessed. This stream can be iterated only once.


Defining the return type is optional, and you can query the database without providing the result type. Hence, the above sample can be modified as follows with an open record type as the return type. The property name in the open record type will be the same as how the column is defined in the database.


sql:Column annotation can be used to map database columns to Typed record fields of different name. This annotation should be attached to record fields.


The above annotation will map the database column first_name to the Ballerina record field firstName. If the query() function does not return first_name column, the field will not be populated.

Multiple table columns can be matched to a single Ballerina record within a returned record. For instance if the query returns data from multiple tables such as Students and Teachers. All columns of the Teachers table can be grouped to another Typed record such as Teacher type within the Student record.


In the above scenario also, sql:Column annotation can be used to rename field name such as,


There are situations in which you may not want to iterate through the database and in that case, you may decide to use the sql:queryRow() operation. If the provided return type is a record, this method returns only the first row retrieved by the query as a record.


The sql:queryRow() operation can also be used to retrieve a single value from the database (e.g., when querying using COUNT() and other SQL aggregation functions). If the provided return type is not a record (i.e., a primitive data type) , this operation will return the value of the first column of the first row retrieved by the query.


Update data

This sample demonstrates modifying data by executing an UPDATE statement via the execute remote method of the client.


Delete data

This sample demonstrates deleting data by executing a DELETE statement via the execute remote method of the client.


Batch update data

This sample demonstrates how to insert multiple records with a single INSERT statement that is executed via the batchExecute remote method of the client. This is done by creating a table with multiple records and a parameterized SQL query as same as the above execute operations.


Execute SQL stored procedures

This sample demonstrates how to execute a stored procedure with a single INSERT statement that is executed via the call remote method of the client.


Note: Once the results are processed, the close method on the sql:ProcedureCallResult must be called.

Note: The default thread pool size used in Ballerina is: the number of processors available * 2. You can configure the thread pool size by using the BALLERINA_MAX_POOL_SIZE environment variable.

Other versions

See more...