-
See Also
- ExternalEvaluate
- StartExternalSession
- DatabaseReference
-
- Database Connections
- SQLite
- MicrosoftSQL
- MySQL
- Oracle
- PostgreSQL
-
- External Evaluation Systems
- SQL-JDBC
- Related Guides
-
-
See Also
- ExternalEvaluate
- StartExternalSession
- DatabaseReference
-
- Database Connections
- SQLite
- MicrosoftSQL
- MySQL
- Oracle
- PostgreSQL
-
- External Evaluation Systems
- SQL-JDBC
- Related Guides
-
See Also
"SQL" (External Evaluation System)
Listing of Supported Databases »Details
- To configure a database for use with ExternalEvaluate, see details for each specific database in the listing of supported databases.
ExternalEvaluate Usage
- ExternalEvaluate["SQL",code] executes a string of SQL in a database connection and returns the result as a Wolfram Language expression.
- ExternalEvaluate["SQL"returntype,code] executes the SQL string and returns the result in the specified returntype. Possible specifications for returntype are "Dataset", "Tabular", "Rows", "NamedRows", "Columns" and "NamedColumns".
- ExternalEvaluate[DatabaseReference[ref],code] is equivalent to ExternalEvaluate[{"SQL","Evaluator"DatabaseReference[ref]},code].
- The possible settings for evaluator in ExternalEvaluate[{"SQL","Evaluator"evaluator},…] include:
-
"path"or File["path"] path to an SQLite database URL["url"] a connection specified in the form "backend://user:password@host:port/name" DatabaseReference[…] an SQL database connection SQLConnection[…] an SQL-JDBC database connection
Data Types
- SQL data types are mapped to appropriate Wolfram Language expressions.
- Dates and times are typically converted to DateObject and TimeObject.
- Binary data is converted to ByteArray.
- A full list of supported data types is available for each supported database: SQLite, PostgreSQL, MySQL, MicrosoftSQL and Oracle.
Examples
open all close allBasic Examples (3)
Specify a reference to the demo database:
db = DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]]Evaluate a query in SQL and return the result:
ExternalEvaluate[db, "SELECT * FROM offices"]To use SQL in an external language cell, you need to register a default database:
db = DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]]RegisterExternalEvaluator["SQL", db]Type > and select SQL from the drop-down menu to get an SQL code cell:
Use the File wrapper to execute code contained in a file:
path = Export[CreateFile[], "select 21 as AGE", "String"]ExternalEvaluate[DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]], File[path]
]Deploy code using CloudDeploy, and then run the code directly from a CloudObject:
cobj = CloudExport["select 21 as AGE", "String"]ExternalEvaluate[DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]], cobj]Use a URL wrapper to directly run code hosted online:
query = URL["https://exampledata.wolfram.com/script.sql"]ExternalEvaluate[DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]], query
]Scope (20)
Define a database connection and open a connection:
db = DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]]session = StartExternalSession[db]Evaluate a query that is returning all tables:
ExternalEvaluate[session, "SELECT name FROM sqlite_master WHERE name NOT LIKE 'sqlite_%'"]Query a certain table using a limit:
ExternalEvaluate[session, "SELECT * FROM offices limit 4"]Rename columns using an AS statement:
ExternalEvaluate[session, "SELECT officeCode AS id, addressLine1 || ' - ' || addressLine2 AS address FROM offices"]DeleteObject[session]By default, ExternalEvaluate returns data using Dataset:
db = DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]]ExternalEvaluate[db, "SELECT officeCode AS pk, phone FROM offices"]"ReturnType" can be used to return data in a different form:
ExternalEvaluate[db -> "Rows", "SELECT officeCode AS pk, phone FROM offices"]ExternalEvaluate[db -> "NamedRows", "SELECT officeCode AS pk, phone FROM offices"]ExternalEvaluate[db -> "Columns", "SELECT officeCode AS pk, phone FROM offices"]ExternalEvaluate[db -> "NamedColumns", "SELECT officeCode AS pk, phone FROM offices"]ExternalEvaluate[db -> "Tabular", "SELECT officeCode AS pk, phone FROM offices"]While using "Columns", numerical data is returned as a packed array when possible:
data = ExternalEvaluate[db -> "Columns", "SELECT employeeNumber AS id FROM employees limit 5"]Developer`PackedArrayQ[First[data]]Start a session to a local PostgreSQL database (to evaluate this input, you would need to have an appropriate PostgreSQL database instance running):
db = DatabaseReference[URL["postgres://localhost/template1"]]When supported, ExternalEvaluate will return Wolfram Language expressions instead of strings:
ExternalEvaluate[db, "SELECT NOW() AS now, NOW()::date AS date, interval '1 day' AS interval, '1.23'::decimal AS decimal"]Parameters are automatically normalized according to the database backend that is currently in use. Expressions like Integer, ByteArray, String, DateObject and TimeObject can be used if the back end supports them:
ExternalEvaluate[DatabaseReference["postgresql://localhost/template1"], <|
"Command" -> "SELECT `` AS kernel_now, NOW() AS db_now",
"TemplateArguments" -> {Now}
|>]String templates can be used to insert Wolfram Language expressions into SQL code:
db = DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]];x = 3;
y = 2;The expression x^2+y^2 is evaluated in the Wolfram Language, and the result is converted and inserted into the SQL code string:
ExternalEvaluate[db, "SELECT <* x^2 + y^2 *> AS value"]Manually provide arguments to the template by using an Association:
ExternalEvaluate[db, <|
"Command" -> "SELECT city, addressLine1, country FROM offices WHERE country = `1`",
"TemplateArguments" -> {"USA"}
|>]ExternalEvaluate[db, <|
"Command" -> "SELECT officeCode, city, addressLine1 FROM offices WHERE officeCode < `n`",
"TemplateArguments" -> <|"n" -> 4|>
|>]Session Options (8)
"ReturnType" (3)
For SQL, the default return type is "Dataset":
db = DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]]ExternalEvaluate[db, "SELECT 2"] === ExternalEvaluate[{db, "ReturnType" -> "Dataset"}, "SELECT 2"]ExternalEvaluate[db, "select officeCode as pk, phone from offices"]"ReturnType" can be used to return data in a different form:
ExternalEvaluate[{db, "ReturnType" -> "Rows"}, "select officeCode as pk, phone from offices"]ExternalEvaluate[{db, "ReturnType" -> "NamedRows"}, "select officeCode as pk, phone from offices"]ExternalEvaluate[{db, "ReturnType" -> "Columns"}, "select officeCode as pk, phone from offices"]ExternalEvaluate[{db, "ReturnType" -> "NamedColumns"}, "select officeCode as pk, phone from offices"]Regardless of the "ReturnType", basic types such as integers, reals and strings are automatically converted:
ExternalEvaluate[DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]], "SELECT 'John' as name, 22 as age, 78.3 as weight"
]You can use connectionreturntype as a shorthand to specify the "ReturnType":
db = DatabaseReference[FindFile["ExampleData/ecommerce-database.sqlite"]];ExternalEvaluate[db -> "NamedColumns", "select officeCode as pk, phone from offices"]"Evaluator" (1)
Evaluate SQL queries using a specified "Evaluator":
ExternalEvaluate[{"SQL", "Evaluator" -> FindFile["ExampleData/ecommerce-database.sqlite"]}, "select 2+2 as result"
]When using a string or a File wrapper, an SQLite connection will be opened:
ExternalEvaluate[{"SQL", "Evaluator" -> File[FindFile["ExampleData/ecommerce-database.sqlite"]]}, "select 2+2 as result"
]"Evaluator" can also be specified by using a URL wrapper:
ExternalEvaluate[{"SQL", "Evaluator" -> URL["postgres://postgres:postgres@localhost/template1"]}, "SELECT NOW() as now, NOW()::date as date, interval '1 day' as interval, '1.23'::decimal as decimal"
]ExternalEvaluate[{"SQL", "Evaluator" -> DatabaseReference[<|"Backend" -> "postgres", "Name" -> "template1", "Port" -> None, "Host" -> "localhost", "Username" -> "postgres", "Password" -> "postgres"|>]}, "SELECT NOW() as now, NOW()::date as date, interval '1 day' as interval, '1.23'::decimal as decimal"
]"SessionProlog" (1)
"SessionEpilog" (1)
Use "SessionEpilog" to perform a side effect at the end of a session.
makeLoggerCommand[s_String] := <|"Command" -> "INSERT INTO db_access(unixtime, type) VALUES (``, ``)", "TemplateArguments" :> {UnixTime[], s}|>connection = {
"SQL",
"Evaluator" -> FindFile["ExampleData/ecommerce-database.sqlite"],
"SessionProlog" -> "CREATE TABLE IF NOT EXISTS db_access (id INTEGER PRIMARY KEY AUTOINCREMENT, unixtime INTEGER, type STRING);",
"SessionEpilog" -> makeLoggerCommand["SessionEpilog"]
};ExternalEvaluate[connection, "SELECT 'hello' as msg"]ExternalEvaluate[connection, "SELECT * from db_access where type == 'SessionEpilog'"]"Prolog" (1)
Use "Prolog" to perform a side effect before every evaluation:
makeLoggerCommand[s_String] := <|"Command" -> "INSERT INTO db_access(unixtime, type) VALUES (``, ``)", "TemplateArguments" :> {UnixTime[], s}|>connection = {
"SQL",
"Evaluator" -> FindFile["ExampleData/ecommerce-database.sqlite"],
"SessionProlog" -> "CREATE TABLE IF NOT EXISTS db_access (id INTEGER PRIMARY KEY AUTOINCREMENT, unixtime INTEGER, type STRING);",
"Prolog" -> makeLoggerCommand["Prolog"]
};ExternalEvaluate[connection, "SELECT * from db_access where type == 'Prolog'"]"Epilog" (1)
Use "Epilog" to perform a side effect after every evaluation:
makeLoggerCommand[s_String] := <|"Command" -> "INSERT INTO db_access(unixtime, type) VALUES (``, ``)", "TemplateArguments" :> {UnixTime[], s}|>connection = {
"SQL",
"Evaluator" -> FindFile["ExampleData/ecommerce-database.sqlite"],
"SessionProlog" -> "CREATE TABLE IF NOT EXISTS db_access (id INTEGER PRIMARY KEY AUTOINCREMENT, unixtime INTEGER, type STRING);",
"Epilog" -> makeLoggerCommand["Epilog"]
};ExternalEvaluate[connection, "select 'hello' as msg"]ExternalEvaluate[connection, "SELECT * from db_access where type == 'Epilog'"]Command Options (8)
"Command" (4)
When only a string is provided, the query is directly executed:
ExternalEvaluate["SQL", "SELECT 21 as age"]This is equivalent to writing the command using this form:
ExternalEvaluate["SQL", <|"Command" -> "SELECT 21 as age"|>]Use a File wrapper to run the code in file:
path = Export[CreateFile[], "select 21 as age", "Text"]ExternalEvaluate["SQL", <|"Command" -> File[path]|>]In most cases, you can omit the Association:
ExternalEvaluate["SQL", File[path]]Use the URL wrapper to directly run code hosted online:
query = URL["https://exampledata.wolfram.com/script.sql"]ExternalEvaluate["SQL", <|"Command" -> query|>]In most cases, you can omit the Association:
ExternalEvaluate["SQL", query]Put code in a CloudObject:
cloudObj = CloudExport["select 21 as age", "Text", CloudObject["hello-world-sql"]]Evaluate directly from the cloud:
ExternalEvaluate["SQL", <|"Command" -> cloudObj|>]In most cases, you can omit the Association:
ExternalEvaluate["SQL", cloudObj]"ReturnType" (1)
By default, the command is executed using the "ReturnType" specified during the session creation:
ExternalEvaluate[
{"SQL", "ReturnType" -> "Rows"},
"select 21 as age, 'john' as name"
]Specifying a "ReturnType" in the command overrides the "ReturnType" for the session:
ExternalEvaluate[
{"SQL", "ReturnType" -> "Rows"},
{
<|"Command" -> "select 21 as age, 'john' as name"|>,
<|"Command" -> "select 21 as age, 'john' as name", "ReturnType" -> "NamedColumns"|>
}
]Use "Tabular" to return a Tabular object.
ExternalEvaluate[
{"SQL", "ReturnType" -> "Tabular"},
"select 21 as age, 'john' as name"
]"TemplateArguments" (3)
When running a command, you can inline a TemplateExpression:
x = RandomReal[]
ExternalEvaluate["SQL", "SELECT <* x *> as real"]You can explicitly fill TemplateSlot using "TemplateArguments":
ExternalEvaluate[
"SQL",
<|"Command" -> "SELECT `1` as real, `2` as integer", "TemplateArguments" -> {RandomReal[], RandomInteger[]}|>
]When a non-list argument is provided, a single template argument is passed to the template:
ExternalEvaluate[
"SQL",
<|"Command" -> "SELECT `` as real", "TemplateArguments" -> RandomReal[]|>
]You can name template slots and use an Association to pass named arguments to the template:
ExternalEvaluate[
"SQL",
<|"Command" -> "SELECT `r` as real, `int` as integer", "TemplateArguments" -> <|"r" -> RandomReal[], "int" -> RandomInteger[]|>|>
]Applications (2)
DatabaseReference can also represent an in-memory SQLite database:
ExternalEvaluate[
DatabaseReference[<|"Backend" -> "sqlite"|>], "SELECT time('now') as now, sqlite_version() AS version"
]All operations done during an in-memory session are lost at the end of an ExternalEvaluate call:
ExternalEvaluate[
DatabaseReference[<|"Backend" -> "sqlite"|>], {
"CREATE TABLE t(x INTEGER PRIMARY KEY ASC, y, z);",
"INSERT INTO t(x, y, z) VALUES (1, 2, 3)",
"INSERT INTO t(x, y, z) VALUES (4, 5, 6)",
"SELECT * FROM t"
}]ExternalEvaluate[
DatabaseReference[<|"Backend" -> "sqlite"|>],
"SELECT * FROM t"
]Operations that are doing side effects on the database typically return Null:
ExternalEvaluate[
DatabaseReference[<|"Backend" -> "sqlite"|>], {
"CREATE TEMPORARY TABLE t(x INTEGER PRIMARY KEY ASC, y, z);",
"INSERT INTO t(x, y, z) VALUES (1, 2, 3)"
}]For some back ends, it is possible to insert data and specify a return value:
ExternalEvaluate[
DatabaseReference["postgresql://localhost/template1"], {
"CREATE TEMPORARY TABLE test_data(
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL
)",
"INSERT INTO test_data(name) VALUES ('john') RETURNING(\"id\") as pk",
"SELECT id, name FROM test_data"
}]Possible Issues (1)
Usually a database returns dates using the server time zone:
db = DatabaseReference[URL["postgres://localhost/template1"]];ExternalEvaluate[db -> "Rows", "SELECT NOW()"]Change the query to return a column at a particular time zone:
ExternalEvaluate[db -> "Rows", "SELECT NOW() AT TIME ZONE 'UTC'"]Or "SessionProlog" can be used to set a default time zone:
ExternalEvaluate[<|"Evaluator" -> db, "System" -> "SQL", "SessionProlog" -> "SET TIME ZONE 'UTC'", "ReturnType" -> "Rows"|>, "SELECT NOW()"]See Also
ExternalEvaluate StartExternalSession DatabaseReference
Database Connections: SQLite MicrosoftSQL MySQL Oracle PostgreSQL
External Evaluation Systems: SQL-JDBC
Related Guides
History
Introduced in 2020 (12.2)