| name | dbcli-exec |
| description | Execute INSERT, UPDATE, DELETE statements on 30+ databases using DbCli. Includes mandatory backup procedures before destructive operations. Use when user needs to modify data, insert records, update fields, or delete rows. Always create backups first. |
| license | MIT |
| compatibility | Requires DbCli CLI tool (based on .NET 10 and SqlSugar). Supports Windows, Linux, macOS. |
| metadata | {"tool":"dbcli","version":"1.0.0","category":"database","safety-level":"requires-backup","supported-databases":"30+"} |
| allowed-tools | dbcli |
Command Style (Use PATH)
All examples use the plain command name dbcli (no directory prefix).
Ensure dbcli is on PATH instead of hardcoding paths like .\.claude\skills\dbcli\dbcli.exe.
DbCli Exec Skill
Execute INSERT, UPDATE, DELETE (DML) operations on databases with mandatory backup procedures.
Supported Databases (DML)
exec is intended for SQL / relational databases supported by DbCli (SqlSugar providers). Examples include:
- SQL Server
- MySQL-family (MySQL, MariaDB, TiDB, OceanBase, etc.)
- PostgreSQL-family (PostgreSQL, GaussDB, Kingbase, etc.)
- SQLite
- Oracle
- IBM DB2
- DaMeng
For connection string examples and the full list, see skills/CONNECTION_STRINGS.md.
⚠️ CRITICAL SAFETY REQUIREMENT
ALWAYS CREATE BACKUPS BEFORE EXECUTING UPDATE/DELETE OPERATIONS
Backup naming convention:
- Table copy:
tablename_copy_YYYYMMDD_HHMMSS
- SQL export:
tablename_backup_YYYYMMDD_HHMMSS.sql
When to Use This Skill
- User wants to insert new records into a table
- User needs to update existing data
- User wants to delete records
- User mentions INSERT, UPDATE, DELETE, modify, change, or remove data
- Never use without creating backups first for UPDATE/DELETE
Command Syntax
export DBCLI_CONNECTION="CONNECTION_STRING"
export DBCLI_DBTYPE="DATABASE_TYPE"
dbcli exec "DML_STATEMENT" [-p JSON] [-P params.json]
Global Options
- Environment variable
DBCLI_CONNECTION: Database connection string (required)
- Environment variable
DBCLI_DBTYPE: Database type (default: sqlite)
Subcommand Options
-F, --file: Execute SQL from file instead of command line
-p, --params: JSON parameters object (use @Param placeholders)
-P, --params-file: Read JSON parameters from file
Safe Operation Workflow
INSERT Operations (No Backup Required)
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "INSERT INTO Users (Name, Email) VALUES ('Alice', 'alice@example.com')"
Parameterized Execute (RDB)
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "INSERT INTO Users (Id, Name) VALUES (@Id, @Name)" -p '{"Id":1,"Name":"Alice"}'
Notes:
- SQL Server supports
GO batch separators for exec when not using -p/-P (use -F for scripts).
- SQLite providers may require
DisableClearParameters: true in config (maps to SqlSugar IsClearParameters=false).
UPDATE Operations (Backup Required)
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
export DBCLI_CONNECTION="Data Source=app.db"
dbcli query "CREATE TABLE Users_copy_${TIMESTAMP} AS SELECT * FROM Users"
dbcli exec "UPDATE Users SET Email = 'newemail@example.com' WHERE Id = 1"
dbcli -f table query "SELECT * FROM Users WHERE Id = 1"
dbcli exec "DELETE FROM Users"
dbcli exec "INSERT INTO Users SELECT * FROM Users_copy_${TIMESTAMP}"
DELETE Operations (Backup Required)
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
export DBCLI_CONNECTION="Data Source=app.db"
dbcli export Users > Users_backup_${TIMESTAMP}.sql
dbcli exec "DELETE FROM Users WHERE inactive = 1"
dbcli query "SELECT COUNT(*) as remaining FROM Users"
dbcli exec -F Users_backup_${TIMESTAMP}.sql
INSERT Operations
Single Row Insert
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "INSERT INTO Users (Name, Email) VALUES ('John', 'john@example.com')"
export DBCLI_CONNECTION="Server=localhost;Database=mydb;Trusted_Connection=True"
export DBCLI_DBTYPE="sqlserver"
dbcli exec "INSERT INTO Users (Name, Email) VALUES ('John', 'john@example.com')"
export DBCLI_CONNECTION="Server=localhost;Database=mydb;Uid=root;Pwd=xxxxxxxxxx"
export DBCLI_DBTYPE="mysql"
dbcli exec "INSERT INTO Users (Name, Email) VALUES ('John', 'john@example.com')"
export DBCLI_CONNECTION="Host=localhost;Database=mydb;Username=postgres;Password=xxxxxxxxxx"
export DBCLI_DBTYPE="postgresql"
dbcli exec "INSERT INTO Users (Name, Email) VALUES ('John', 'john@example.com')"
export DBCLI_CONNECTION="Data Source=localhost:1521/XEPDB1;User Id=system;Password=xxxxxxxxxx"
export DBCLI_DBTYPE="oracle"
dbcli exec "INSERT INTO Users (Name, Email) VALUES ('John', 'john@example.com')"
export DBCLI_CONNECTION="Server=localhost:50000;Database=MYDB;UID=db2inst1;PWD=xxxxxxxxxx"
export DBCLI_DBTYPE="db2"
dbcli exec "INSERT INTO Users (Name, Email) VALUES ('John', 'john@example.com')"
export DBCLI_CONNECTION="Server=localhost;Database=MYDB;User Id=SYSDBA;Password=xxxxxxxxxx"
export DBCLI_DBTYPE="dm"
dbcli exec "INSERT INTO Users (Name, Email) VALUES ('John', 'john@example.com')"
Multiple Row Insert
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "INSERT INTO Users (Name, Email) VALUES ('Alice', 'alice@example.com'), ('Bob', 'bob@example.com'), ('Charlie', 'charlie@example.com')"
Insert with Auto-Generated ID
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "INSERT INTO Users (Name, Email) VALUES ('David', 'david@example.com')"
Insert from File
cat > bulk_insert.sql <<EOF
INSERT INTO Products (Name, Price) VALUES ('Laptop', 5999.00);
INSERT INTO Products (Name, Price) VALUES ('Mouse', 99.00);
INSERT INTO Products (Name, Price) VALUES ('Keyboard', 299.00);
EOF
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec -F bulk_insert.sql
UPDATE Operations
Simple UPDATE with Backup
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
export DBCLI_CONNECTION="Data Source=app.db"
dbcli query "CREATE TABLE Users_copy_${TIMESTAMP} AS SELECT * FROM Users WHERE Id = 1"
dbcli exec "UPDATE Users SET Email = 'updated@example.com' WHERE Id = 1"
Bulk UPDATE with Verification
export DBCLI_CONNECTION="Data Source=app.db"
dbcli query "SELECT COUNT(*) as count FROM Users WHERE status = 'inactive'"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
dbcli query "CREATE TABLE Users_copy_${TIMESTAMP} AS SELECT * FROM Users WHERE status = 'inactive'"
dbcli exec "UPDATE Users SET status = 'archived' WHERE status = 'inactive'"
dbcli query "SELECT COUNT(*) as count FROM Users WHERE status = 'archived'"
UPDATE Multiple Columns
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
export DBCLI_CONNECTION="Data Source=app.db"
dbcli export Users > Users_backup_${TIMESTAMP}.sql
dbcli exec "UPDATE Users SET Name = 'Jane Doe', Email = 'jane@example.com', UpdatedAt = datetime('now') WHERE Id = 5"
Conditional UPDATE
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
export DBCLI_CONNECTION="Data Source=app.db"
dbcli query "CREATE TABLE Orders_copy_${TIMESTAMP} AS SELECT * FROM Orders WHERE status = 'pending' AND created_at < date('now', '-30 days')"
dbcli exec "UPDATE Orders SET status = 'expired' WHERE status = 'pending' AND created_at < date('now', '-30 days')"
DELETE Operations
DELETE with WHERE Clause
export DBCLI_CONNECTION="Data Source=app.db"
dbcli -f table query "SELECT * FROM Users WHERE last_login < date('now', '-365 days')"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
dbcli export Users > Users_backup_${TIMESTAMP}.sql
dbcli exec "DELETE FROM Users WHERE last_login < date('now', '-365 days')"
dbcli query "SELECT COUNT(*) as remaining FROM Users"
DELETE All Records (DANGEROUS)
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
export DBCLI_CONNECTION="Data Source=app.db"
dbcli query "CREATE TABLE Users_copy_${TIMESTAMP} AS SELECT * FROM Users"
dbcli export Users > Users_backup_${TIMESTAMP}.sql
read -p "Delete ALL records from Users table? (yes/no): " confirm
if [ "$confirm" = "yes" ]; then
dbcli exec "DELETE FROM Users"
echo "All records deleted. Backups: Users_copy_${TIMESTAMP} and Users_backup_${TIMESTAMP}.sql"
fi
DELETE with JOIN (Advanced)
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
export DBCLI_CONNECTION="Data Source=app.db"
dbcli export OrderItems > OrderItems_backup_${TIMESTAMP}.sql
dbcli exec "DELETE FROM OrderItems WHERE order_id NOT IN (SELECT id FROM Orders)"
DaMeng
export DBCLI_CONNECTION="Server=localhost;User Id=SYSDBA;PWD=xxxxxxxxxx;DATABASE=mydb"
export DBCLI_DBTYPE="dm"
dbcli exec "INSERT INTO dm_test (id, name) VALUES (1, 'test')"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DBCLI_CONNECTION="Server=localhost;User Id=SYSDBA;PWD=xxxxxxxxxx;DATABASE=mydb" DBCLI_DBTYPE="dm" dbcli query "CREATE TABLE dm_test_copy_${TIMESTAMP} AS SELECT * FROM dm_test WHERE id = 1"
DBCLI_CONNECTION="Server=localhost;User Id=SYSDBA;PWD=xxxxxxxxxx;DATABASE=mydb" DBCLI_DBTYPE="dm" dbcli exec "UPDATE dm_test SET name = 'updated' WHERE id = 1"
GaussDB
export DBCLI_CONNECTION="Host=localhost;Port=8000;Database=mydb;Username=gaussdb;Password=xxxxxxxxxx"
export DBCLI_DBTYPE="gaussdb"
dbcli exec "INSERT INTO gauss_test (name, amount) VALUES ('Product A', 99.99')"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DBCLI_CONNECTION="Host=localhost;Port=8000;Database=mydb;Username=gaussdb;Password=xxxxxxxxxx" DBCLI_DBTYPE="gaussdb" dbcli export gauss_test > gauss_backup_${TIMESTAMP}.sql
DBCLI_CONNECTION="Host=localhost;Port=8000;Database=mydb;Username=gaussdb;Password=xxxxxxxxxx" DBCLI_DBTYPE="gaussdb" dbcli exec "UPDATE gauss_test SET amount = amount * 1.1 WHERE category = 'premium'"
Programmatic Usage
Python with Backup
import subprocess
import json
from datetime import datetime
"""
Assumes `appsettings.json` is in the current working directory.
DbCli auto-loads it when `--config` is not provided.
"""
def safe_update(table, update_sql):
"""Execute UPDATE with automatic backup"""
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_table = f"{table}_copy_{timestamp}"
try:
subprocess.run(
['dbcli', 'query', f'CREATE TABLE {backup_table} AS SELECT * FROM {table}'],
check=True,
)
print(f"Backup created: {backup_table}")
result = subprocess.run(
['dbcli', 'exec', update_sql],
capture_output=True,
text=True,
check=True,
)
data = json.loads(result.stdout)
print(f"Updated {data['AffectedRows']} rows")
except subprocess.CalledProcessError as e:
raise RuntimeError(
"dbcli failed. Please configure appsettings.json (ConnectionString/DbType) or set DBCLI_CONNECTION/DBCLI_DBTYPE."
) from e
return backup_table
backup = safe_update('Users', "UPDATE Users SET status = 'active' WHERE verified = 1")
PowerShell with Verification
function Safe-DbUpdate {
param(
[string]$Table,
[string]$UpdateSql
)
# Assumes appsettings.json is in the current working directory (DbCli auto-loads it)
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$backup = "${Table}_backup_${timestamp}.sql"
try {
dbcli export $Table | Out-File -FilePath $backup -Encoding utf8
Write-Host "Backup created: $backup"
$result = dbcli exec $UpdateSql | ConvertFrom-Json
} catch {
throw "dbcli failed. Please configure appsettings.json (ConnectionString/DbType) or set DBCLI_CONNECTION/DBCLI_DBTYPE. $($_.Exception.Message)"
}
Write-Host "Updated $($result.AffectedRows) rows"
return $backup
}
# Usage
$backup = Safe-DbUpdate -Table "Users" -UpdateSql "UPDATE Users SET Email = LOWER(Email)"
Response Format
All exec operations return JSON with affected row count:
{
"AffectedRows": 5
}
Error Handling
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "DELETE FROM temp_data"
if [ $? -eq 0 ]; then
echo "Delete succeeded"
else
echo "Delete failed - check error message"
exit 1
fi
Common Patterns
Upsert Pattern (INSERT or UPDATE)
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "INSERT OR REPLACE INTO Settings (key, value) VALUES ('theme', 'dark')"
export DBCLI_CONNECTION="Server=localhost;Database=mydb;Uid=root;Pwd=xxxxxxxxxx"
export DBCLI_DBTYPE="mysql"
dbcli exec "INSERT INTO Settings (key, value) VALUES ('theme', 'dark') ON DUPLICATE KEY UPDATE value = 'dark'"
Batch Insert from CSV
awk -F',' 'NR>1 {print "INSERT INTO products (name, price) VALUES (\""$1"\", "$2");"}' products.csv > insert_products.sql
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec -F insert_products.sql
Increment Counter
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "UPDATE counters SET value = value + 1 WHERE name = 'page_views'"
Security Best Practices
- Always create backups before UPDATE/DELETE
- Use WHERE clauses to avoid accidental full-table updates
- Verify affected rows match expectations
- Test on backup database first for complex operations
- Use transactions for multi-step operations when possible
- Avoid dynamic SQL - validate all user input
- Use read-only users when possible (query-only access)
Backup Recovery
Restore from Table Copy
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "DELETE FROM Users"
dbcli exec "INSERT INTO Users SELECT * FROM Users_copy_20250127_143022"
Restore from SQL Export
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "DELETE FROM Users"
dbcli exec -F Users_backup_20250127_143022.sql
Selective Restore
export DBCLI_CONNECTION="Data Source=app.db"
dbcli exec "INSERT INTO Users SELECT * FROM Users_copy_20250127_143022 WHERE Id IN (1, 2, 3)"