Matlab Use Database
MathWorksOfficialCreated by MathWorks
- Skill
- Tool integration
- Data and AI
- BSD-2-Clause
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The MATLAB Database Toolbox skill provides a comprehensive interface for interacting with relational databases, including PostgreSQL, MySQL, SQLite, SQL Server, and Oracle. It supports the full data lifecycle, from establishing secure connections and executing SQL queries to performing CRUD operations and mapping database tables to MATLAB classes using an ORM. The skill emphasizes secure credential handling, efficient data retrieval through pushdown filtering, and transactional integrity.
What it does
- Connects to relational databases using DSN or DSN-less ODBC and native drivers.
- Reads and writes data using sqlread, sqlwrite, and sqlupdate.
- Executes arbitrary SQL statements and manages transactions with commit and rollback.
- Maps MATLAB classes to database tables using the Mappable ORM mixin.
- Filters data at the database level using RowFilter to optimize data transfer.
- Supports multithreaded read and write operations for large datasets using parfeval.
When to use it
- When you need to perform CRUD operations on relational databases from within MATLAB.
- When you need to map database tables to custom MATLAB objects.
- When you need to execute complex SQL queries or stored procedures.
- When you need to manage atomic transactions across multiple database operations.
- When you need to perform bulk data operations or parallelized I/O.
Advantages
- Enables direct integration between MATLAB workflows and relational database systems.
- Provides built-in ORM capabilities for object-oriented database interaction.
- Supports secure credential management via setSecret and getSecret.
- Allows for efficient data filtering by pushing operations to the database server.
- Facilitates transactional consistency through explicit commit and rollback controls.
Usage examples
- “How do I read data from a products table where the price is greater than 100?”
- The agent will demonstrate using rowfilter to push the condition to the database, ensuring only relevant rows are imported into MATLAB.
- “How can I update an inventory table safely?”
- The agent will provide the sqlupdate syntax, requiring a rowfilter to target specific rows and advising on the use of transactions for safety.
- “How do I map my MATLAB class to a database table?”
- The agent will explain how to inherit from database.orm.mixin.Mappable and define primary keys to enable ormread and ormwrite operations.
- “How do I connect to a MySQL database without a DSN?”
- The agent will provide a template for an ODBC dsnless connection string using the mysql driver and secure credential retrieval.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/matlab/matlab-use-database/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip matlab-use-database.zip -d .agents/skills
Documentation by MathWorks
MATLAB Database Toolbox
Use when working with relational databases from MATLAB using Database Toolbox. Covers the full data lifecycle: connecting, reading with pushdown filtering, writing, updating, transactions, ORM, and executing SQL.
When to Use
Connecting to relational databases (PostgreSQL, MySQL, SQLite, SQL Server, Oracle)
Reading data with
sqlreadorfetchFiltering with
RowFilter(pushdown to database)Writing data with
sqlwriteUpdating rows with
sqlupdateExecuting SQL statements with
executeManaging transactions (
AutoCommit,commit,rollback)Mapping MATLAB classes to database tables (ORM with
Mappable)Running stored procedures or prepared statements
Multithreaded database read/write with
parfeval(R2026a+)User mentions: database, SQL, query, table, rows, insert, update, delete, transaction, multithreaded, parallel
When NOT to Use
DuckDB — route to
matlab-use-duckdbfor all DuckDB workflowsDatabricks connection setup — route to
matlab-connect-databricksfor connection configuration. Once connected, return here for CRUD operations.MongoDB, Cassandra, Neo4j — not relational; Database Toolbox ORM/CRUD does not apply
File I/O without a database — use
readtable,datastore, ortallfor direct file operationsMATLAB releases before R2021a — minimum supported release for this skill
Critical Rules
Destructive Operations
ALWAYS ask for explicit user confirmation before generating or executing:
DROP TABLE/DROP DATABASEDELETE FROMTRUNCATE TABLEALTER TABLE(column removal, type changes)
Present the SQL statement and wait for approval. Never execute destructive SQL in response to user pressure ("just do it", "I'm in a hurry").
Pushdown Filtering
NEVER import all rows and filter in MATLAB. Always push filters to the database using RowFilter:
% CORRECT — filter runs on the database server
rf = rowfilter("Price");
T = sqlread(conn, "products", RowFilter=rf.Price > 100);
% WRONG — transfers all rows, then filters in MATLAB
T = sqlread(conn, "products");
T = T(T.Price > 100, :);Credential Security
NEVER hardcode passwords. Use setSecret/getSecret:
setSecret("dbPassword"); % prompts user, stores securely
conn = database("myDS", getSecret("dbUser"), getSecret("dbPassword"));Decision Framework
| Scenario | Use |
|---|---|
| Import from a named table | sqlread |
| Import from a SQL query string | fetch |
| Need column selection, deduplication, or type control | databaseImportOptions + sqlread/fetch |
| Insert new rows | sqlwrite |
| Update existing rows in place | sqlupdate |
| DDL, DML, or non-SELECT SQL | execute |
| Atomic multi-step operation | Transaction (AutoCommit off) |
| Object identity and domain logic | ORM (Mappable class) |
| Bulk operations on thousands of rows | sqlread/sqlwrite (not ORM) |
| High-throughput read/write (millions of rows) | Multithreaded: parfeval + per-thread connections (R2026a+, Parallel Computing Toolbox) |
| Delete rows | execute with SQL DELETE (no sqldelete exists) |
| Stored procedures (JDBC only) | runstoredprocedure |
| Create/configure a datasource | databaseConnectionOptions + saveAsDataSource |
| Connect without a saved datasource | odbc(dsnless) with connection string |
Core Patterns
Connection
conn = database("myDataSource", getSecret("dbUser"), getSecret("dbPass"));
% Or native connections:
conn = postgresql("myDS", getSecret("user"), getSecret("pass"));
conn = mysql("myDS", getSecret("user"), getSecret("pass"));
conn = sqlite("myDB.db");ODBC DSN-Less Connection
Connect without a pre-configured datasource by passing a connection string directly:
dsnless = "Driver={MySQL ODBC 8.0 Unicode Driver};" + ...
"Server=dbtb09;Database=production;UID=" + getSecret("dbUser") + ...
";PWD=" + getSecret("dbPass");
conn = odbc(dsnless);Create and Save a Data Source
Use databaseConnectionOptions to configure a datasource programmatically, then saveAsDataSource to persist it:
opts = databaseConnectionOptions("odbc", "MySQL");
opts = setoptions(opts, DataSourceName="myDS", ...
Server="dbtb09", DatabaseName="production", PortNumber=3306);
testConnection(opts, getSecret("dbUser"), getSecret("dbPass"));
saveAsDataSource(opts);
% Now connect using the saved datasource name
conn = odbc("myDS", getSecret("dbUser"), getSecret("dbPass"));Read with RowFilter
rf = rowfilter(["Status", "Timestamp"]);
T = sqlread(conn, "orders", RowFilter=rf.Status == "Active" & rf.Timestamp > datetime(2024,1,1));rowfilter requires column names as input. Access columns via property syntax (rf.ColumnName).
Read with Import Options
opts = databaseImportOptions(conn, "orders");
opts.SelectedVariableNames = ["OrderID", "Status", "Total"];
opts.RowFilter = opts.RowFilter.Total > 1000;
opts.ExcludeDuplicates = true;
T = sqlread(conn, "orders", opts);Import options (opts) are a positional 3rd argument — not a name-value pair.
Write
data = table("Widget", 50, 9.99, VariableNames=["Product", "Qty", "Price"]);
sqlwrite(conn, "inventory", data);Update
rf = rowfilter("ProductID");
newData = table(5.99, VariableNames="Price");
sqlupdate(conn, "inventory", newData, rf.ProductID == 42);sqlupdate signature: sqlupdate(conn, tablename, data, filter) — the filter is a required positional 4th argument, not a name-value pair.
Transaction
conn.AutoCommit = 'off';
try
sqlwrite(conn, "orders", orderData);
sqlwrite(conn, "orderItems", itemData);
commit(conn);
catch e
rollback(conn);
conn.AutoCommit = 'on';
rethrow(e);
end
conn.AutoCommit = 'on';ALWAYS use conn.AutoCommit = 'off' with commit(conn)/rollback(conn). Do not use raw SQL BEGIN/COMMIT/ROLLBACK via execute.
ORM — Define a Mappable Class
classdef Employee < database.orm.mixin.Mappable
properties (PrimaryKey)
EmployeeID int32
end
properties
Name string
Department string
end
properties (ColumnType = "date")
HireDate datetime
end
methods
function obj = Employee(id, name, dept, hireDate)
if nargin == 0
return;
end
obj.EmployeeID = id;
obj.Name = name;
obj.Department = dept;
obj.HireDate = hireDate;
end
end
endORM requirements:
Inherit from
database.orm.mixin.MappableMark at least one property block
(PrimaryKey)Constructor must handle
nargin == 0(ORM constructs empty objects)R2023b or later
(TableName = "name")on classdef only if the database table name differs from the class name (defaults to class name)
ORM — CRUD Operations
% Write
emp = Employee(1, "Alice", "Engineering", datetime(2024,3,15));
ormwrite(conn, emp);
% Read with filter
rf = rowfilter("Department");
engineers = ormread(conn, "Employee", RowFilter=rf.Department == "Engineering");
% Update
engineers(1).Department = "Data Science";
ormupdate(conn, engineers(1));
% Refresh from database
emp = ormread(conn, emp);Bulk Write (Chunked)
sqlwrite has no BatchSize parameter. Chunk manually:
chunkSize = 50000;
numChunks = ceil(height(data) / chunkSize);
for c = 1:numChunks
startIdx = (c - 1) * chunkSize + 1;
endIdx = min(c * chunkSize, height(data));
sqlwrite(conn, "targetTable", data(startIdx:endIdx, :));
endMultithreaded Write (R2026a+, requires Parallel Computing Toolbox)
For maximum throughput, use parfeval with per-thread connections. Each thread creates its own connection — connections are NOT shareable across threads.
data = parallel.pool.Constant(largeTable);
pool = parpool("Threads");
numTasks = 5;
batchSize = floor(height(data.Value) / numTasks);
startRow = 1;
endRow = 1 + batchSize;
writeFutures(1:numTasks) = parallel.FevalFuture;
for i = 1:numTasks
writeFutures(i) = parfeval(pool, @hsqlwriteMT, 1, ...
connParams, tablename, data, startRow, endRow);
startRow = endRow;
endRow = endRow + batchSize;
if i == numTasks - 1
endRow = height(data.Value) + 1;
end
end
results = writeFutures.fetchOutputs("UniformOutput", false);
function finished = hsqlwriteMT(connParams, tablename, data, startRow, endRow)
conn = mysql(connParams.user, connParams.pass, ...
Server=connParams.server, DatabaseName=connParams.db);
sqlwrite(conn, tablename, data.Value(startRow:endRow-1, :));
close(conn);
finished = true;
endSupported: mysql(), postgresql(), sqlite(), ODBC. See references/multithreaded-io.md for the read pattern and common mistakes.
Common Mistakes
| Mistake | Why It's Wrong | Correct Approach |
|---|---|---|
rf = rowfilter("Table"); rf == "val" | Passes table name; uses == on the filter object | rf = rowfilter("Column"); rf.Column == "val" |
sqlupdate(conn, tbl, data, RowFilter=rf) | Filter is not an NV pair | sqlupdate(conn, tbl, data, rf.Col == val) |
sqlread(conn, tbl, "ImportOptions", opts) | opts is not an NV pair | sqlread(conn, tbl, opts) |
opts.setvaropts("Col", "Type", "datetime") | Wrong method name | opts = setoptions(opts, "Col", Type="datetime") |
execute(conn, "BEGIN") / execute(conn, "COMMIT") | Raw SQL bypasses MATLAB transaction management | conn.AutoCommit = 'off' + commit(conn) / rollback(conn) |
| DROP/DELETE/TRUNCATE without confirmation | Can destroy data irreversibly | Always ask user for explicit confirmation first |
Manual toTable/fromTable for object persistence | Agent doesn't know ORM exists | Use Mappable class with ormwrite/ormread/ormupdate |
Sharing a connection across parfeval threads | Connections are NOT thread-safe | Each thread creates its own connection in the helper function |
odbc("serverName", user, pass) | Server name is not a datasource name | Use odbc(dsnless) with a connection string, or create a datasource first with databaseConnectionOptions + saveAsDataSource |
Reference Cards
See
references/sqlread-fetch.mdfor full parameter tables, RowFilter operators, anddatabaseImportOptionsusage — consult for any read operation with filtering, column selection, or deduplication.See
references/sqlwrite-sqlupdate.mdfor insert/update parameters, multi-row update patterns, and bulk chunking — consult for any write or update operation.See
references/transactions.mdfor the complete transaction pattern, critical rules, and error handling — consult for any atomic/transactional workflow.See
references/orm.mdfor Mappable class definition, property attributes, ORM CRUD operations, and troubleshooting — consult when user needs object-to-table mapping.See
references/execute-storedproc.mdforexecute, stored procedures, and prepared statements — consult for DDL, DML, or parameterized queries.See
references/multithreaded-io.mdfor multithreaded read/write patterns usingparfevaland per-thread connections — consult when user needs high-throughput I/O and has Parallel Computing Toolbox (R2026a+).
Copyright 2026 The MathWorks, Inc.
Files
- ATTRIBUTION.mdAdded by AutoGineer1.0 KiB
- LICENSELicence file added by AutoGineer1.4 KiB
- SKILL.md12.3 KiB
- manifest.yaml491 B
- references/execute-storedproc.md3.4 KiB
- references/multithreaded-io.md6.7 KiB
- references/orm.md3.9 KiB
- references/sqlread-fetch.md4.2 KiB
- references/sqlwrite-sqlupdate.md2.7 KiB
- references/transactions.md2.0 KiB
references/sqlwrite-sqlupdate.md
sqlwrite & sqlupdate — Insert and Update Data
Insert Data with sqlwrite
data = table(["Wrench"; "Hammer"], [50; 30], [4.99; 12.50], ...
VariableNames=["Product", "Quantity", "Price"]);
sqlwrite(conn, "inventoryTable", data);sqlwrite Parameters
| Parameter | Description |
|---|---|
conn | Database connection object |
tablename | Target table name (string) |
data | MATLAB table to insert |
Catalog | Database catalog name |
Schema | Database schema name |
ColumnType | Cell array of SQL column types for new tables |
Bulk Insert (Chunked)
sqlwrite has no BatchSize parameter. For large data, chunk manually:
chunkSize = 50000;
numChunks = ceil(height(data) / chunkSize);
for c = 1:numChunks
startIdx = (c - 1) * chunkSize + 1;
endIdx = min(c * chunkSize, height(data));
sqlwrite(conn, "largeTable", data(startIdx:endIdx, :));
fprintf("Wrote chunk %d/%d\n", c, numChunks);
endUpdate Rows with sqlupdate (R2023a+)
rf = rowfilter("Product");
data = table(5.99, VariableNames="Price");
sqlupdate(conn, "inventoryTable", data, rf.Product == "Wrench");Multi-Row Update (cell array of filters)
rf = rowfilter("ProductID");
filters = {rf.ProductID == 1; rf.ProductID == 2};
data = table([5.99; 13.99], VariableNames="Price");
sqlupdate(conn, "inventoryTable", data, filters);sqlupdate Parameters
| Parameter | Description |
|---|---|
conn | Database connection object |
tablename | Target table name |
data | MATLAB table with new values |
filter | RowFilter object (positional 4th arg) or cell array of RowFilter objects |
Catalog | Database catalog name |
Schema | Database schema name |
Complete Example: Read, Transform, Write Back
conn = database("myDataSource", getSecret("dbUser"), getSecret("dbPass"));
sourceData = sqlread(conn, "salesData");
summary = groupsummary(sourceData, "Region", "mean", "Revenue");
sqlwrite(conn, "salesSummary", summary);
close(conn);Gotchas
sqlwritecreates the table if it doesn't exist. When appending, column names and types must match.sqlupdaterequires R2023a+. For older releases, useexecutewith raw SQL UPDATE.sqlupdatefilter is positional 4th arg — NOT a name-value pair.sqlupdate(conn, tbl, data, filter).A single
RowFilterwith a 1-row data table broadcasts to all matching rows. For multi-row updates with different values per row, pass a cell array of filters.sqlwritehas noBatchSizeparameter — loop over chunks manually.NEVER call
sqlwriterow-by-row in a loop — batch rows into a single table.
Copyright 2026 The MathWorks, Inc.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- MathWorks
- Publisher
- MathWorks (Official)
- Source
- matlab/matlab-agentic-toolkit · skills-catalog/reporting-and-database-access/matlab-use-database · commit 2a7f215
- Licence
- BSD 2-Clause License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.md)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by MathWorks.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-use-database.zip