SQLExecute[conn,command]
executes a command in an SQL connection.
SQLExecute[conn,command,args]
passes arguments to the command.
SQLExecute[SQLSelect[conn,...]]
manages the opening and closing of conn.
SQLExecute
SQLExecute[conn,command]
executes a command in an SQL connection.
SQLExecute[conn,command,args]
passes arguments to the command.
SQLExecute[SQLSelect[conn,...]]
manages the opening and closing of conn.
Details and Options
- To use SQLExecute, you first need to load DatabaseLink using Needs["DatabaseLink`"].
- Use this function with caution, as you can lose data permanently!
- Options support and behavior varies with driver, driver version, and RDBMS type.
- Returns an integer specifying the number of rows affected by the query. Returns $Failed if an error is encountered when dropping a table.
- The following options can be given:
-
"ColumnSymbols" None symbols to be associated with results "EscapeProcessing" True translate escaped JDBC function syntax "FetchSize" Automatic JDBC driver hint for filling result sets "GetAsStrings" False return all results as strings "GetGeneratedKeys" False return keys associated with updated records "MaxFieldSize" Automatic byte limit for variable-length column types "MaxRows" Automatic the maximum number of rows to return "ShowColumnHeadings" False whether to return headings with the results "Timeout" $SQLTimeout the timeout for the query "BatchSize" 1000 queries with parameters will be processed incrementally in batches of this size "JavaBatching" True perform parameter batching in Java layer instead of Wolfram Language layer
Examples
open all close allBasic Examples (1)
Needs["DatabaseLink`"]If you find that the examples in this section do not work as shown, you may need to install or restore the example database with the DatabaseLink`DatabaseExamples` package, as described in Using the Example Databases.
conn = OpenSQLConnection["demo"];SQLExecute[conn, "SELECT * FROM SAMPLETABLE1"]SQLExecute[conn, "CREATE TABLE TEST (X INTEGER, Y DOUBLE)"]SQLExecute[conn, "INSERT INTO TEST (X,Y) VALUES (2, 6.7)"]SQLExecute[conn, "INSERT INTO TEST (X,Y) VALUES (`1`, `2`)", {5, 2.1}]SQLExecute[conn, "SELECT * FROM TEST"]SQLExecute[conn, "UPDATE TEST SET Y=6.8"]SQLExecute[conn, "SELECT * FROM TEST"]SQLExecute[conn, "DELETE FROM TEST"]SQLExecute[conn, "DROP TABLE TEST"]CloseSQLConnection[conn];Scope (5)
Selecting Data (1)
Needs["DatabaseLink`"]conn = OpenSQLConnection["publisher"];Select data matching a condition:
SQLExecute[conn, "SELECT * FROM ROYSCHED WHERE ROYALTY >= .11 AND ROYALTY <= .12"]Select the same data using a prepared statement:
SQLExecute[conn, "SELECT * FROM ROYSCHED WHERE ROYALTY >= `1` AND ROYALTY <= `2`", {0.11, 0.12}]Specify a column in a prepared statement:
SQLExecute[conn, "SELECT `1` FROM ROYSCHED WHERE TITLE_ID = `2`", {SQLColumn["ROYALTY"], "BS1011"}]Give a sequence of arguments in a prepared statement:
SQLExecute[conn, "SELECT `1` FROM ROYSCHED WHERE TITLE_ID = `2`", {SQLArgument[SQLColumn["LORANGE"], SQLColumn["HIRANGE"], SQLColumn["ROYALTY"]], "BS1011"}]Apply a database function to the selected data:
SQLExecute[conn, "SELECT COUNT(ROYALTY) FROM ROYSCHED"]SQLExecute[conn, "SELECT MIN(ROYALTY) FROM ROYSCHED"]SQLExecute[conn, "SELECT ROYALTY * 2 FROM ROYSCHED"]SQLExecute[conn, "SELECT ROYALTY / 10 FROM ROYSCHED"]SQLExecute[conn, "SELECT -ROYALTY FROM ROYSCHED"]SQLExecute[conn, "SELECT DISTINCT ROYALTY FROM ROYSCHED"]SQLExecute[conn, "SELECT TITLE_ID, MIN(ROYALTY) FROM ROYSCHED GROUP BY TITLE_ID"]SQLExecute[conn, "SELECT TOP 5 * FROM ROYSCHED"]SQLExecute[conn, "SELECT LIMIT 5 10 * FROM ROYSCHED"]Join data from multiple tables:
SQLExecute[conn, "SELECT DISTINCT TITLES.TITLE FROM TITLES INNER JOIN ROYSCHED ON TITLES.TITLE_ID=ROYSCHED.TITLE_ID WHERE TITLES.PUB_ID='0877' AND ROYSCHED.ROYALTY > .1"]CloseSQLConnection[conn];Creating Tables (1)
Needs["DatabaseLink`"]conn = OpenSQLConnection["demo"];SQLExecute[conn,
"CREATE TABLE ADDRESSES (
USERNAME VARCHAR(32) NOT NULL PRIMARY KEY,
ADDRESS VARCHAR(128),
CITY VARCHAR(64),
ZIPCODE VARCHAR(12),
UNIQUE (ADDRESS, CITY, ZIPCODE))"]SQLExecute[conn, "CREATE TABLE MAILER (
MAILERID INT IDENTITY,
USERNAME VARCHAR(21) NOT NULL,
SENDMAILER BIT DEFAULT '1' NOT NULL,
FOREIGN KEY (USERNAME) REFERENCES ADDRESSES (USERNAME))"]SQLExecute[conn, "DROP TABLE MAILER"];SQLExecute[conn, "DROP TABLE ADDRESSES"];CloseSQLConnection[conn];Updating Data (1)
Needs["DatabaseLink`"]conn = OpenSQLConnection["demo"];SQLExecute[conn, "CREATE TABLE TEST (X INTEGER, Y DOUBLE)"];SQLExecute[conn, "INSERT INTO TEST (X, Y) VALUES (4, 8.3)"];SQLExecute[conn, "INSERT INTO TEST (X, Y) VALUES (3, 9.1)"];Update data matching a condition:
SQLExecute[conn, "UPDATE TEST SET X = 7 WHERE Y < 9"]SQLExecute[conn, "SELECT * FROM TEST"]SQLExecute[conn, "UPDATE TEST SET X = `1` WHERE Y >= `2`", {6, 9}]SQLExecute[conn, "SELECT * FROM TEST"]SQLExecute[conn, "DROP TABLE TEST"];CloseSQLConnection[conn];Deleting Data (1)
Needs["DatabaseLink`"]conn = OpenSQLConnection["demo"];SQLExecute[conn, "CREATE TABLE TEST (X INTEGER, Y DOUBLE)"];SQLExecute[conn, "INSERT INTO TEST (X, Y) VALUES (4, 8.3)"];SQLExecute[conn, "INSERT INTO TEST (X, Y) VALUES (3, 9.1)"];SQLExecute[conn, "INSERT INTO TEST (X, Y) VALUES (1, 1.6)"];Delete data matching a condition:
SQLExecute[conn, "DELETE FROM TEST WHERE X = 1"]SQLExecute[conn, "DELETE FROM TEST WHERE Y = `1`", {8.3}]SQLExecute[conn, "DROP TABLE TEST"];CloseSQLConnection[conn];Working with Dates and Times (1)
Needs["DatabaseLink`"]Date and time data may be given in a query using DateObject, TimeObject or SQLDateTime. Create a table with DATE, TIME, and DATETIME column types:
conn = OpenSQLConnection[JDBC["HSQL(Memory)", "temp"]];SQLCreateTable[conn, SQLTable["DateTimeTable"], {
SQLColumn["Col1", "DataTypeName" -> "DATE"], SQLColumn["Col2", "DataTypeName" -> "TIME"],
SQLColumn["Col3", "DataTypeName" -> "DATETIME"]}]SQLExecute[conn, "INSERT INTO DateTimeTable (Col1, Col2, Col3) VALUES (`1`)", {SQLArgument[DateObject[], TimeObject[], SQLDateTime[DateList[]]]}]Selected date and time data will return with head SQLDateTime:
dat = SQLSelect[conn, SQLTable["DateTimeTable"]]Express the selected data in its original form:
Inner[Apply, {DateObject, TimeObject, Identity}, First@dat, List]CloseSQLConnection[conn];Generalizations & Extensions (1)
Options (11)
"ColumnSymbols" (1)
Needs["DatabaseLink`"]Supply a list of symbols for query results to be assigned to:
conn = OpenSQLConnection["demo"];Clear[entries, values, names];SQLExecute[conn, "SELECT ENTRY, VALUE, NAME FROM SAMPLETABLE1", "ColumnSymbols" -> {entries, values, names}];entriesvaluesnamesSQLExecute[conn, "SELECT ENTRY, VALUE, NAME FROM SAMPLETABLE1", "ColumnSymbols" -> Automatic];Names["Global`*"]Global`col1Global`col2Global`col3Supply a function to operate on column names and results. If column headings have not been requested, the first argument to the function will be Null:
SQLExecute[conn, "SELECT ENTRY, VALUE FROM SAMPLETABLE1", "ShowColumnHeadings" -> True,
"ColumnSymbols" -> Function[{cols, res},
With[{syms = Symbol["SAMPLETABLE1" <> #]& /@ cols},
Evaluate[syms] = Transpose[res]
]
]
]SAMPLETABLE1ENTRYSAMPLETABLE1VALUEClear@values;
SQLExecute[conn, "SELECT VALUE FROM SAMPLETABLE1", "ColumnSymbols" -> ((values = Flatten[#2])&)];valuesCloseSQLConnection[conn];"EscapeProcessing" (1)
Needs["DatabaseLink`"]The JDBC specification defines an escape call sequence for authoring queries that would otherwise require vendor-specific SQL. Set the "EscapeProcessing" option to employ defined escape syntax:
conn = OpenSQLConnection[JDBC["H2(Memory)", "sandbox"]];Issue a query using escaped SQL:
SQLExecute[conn, "SELECT {fn week({d '2014-01-08'})}", "EscapeProcessing" -> True]Issuing the query without escape processing results in an error:
SQLExecute[conn, "SELECT {fn week({d '2014-01-08'})}", "EscapeProcessing" -> False]SQL native to this RDBMS may be used without escape processing:
SQLExecute[conn, "SELECT extract(week from DATE '2014-01-08')", "EscapeProcessing" -> False]Issue a query using escaped SQL:
SQLExecute[conn, "SELECT {fn lcase('GIRAFFE')}", "EscapeProcessing" -> True]SQLExecute[conn, "SELECT lower('GIRAFFE')"]CloseSQLConnection[conn];Section 13.4 of the JDBC 4.0 Specification contains further information on escape processing and supported functions.
"FetchSize" (1)
Needs["JLink`"];
Needs["DatabaseLink`"];The "FetchSize" option suggests to the JDBC driver a number of rows to fetch on each visit to the database. Increasing this parameter reduces the amount of network traffic required to execute a query, at the cost of memory used:
AddToClassPath["/Users/me/Documents/DatabaseLink/drivers"];
connSpec = {JDBC["oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@server.domain.com:1521:xe"], Username -> "GUEST", Password -> "GUEST"};conn = OpenSQLConnection@@connSpecCompute memory in use, including both kernel and Java layers:
javaMem[] := Module[{rt},
LoadJavaClass["java.lang.Runtime"];
rt = Runtime`getRuntime[];
rt@totalMemory[](* allocated; some is free for jvm use *)
];
memReport[] := TableForm[List@{MemoryInUse[], javaMem[], MemoryInUse[] + javaMem[]}, TableHeadings -> {None, {"Kernel", "Java", "Total"}}]memReport[]Fetch a large result with small fetch size:
AbsoluteTiming[
ByteCount@SQLExecute[conn, "SELECT * FROM test_tab", "MaxRows" -> 20000, "FetchSize" -> 5]
]memReport[]CloseSQLConnection[conn];
ReinstallJava[];
conn = OpenSQLConnection@@connSpec;
memReport[]Fetch a large result with large fetch size:
AbsoluteTiming[
ByteCount@SQLExecute[conn, "SELECT * FROM test_tab", "MaxRows" -> 20000, "FetchSize" -> 10000]
]memReport[]CloseSQLConnection[conn];"GetAsStrings" (1)
Needs["DatabaseLink`"]Retrieve data without converting it to Wolfram Language types:
conn = OpenSQLConnection["demo"]SQLExecute[conn, "SELECT * FROM SAMPLETABLE1", "GetAsStrings" -> True]//InputFormCloseSQLConnection[conn];"GetGeneratedKeys" (1)
Needs["DatabaseLink`"]Open a connection to a data source that supports generated key retrieval:
conn = OpenSQLConnection["demo"]SQLConnectionInformation[conn, "SupportsGetGeneratedKeys"]Create a table with an auto-incrementing primary key:
SQLExecute[conn,
"CREATE TABLE PEOPLE (
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(128) DEFAULT 'Steve',
age INTEGER
)"]SQLExecute[conn, "INSERT INTO PEOPLE (name, age) VALUES ('Amy', 64), ('Jean', 47)",
"GetGeneratedKeys" -> True]SQLExecute[conn, "INSERT INTO PEOPLE (name, age) VALUES (?,?)",
{{"Amy", 64}, {"Jean", 47}},
"GetGeneratedKeys" -> True]Contents of the primary key column:
SQLExecute[conn, "SELECT id FROM PEOPLE"]SQLDropTable[conn, "PEOPLE"]CloseSQLConnection[conn];"MaxFieldSize" (1)
Needs["DatabaseLink`"]For some variable-length column types the "MaxFieldSize" option can be used to limit the number of bytes returned for a field:
conn = OpenSQLConnection[JDBC["Derby(Embedded)", FileNameJoin[{$TemporaryDirectory, "scratch"}]], "Properties" -> {"create" -> "true"}]Create a table with a VARCHAR field:
SQLExecute[conn, "CREATE TABLE STRINGS (string VARCHAR(512))"]SQLExecute[conn, "INSERT INTO strings (string) VALUES (?)", {StringTake[ExampleData[{"Text", "AeneidEnglish"}], 512]}
]Select string contents, limiting byte length of results:
res = SQLExecute[conn, "SELECT string FROM strings", "MaxFieldSize" -> 64]StringLength@res[[1, 1]]SQLDropTable[conn, "STRINGS"]CloseSQLConnection[conn];"MaxRows" (1)
Needs["DatabaseLink`"]Limit the number of rows returned in a result:
conn = OpenSQLConnection["publisher"];SQLExecute[conn, "SELECT COUNT(*) FROM AUTHORS"]SQLExecute[conn, "SELECT * FROM AUTHORS", "MaxRows" -> 5]//TableFormCloseSQLConnection[conn];"ShowColumnHeadings" (1)
Needs["DatabaseLink`"]Include column names as the first row of the results:
conn = OpenSQLConnection["publisher"];res = SQLExecute[conn, "SELECT * FROM AUTHORS", "ShowColumnHeadings" -> True, "MaxRows" -> 5];TableForm@resThe column headings are equivalent to the unqualified column names:
First@res === SQLColumnNames[conn, "AUTHORS"][[All, 2]]CloseSQLConnection[conn];"Timeout" (1)
Needs["DatabaseLink`"]Set a timeout value for a particular query:
conn = OpenSQLConnection[JDBC["MySQL(Connector/J))", "localhost/testdb"]]AbsoluteTiming@SQLExecute[conn, "SELECT SLEEP(5)", "Timeout" -> 3]CloseSQLConnection[conn];"BatchSize" (1)
Needs["DatabaseLink`"];
Needs["JLink`"];Adjust batch size to trade off memory use and speed when issuing queries with long parameter lists:
AddToClassPath["/Users/me/Documents/DatabaseLink/drivers"];
connSpec = {JDBC["oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@server.domain.com:1521:xe"], Username -> "GUEST", Password -> "GUEST"};conn = OpenSQLConnection@@connSpecSQLExecute[conn,
"CREATE TABLE SCRATCH(
A FLOAT,
B INTEGER,
C VARCHAR(128)
)"];Generate random data for insertion:
randomRows[n_] := Transpose[{RandomInteger[10000, n], RandomReal[1, n], RandomChoice[WordData[], n]}];data = randomRows[2 * 10 ^ 5];ByteCount@dataCompute memory in use, including both kernel and Java layers:
javaMem[] := Module[{rt},
LoadJavaClass["java.lang.Runtime"];
rt = Runtime`getRuntime[];
rt@totalMemory[](* allocated; some is free for jvm use *)
];
memReport[] := TableForm[List@{MemoryInUse[], javaMem[], MemoryInUse[] + javaMem[]}, TableHeadings -> {None, {"Kernel", "Java", "Total"}}]memReport[]Run a query with a small batch size, resulting in relatively light Java-side memory use:
AbsoluteTiming@SQLExecute[conn, "INSERT INTO SCRATCH (A, B, C) VALUES (?, ?, ?)",
data,
"BatchSize" -> 10
]//FirstmemReport[]SQLDelete[conn, "SCRATCH"];
CloseSQLConnection[conn];
ReinstallJava[];
conn = OpenSQLConnection@@connSpec;
memReport[]Rerun with larger batch size, necessitating fewer server trips:
AbsoluteTiming@SQLExecute[conn, "INSERT INTO SCRATCH (A, B, C) VALUES (?, ?, ?)",
data,
"BatchSize" -> 100000
]//FirstJava memory use is higher in this case:
memReport[]SQLDropTable[conn, "SCRATCH"]CloseSQLConnection[conn];"JavaBatching" (1)
Needs["DatabaseLink`"];
Needs["JLink`"];Switch parameter batching from Java layer to Wolfram Language layer to trade speed for memory:
AddToClassPath["/Users/me/Documents/DatabaseLink/drivers"];
connSpec = {JDBC["oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@server.domain.com:1521:xe"], Username -> "GUEST", Password -> "GUEST"};conn = OpenSQLConnection@@connSpecSQLExecute[conn,
"CREATE TABLE SCRATCH(
A FLOAT,
B INTEGER,
C VARCHAR(128)
)"];Generate random data for insertion:
randomRows[n_] := Transpose[{RandomInteger[10000, n], RandomReal[1, n], RandomChoice[WordData[], n]}];data = randomRows[5 * 10 ^ 4];ByteCount@dataCompute memory in use, including both kernel and Java layers:
javaMem[] := Module[{rt},
LoadJavaClass["java.lang.Runtime"];
rt = Runtime`getRuntime[];
rt@totalMemory[](* allocated; some is free for jvm use *)
];
memReport[] := TableForm[List@{MemoryInUse[], javaMem[], MemoryInUse[] + javaMem[]}, TableHeadings -> {None, {"Kernel", "Java", "Total"}}]memReport[]Run query with Java-side batching:
AbsoluteTiming@SQLExecute[conn, "INSERT INTO SCRATCH (A, B, C) VALUES (?, ?, ?)",
data,
"JavaBatching" -> True,
"BatchSize" -> 10
]//FirstmemReport[]SQLDelete[conn, "SCRATCH"];
CloseSQLConnection[conn];
ReinstallJava[];
conn = OpenSQLConnection@@connSpec;
memReport[]Run query with Wolfram Language-side batching:
AbsoluteTiming@SQLExecute[conn, "INSERT INTO SCRATCH (A, B, C) VALUES (?, ?, ?)",
data,
"JavaBatching" -> False,
"BatchSize" -> 10
]//FirstTotal memory use is lower in this case:
memReport[]SQLDropTable[conn, "SCRATCH"];CloseSQLConnection[conn];Possible Issues (1)
Needs["DatabaseLink`"]Retrieving generated keys from batch operations has driver- and RDBMS-dependent behavior. In many cases, only the last generated key is returned:
conn = OpenSQLConnection[JDBC["SQLite(Memory)", "genkeys"]];Create a table with an auto-incrementing primary key:
SQLCreateTable[conn, "PEOPLE", {
SQLColumn["ID", "DataTypeName" -> "INTEGER", "PrimaryKey" -> True],
SQLColumn["NAME", "DataTypeName" -> "VARCHAR", "DataLength" -> 128, "Default" -> "Steve"],
SQLColumn["AGE", "DataTypeName" -> "INTEGER"]
}];When using a parameterized SQLExecute with this RDBMS and driver, only the last generated key is returned:
SQLExecute[conn, "INSERT INTO PEOPLE (NAME, AGE) VALUES (?,?)",
{{"Amy", 64}, {"Jean", 47}},
"GetGeneratedKeys" -> True]SQLDropTable[conn, "PEOPLE"];CloseSQLConnection[conn];