The "runSqlStatements" action runs one or more SQL statements as a batch operation, such as drop, create, alter, call, insert, update, and delete statements.
Notice JSON DB API transactions do not support SQL stored procedures, stored functions, and triggers. It also does not support "revertTransactionToSavepoint" when the transaction contains a call to "getRecordsUsingSQL" or "runSqlStatements". Unsupported actions return an error.
- The "runSqlStatements" action cannot run in an existing transaction. It creates a new transaction.
- FairCom does not recommend including SELECT statements in the "runSqlStatements" action because the server returns all records selected by each query.
- It is easy to return too many records, which results in query timeouts or clients receiving too much data.
- It is much better to use the "getRecordsUsingSQL" action to run SQL queries because it can return a cursor, which is faster and much more efficient at paginating data.
- If you want to use the "runSqlStatements" to run queries, be sure to add the SQL TOP clause to your SQL statement to limit the number of records returned.
- The server returns a "data" object in the response that contains one object for each SQL statement in the request.
- The "errorCode" property for each individual SQL statement indicates the success or failure of the statement during runtime.
- You must check the "errorCode" property of each individual SQL statement to determine if it succeeded or failed. This is intentional because there are use cases where you expect some SQL statements to fail, such as dropping a table before creating it.
- Do not assume a zero value in the "errorCode" property for the "runSqlStatements" action means all SQL statements succeeded.
- The only time the server sets a non-zero value in the "errorCode" property for the "runSqlStatements" action is when it evaluates the request and detects invalid JSON syntax, missing required properties, and invalid property values.
- Before the server runs SQL statements, it creates a new transaction, then runs all specified SQL statements in that transaction.
- It can be efficient to run hundreds of statements in one "runSQLStatements" action.
- By default, the server automatically rolls back the transaction at the end. You must set the "atEnd" and "onError" properties to control how the server commits each SQL statement.
- You may call a stored procedure as long as it does not have out or "in"/"out" parameters and you pass a constant value to each "in" parameter.
- A SQL statement may optionally include a semicolon at its end, but it is unnecessary and is ignored.
- A SQL statement may contain one or more line feed characters. These are encoded in JSON strings as \n.
- Use "runSQLStatements" action to do things that are not available in other JSON DB API actions.
- Use parameters in the SELECT and CALL statements to prevent SQL injection attacks.
- A parameter name in the SQL statement must begin with a colon, immediately followed by the name of the parameter. When defining input and output parameters in JSON, parameter names do not include the colon to be more friendly to programming languages.
- Use native JSON DB API actions when possible. They run faster than SQL. It is also easier and safer to dynamically generate JSON in your code than to generate SQL code.
- Use the "getRecordsUsingSQL" action to run queries because it can return a cursor.
- Use the "createTable" action to create a table because it follows best practices and provides more settings.
- Use the "alterTable" action to modify a table because it is easier to use.
- Use the "insertRecords" action to insert large numbers of records because it is more efficient.
Request examples
Minimal
Note This example shows automatic rollback on error.
{
"action": "runSQLStatements",
"params": {
"sqlStatements": [
"CREATE TABLE employee (id BIGINT, name VARCHAR(50), job VARCHAR(50) )",
"CREATE UNIQUE INDEX employee_pk ON employee (id)",
"INSERT INTO employee \n VALUES (7369, 'John Smith', 'Clerk')"
]
},
"authToken": "replaceWithAuthTokenFromCreateSession"
}Unconditional rollback and immediate stop on first error
{
"api": "db",
"action": "runSQLStatements",
"params": {
"onError": "stop",
"atEnd": "rollback",
"sqlStatements": [
"CREATE TABLE employee (id BIGINT, name VARCHAR(50), job VARCHAR(50) )",
"CREATE UNIQUE INDEX employee_pk ON employee (id)",
"INSERT INTO employee \n VALUES (7369, 'John Smith', 'Clerk')"
]
},
"debug": "none",
"authToken": "replaceWithAuthTokenFromCreateSession"
}Unconditional commit
{
"requestId": "2",
"api": "db",
"action": "runSQLStatements",
"params": {
"transactionId": "NO SUPPORT FOR TRANSACTIONS AT THIS TIME",
"databaseName": "ctreeSQL",
"ownerName": "admin",
"onError": "continue",
"atEnd": "commit",
"sqlStatements": [
"DROP TABLE employee;",
"CREATE TABLE employee (id BIGINT, name VARCHAR(50), job VARCHAR(50) )",
"CREATE UNIQUE INDEX employee_pk ON employee (id)",
"INSERT INTO employee VALUES (7369, 'John Smith', 'Clerk');",
"INSERT INTO employee VALUES (1, 'Emma Smith', 'Boss')",
"CALL my_stored_proc(:inIntParam1, :outDoubleParam2, :inOutBinaryParam3)",
"CALL c2f(:input_celsius, :output_fahrenheit) ",
"SELECT TOP 20 SKIP 0 name \nFROM employee \nWHERE name <= :mySqlNamedParam4",
"CREATE TABLE employee ( id BIGINT )"
],
"inParams": [
{
"name": "inIntParam1",
"value": 3
},
{
"name": "inoutBinaryParam3",
"value": "54657374"
},
{
"name": "mySqlNamedParam4",
"value": "J"
},
{
"name": "input_celsius",
"value": 22
}
]
},
"responseOptions": {
"binaryFormat": "hex",
"dataFormat": "objects",
"numberFormat": "string",
"includeFields": [],
"excludeFields": []
},
"apiVersion": "1.0",
"debug": "max",
"authToken": "replaceWithAuthTokenFromCreateSession"
}
Response examples
Minimal
Note This example shows automatic rollback on error.
{
"result": {
"reactions": [
{
"affectedRows": 0,
"errorCode": 0,
"errorMessage": "",
"outParams": [],
"rows": {},
"sql": "CREATE TABLE employee (id BIGINT, name VARCHAR(50), job VARCHAR(50) )"
},
{
"affectedRows": 0,
"errorCode": 0,
"errorMessage": "",
"outParams": [],
"rows": {},
"sql": "CREATE UNIQUE INDEX employee_pk ON employee (id)"
},
{
"affectedRows": 1,
"errorCode": 0,
"errorMessage": "",
"outParams": [],
"rows": {},
"sql": "INSERT INTO employee \n VALUES (7369, 'John Smith', 'Clerk')"
}
]
},
"debugInfo": {
"request": {
"action": "runSQLStatements",
"params": {
"sqlStatements": [
"CREATE TABLE employee (id BIGINT, name VARCHAR(50), job VARCHAR(50) )",
"CREATE UNIQUE INDEX employee_pk ON employee (id)",
"INSERT INTO employee \n VALUES (7369, 'John Smith', 'Clerk')"
]
},
"debug": "max",
"authToken": "replaceWithAuthTokenFromCreateSession"
},
"serverSuppliedValues": {
"databaseName": "faircom",
"ownerName": null
},
"errorData": {
"errorData": null
},
"warnings": []
},
"errorCode": 0,
"errorMessage": "",
"authToken": "replaceWithAuthTokenFromCreateSession"
}Rollback on error
Note This result occurs when the minimal request example is run a second time.
{
"result": {
"data": [
{
"affectedRows": 0,
"errorCode": -20041,
"errorMessage": "Table/View/Synonym employee already exists",
"sql": "CREATE TABLE employee (id BIGINT, name VARCHAR(50), job VARCHAR(50) )"
},
{
"affectedRows": 0,
"errorCode": -20028,
"errorMessage": "Index with the same name employee_pk already exists",
"sql": "CREATE UNIQUE INDEX employee_pk ON employee (id)"
},
{
"affectedRows": 0,
"errorCode": -17002,
"errorMessage": "CT - Key value already exists in index employee_pk",
"output": {},
"sql": "INSERT INTO employee \n VALUES (7369, 'John Smith', 'Clerk')"
}
]
},
"errorCode": 0,
"errorMessage": "",
"authToken": "replaceWithAuthTokenFromCreateSession"
}Unconditional rollback and immediate stop on first error
{
"result": {
"reactions": [
{
"affectedRows": 0,
"errorCode": -20041,
"errorMessage": "Table/View/Synonym employee already exists",
"outParams": [],
"rows": {},
"sql": "CREATE TABLE employee (id BIGINT, name VARCHAR(50), job VARCHAR(50) )"
}
]
},
"errorCode": 0,
"errorMessage": "",
"authToken": "replaceWithAuthTokenFromCreateSession"
}Unconditional commit
{
"result": {
"reactions": [
{
"affectedRows": 0,
"errorCode": -20005,
"errorMessage": "Table/View/Synonym employee not found",
"outParams": [],
"rows": {},
"sql": "DROP TABLE employee"
},
{
"affectedRows": 0,
"errorCode": 0,
"errorMessage": "",
"outParams": [],
"rows": {},
"sql": "CREATE TABLE employee (id BIGINT, name VARCHAR(50), job VARCHAR(50) )"
},
{
"affectedRows": 0,
"errorCode": 0,
"errorMessage": "",
"outParams": [],
"rows": {},
"sql": "CREATE UNIQUE INDEX employee_pk ON employee (id)"
},
{
"affectedRows": 1,
"errorCode": 0,
"errorMessage": "",
"outParams": [],
"rows": {},
"sql": "INSERT INTO employee VALUES (7369, 'John Smith', 'Clerk')"
},
{
"affectedRows": 1,
"errorCode": 0,
"errorMessage": "",
"outParams": [],
"rows": {},
"sql": "INSERT INTO employee VALUES (1, 'Emma Smith', 'Boss')"
},
{
"affectedRows": 0,
"errorCode": -20122,
"errorMessage": "procedure my_stored_proc not found",
"outParams": [],
"rows": {},
"sql": "CALL my_stored_proc(:inIntParam1, :outDoubleParam2, :inOutBinaryParam3)"
},
{
"affectedRows": 0,
"errorCode": -20122,
"errorMessage": "procedure c2f not found",
"outParams": [],
"rows": {},
"sql": "CALL c2f(:input_celsius, :output_fahrenheit)"
},
{
"affectedRows": 0,
"errorCode": 0,
"errorMessage": "",
"outParams": [],
"rows": {
"binaryFormat": "hex",
"data": [
{
"name": "Emma Smith"
}
],
"dataFormat": "objects",
"fields": [
{
"length": 50,
"name": "name",
"type": "varchar"
}
],
"moreRecords": false,
"numberFormat": "string",
"requestedRecordCount": 1,
"returnedRecordCount": 1
},
"sql": "SELECT TOP 20 SKIP 0 name \nFROM employee \nWHERE name <= :mySqlNamedParam4"
},
{
"affectedRows": 0,
"errorCode": -20041,
"errorMessage": "Table/View/Synonym employee already exists",
"outParams": [],
"rows": {},
"sql": "CREATE TABLE employee ( id BIGINT )"
}
]
},
"requestId": "2",
"debugInfo": {
"request": {
"api": "db",
"action": "runSQLStatements",
"params": {
"databaseName": "ctreeSQL",
"ownerName": "admin",
"onError": "continue",
"atEnd": "commit",
"sqlStatements": [
"DROP TABLE employee;",
"CREATE TABLE employee (id BIGINT, name VARCHAR(50), job VARCHAR(50) )",
"CREATE UNIQUE INDEX employee_pk ON employee (id)",
"INSERT INTO employee VALUES (7369, 'John Smith', 'Clerk');",
"INSERT INTO employee VALUES (1, 'Emma Smith', 'Boss')",
"CALL my_stored_proc(:inIntParam1, :outDoubleParam2, :inOutBinaryParam3)",
"CALL c2f(:input_celsius, :output_fahrenheit) ",
"SELECT TOP 20 SKIP 0 name \nFROM employee \nWHERE name <= :mySqlNamedParam4",
"CREATE TABLE employee ( id BIGINT )"
],
"inParams": [
{
"name": "inIntParam1",
"value": 3
},
{
"name": "inoutBinaryParam3",
"value": "54657374"
},
{
"name": "mySqlNamedParam4",
"value": "J"
},
{
"name": "input_celsius",
"value": 22
}
]
},
"apiVersion": "1.0",
"requestId": "2",
"responseOptions": {
"binaryFormat": "hex",
"dataFormat": "objects",
"numberFormat": "string",
"includeFields": [],
"excludeFields": []
},
"debug": "max",
"authToken": "replaceWithAuthTokenFromCreateSession"
},
"serverSuppliedValues": {
"databaseName": "ctreeSQL",
"ownerName": null
},
"errorData": {
"errorData": null
},
"warnings": [
{
"code": 100,
"message": "SQL execution produced errors"
}
]
},
"errorCode": 0,
"errorMessage": "",
"authToken": "replaceWithAuthTokenFromCreateSession"
}
Request properties ("params")
| Property | Description | Default | Type | Limits (inclusive) |
|---|---|---|---|---|
transactionId |
The "transactionId" property identifies a transaction in which the specified action will be included. |
Optional with default of ""
|
string | 0 to 255 bytes |
databaseName |
The You specify this property when you want to use a different database instead of the default. This property is useful because objects, such as tables and code packages, can have the same name in multiple databases. This feature allows you to create multiple environments in the same server and reuse the same JSON actions in each environment. For example, you can create It is an error to set If no default database is specified during |
Defaults to the session's "defaultDatabaseName" property |
string | 1 to 64 bytes |
ownerName |
The You specify this property when you want to use a different account instead of the default. Your session's account must have the appropriate privileges to access the code package. This property is useful because objects, such as tables and code packages, can have the same name in the same database as long as different accounts own each object. This feature allows you to create duplicate objects for different users on the same server and reuse the same JSON actions on those objects. For example, an administrator can copy objects from a production environment to her account so she can troubleshoot an issue using the same JSON actions, JavaScript, and SQL code. It is an error to set If no default owner is specified during |
Optional with default of the session's "defaultOwnerName" property |
string | 1 to 64 bytes |
onError |
The |
Optional with default of "continue"
|
string |
|
atEnd |
The "atEnd" property defines how the action commits or rolls back the statement it runs. For more details, see “atEnd”. |
Optional with default of "rollbackOnError"
|
string |
|
sqlStatements |
The There is one SQL statement per string. |
Required - No default value |
array of strings | 1 or more sql statements |
inParams |
The
{
"params": {
"inParams": [
{
"name": "inIntParam1",
"value": 3
},
{
"name": "inoutBinaryParam3",
"value": "54657374"
},
{
"name": "mySqlNamedParam4",
"value": "Ray"
}
]
}
} |
is the default when no SQL statements have any named parameters. When one or more SQL statements have named parameters, this is required. |
array of objects |
|
|
inParams .name |
The The The
|
Required - No default value | string | 1 to 64 bytes |
|
inParams .value |
The
In Key-Value actions, the required |
Required - No default value | string |
|
Response properties ("result")
| Property | Description | Type | Limits (inclusive) |
|---|---|---|---|
reactions |
The "reactions" property contains the data returned by a SQL SELECT statement. |
array of objects | |
|
reactions .affectedRows |
The "affectedRows" property specifies the number of records that were affected by the SQL statement. |
integer | number of records affected by the statement. |
|
reactions .errorCode |
The "errorCode" property indicates an error when set to a non-zero integer or success when 0.
|
integer | -2147483648 to 2147483647 |
|
reactions .errorMessage |
The "errorMessage" property displays a human-readable error message. |
string | 0 to 256 bytes |
|
reactions .outParams |
The "outParams" property specifies the output values of a stored procedure. |
array of objects |
|
|
reactions .rows |
The "rows" property specifies the rows returned by a stored procedure of a SELECT statement and metadata about the results. |
object | The rows returned by a stored procedure. |
|
reactions .rows .binaryFormat |
The "binaryFormat" property designates the format of binary values embedded in JSON strings. See binaryFormat for more details. |
string | One of the following: "base64", "hex", or "byteArray". |
|
reactions .rows .data |
The |
array of objects | The action determines its contents. |
|
reactions .rows .data .name |
The The The
|
string | 1 to 64 bytes |
|
reactions .rows .dataformat |
The
|
string |
|
|
reactions .rows .fields |
The
"fields": [
{
"autoValue": "none",
"name": "name",
"type": "varchar",
"length": 50,
"scale": null,
"defaultValue": null,
"nullable": false, |
array |
|
|
reactions .rows .fields .length |
Identifies the length of the field. | integer |
1 to 65500 |
|
reactions .rows .fields .name |
The The The
|
string | 1 to 64 bytes |
|
reactions .rows .fields .type |
Identifies the type of the field. See Data types. | string |
|
|
reactions .numberFormat |
The
Possible values:
|
string |
|
|
reactions .requestedRecordCount |
The
|
integer |
|
|
reactions .returnedRecordCount |
The
|
integer |
|
sql |
The "sql" property specifies the original SQL statement that was executed. |
string | The original SQL statement |