| name | dbcli-db-ddl |
| description | Execute DDL (Data Definition Language) statements - CREATE, ALTER, DROP tables, indexes, views on 30+ databases using DbCli. CRITICAL - requires mandatory backup before DROP/ALTER operations. Use when user needs to create schema, modify structure, or drop database objects. |
| 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":"critical-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 Database DDL Skill
Execute Data Definition Language (DDL) operations - CREATE, ALTER, DROP tables, indexes, and views.
⚠️ CRITICAL SAFETY REQUIREMENT
MANDATORY BACKUPS BEFORE DROP/ALTER OPERATIONS
- DROP TABLE: Export table data + create table copy
- ALTER TABLE: Export table schema + data
- DROP INDEX/VIEW: Document structure before dropping
When to Use This Skill
- User wants to create tables, indexes, or views
- User needs to modify table structure (add/drop columns, change types)
- User wants to drop tables, indexes, or views
- User mentions CREATE, ALTER, DROP, schema, structure, or database design
- Never DROP/ALTER without backups
Command Syntax
DBCLI_CONNECTION="CONNECTION_STRING" DBCLI_DBTYPE="DATABASE_TYPE" dbcli ddl "DDL_STATEMENT"
Global Options
- Environment variable
DBCLI_CONNECTION: Database connection string (required)
- Environment variable
DBCLI_DBTYPE: Database type (default: sqlite)
--config <path>: Config file path (e.g. appsettings.json) (optional)
Subcommand Options
-F, --file: Execute DDL from file
Notes:
- SQL Server supports
GO batch separators in DDL scripts (use -F and keep GO on its own line).
CREATE Operations (Safe - No Backup Required)
Create Table
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE Users (Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL, Email TEXT UNIQUE, CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"
DBCLI_CONNECTION="Server=localhost;Database=mydb;Trusted_Connection=True" DBCLI_DBTYPE="sqlserver" dbcli ddl "CREATE TABLE Users (Id INT PRIMARY KEY IDENTITY(1,1), Name NVARCHAR(100) NOT NULL, Email NVARCHAR(255) UNIQUE, CreatedAt DATETIME DEFAULT GETDATE())"
DBCLI_CONNECTION="Server=localhost;Database=mydb;Uid=root;Pwd=xxxxxxxxxx" DBCLI_DBTYPE="mysql" dbcli ddl "CREATE TABLE Users (Id INT PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(100) NOT NULL, Email VARCHAR(255) UNIQUE, CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"
DBCLI_CONNECTION="Host=localhost;Database=mydb;Username=postgres;Password=xxxxxxxxxx" DBCLI_DBTYPE="postgresql" dbcli ddl "CREATE TABLE Users (Id SERIAL PRIMARY KEY, Name VARCHAR(100) NOT NULL, Email VARCHAR(255) UNIQUE, CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"
Create Table with Foreign Key
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE Orders (Id INTEGER PRIMARY KEY AUTOINCREMENT, UserId INTEGER NOT NULL, Total REAL NOT NULL, OrderDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (UserId) REFERENCES Users(Id))"
Create Table from Query (Backup/Copy)
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE Users_backup AS SELECT * FROM Users"
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE ActiveUsers AS SELECT * FROM Users WHERE active = 1"
Create Table if Not Exists
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE IF NOT EXISTS Settings (Key TEXT PRIMARY KEY, Value TEXT)"
Create Index
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE INDEX idx_users_email ON Users(Email)"
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE INDEX idx_orders_user_date ON Orders(UserId, OrderDate)"
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE UNIQUE INDEX idx_users_username ON Users(Username)"
Create View
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE VIEW ActiveUsers AS SELECT Id, Name, Email FROM Users WHERE active = 1"
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE VIEW UserOrders AS SELECT u.Name, o.Id as OrderId, o.Total, o.OrderDate FROM Users u JOIN Orders o ON u.Id = o.UserId"
DROP Operations (DANGEROUS - Requires Backup)
Safe DROP TABLE Workflow
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DBCLI_CONNECTION="Data Source=app.db" dbcli -f table columns OldTable > OldTable_schema_${TIMESTAMP}.txt
DBCLI_CONNECTION="Data Source=app.db" dbcli export OldTable > OldTable_backup_${TIMESTAMP}.sql
DBCLI_CONNECTION="Data Source=app.db" dbcli query "CREATE TABLE OldTable_copy_${TIMESTAMP} AS SELECT * FROM OldTable"
DBCLI_CONNECTION="Data Source=app.db" dbcli query "SELECT COUNT(*) FROM OldTable"
DBCLI_CONNECTION="Data Source=app.db" dbcli query "SELECT COUNT(*) FROM OldTable_copy_${TIMESTAMP}"
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "DROP TABLE IF EXISTS OldTable"
echo "Table dropped. Backups: OldTable_backup_${TIMESTAMP}.sql, OldTable_copy_${TIMESTAMP}"
Safe DROP INDEX
DBCLI_CONNECTION="Data Source=app.db" dbcli query "SELECT sql FROM sqlite_master WHERE type='index' AND name='idx_old_index'" > idx_old_index_definition.sql
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "DROP INDEX IF EXISTS idx_old_index"
Safe DROP VIEW
DBCLI_CONNECTION="Data Source=app.db" dbcli query "SELECT sql FROM sqlite_master WHERE type='view' AND name='OldView'" > OldView_definition.sql
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "DROP VIEW IF EXISTS OldView"
ALTER Operations (CRITICAL - Requires Backup)
Safe ALTER TABLE Workflow
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DBCLI_CONNECTION="Data Source=app.db" dbcli export Users > Users_backup_${TIMESTAMP}.sql
DBCLI_CONNECTION="Data Source=app.db" dbcli query "CREATE TABLE Users_copy_${TIMESTAMP} AS SELECT * FROM Users"
DBCLI_CONNECTION="Data Source=app.db" dbcli query "SELECT COUNT(*) FROM Users"
DBCLI_CONNECTION="Data Source=app.db" dbcli query "SELECT COUNT(*) FROM Users_copy_${TIMESTAMP}"
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "ALTER TABLE Users ADD COLUMN PhoneNumber TEXT"
DBCLI_CONNECTION="Data Source=app.db" dbcli -f table columns Users
ALTER TABLE - Add Column
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DBCLI_CONNECTION="Data Source=app.db" dbcli export Users > Users_backup_${TIMESTAMP}.sql
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "ALTER TABLE Users ADD COLUMN Age INTEGER"
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "ALTER TABLE Users ADD COLUMN Status TEXT DEFAULT 'active'"
ALTER TABLE - Drop Column
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DBCLI_CONNECTION="Data Source=app.db" dbcli export Users > Users_backup_${TIMESTAMP}.sql
DBCLI_CONNECTION="Data Source=app.db" dbcli query "CREATE TABLE Users_copy_${TIMESTAMP} AS SELECT * FROM Users"
DBCLI_CONNECTION="Server=localhost;Database=mydb;Trusted_Connection=True" DBCLI_DBTYPE="sqlserver" dbcli ddl "ALTER TABLE Users DROP COLUMN TempColumn"
ALTER TABLE - Rename Table
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DBCLI_CONNECTION="Data Source=app.db" dbcli export OldName > OldName_backup_${TIMESTAMP}.sql
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "ALTER TABLE OldName RENAME TO NewName"
DBCLI_CONNECTION="Server=localhost;Database=mydb;Trusted_Connection=True" DBCLI_DBTYPE="sqlserver" dbcli ddl "EXEC sp_rename 'OldName', 'NewName'"
ALTER TABLE - Rename Column
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DBCLI_CONNECTION="Data Source=app.db" dbcli export Users > Users_backup_${TIMESTAMP}.sql
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "ALTER TABLE Users RENAME COLUMN OldColumnName TO NewColumnName"
DBCLI_CONNECTION="Server=localhost;Database=mydb;Trusted_Connection=True" DBCLI_DBTYPE="sqlserver" dbcli ddl "EXEC sp_rename 'Users.OldColumnName', 'NewColumnName', 'COLUMN'"
DDL from File
Execute Schema File
cat > schema.sql <<EOF
CREATE TABLE Users (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Email TEXT UNIQUE,
CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE Orders (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
UserId INTEGER NOT NULL,
Total REAL NOT NULL,
OrderDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (UserId) REFERENCES Users(Id)
);
CREATE INDEX idx_users_email ON Users(Email);
CREATE INDEX idx_orders_user ON Orders(UserId);
EOF
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl -F schema.sql
Migration Scripts
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl -F migrations/001_create_users.sql
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl -F migrations/002_add_orders.sql
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl -F migrations/003_add_indexes.sql
DaMeng
DBCLI_CONNECTION="Server=localhost;User Id=SYSDBA;PWD=xxxxxxxxxx;DATABASE=mydb" DBCLI_DBTYPE="dm" dbcli ddl "CREATE TABLE dm_test (id INT PRIMARY KEY, name VARCHAR(100), create_time TIMESTAMP)"
DBCLI_CONNECTION="Server=localhost;User Id=SYSDBA;PWD=xxxxxxxxxx;DATABASE=mydb" DBCLI_DBTYPE="dm" dbcli ddl "CREATE INDEX idx_dm_test_name ON dm_test(name)"
DBCLI_CONNECTION="Server=localhost;User Id=SYSDBA;PWD=xxxxxxxxxx;DATABASE=mydb" DBCLI_DBTYPE="dm" dbcli ddl "CREATE VIEW v_dm_test AS SELECT id, name FROM dm_test WHERE id > 0"
GaussDB
DBCLI_CONNECTION="Host=localhost;Port=8000;Database=mydb;Username=gaussdb;Password=xxxxxxxxxx" DBCLI_DBTYPE="gaussdb" dbcli ddl "CREATE TABLE gauss_test (id SERIAL PRIMARY KEY, name VARCHAR(100), amount DECIMAL(10,2))"
DBCLI_CONNECTION="Host=localhost;Port=8000;Database=mydb;Username=gaussdb;Password=xxxxxxxxxx" DBCLI_DBTYPE="gaussdb" dbcli ddl "CREATE INDEX idx_gauss_test_name ON gauss_test(name)"
DBCLI_CONNECTION="Host=localhost;Port=8000;Database=mydb;Username=gaussdb;Password=xxxxxxxxxx" DBCLI_DBTYPE="gaussdb" dbcli ddl "CREATE OR REPLACE FUNCTION get_total() RETURNS DECIMAL AS \$\$ BEGIN RETURN (SELECT SUM(amount) FROM gauss_test); END; \$\$ LANGUAGE plpgsql"
KingbaseES (人大金仓)
DBCLI_CONNECTION="Server=localhost;Port=54321;UID=system;PWD=xxxxxxxxxx;database=mydb" DBCLI_DBTYPE="kdbndp" dbcli ddl "CREATE TABLE kingbase_test (id SERIAL PRIMARY KEY, name VARCHAR(100), price NUMERIC(10,2))"
DBCLI_CONNECTION="Server=localhost;Port=54321;UID=system;PWD=xxxxxxxxxx;database=mydb" DBCLI_DBTYPE="kdbndp" dbcli ddl "CREATE VIEW v_kingbase_active AS SELECT * FROM kingbase_test WHERE status = 1"
Advanced DDL
Composite Primary Key
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE UserRoles (UserId INTEGER NOT NULL, RoleId INTEGER NOT NULL, AssignedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (UserId, RoleId))"
Check Constraints
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE Products (Id INTEGER PRIMARY KEY, Name TEXT NOT NULL, Price REAL CHECK(Price > 0), Stock INTEGER CHECK(Stock >= 0))"
Triggers (SQLite)
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TRIGGER update_timestamp AFTER UPDATE ON Users BEGIN UPDATE Users SET UpdatedAt = datetime('now') WHERE Id = NEW.Id; END"
Partial Index
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE INDEX idx_active_users ON Users(Email) WHERE active = 1"
Backup Recovery for DDL
Recover Dropped Table
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE Users AS SELECT * FROM Users_copy_20250127_143022"
DBCLI_CONNECTION="Data Source=app.db" dbcli exec -F Users_backup_20250127_143022.sql
Recover Dropped Index
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl -F idx_users_email_definition.sql
Rollback ALTER TABLE
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "DROP TABLE Users"
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE Users AS SELECT * FROM Users_copy_20250127_143022"
Schema Verification
Check Table Exists
DBCLI_CONNECTION="Data Source=app.db" dbcli query "SELECT name FROM sqlite_master WHERE type='table' AND name='Users'"
DBCLI_CONNECTION="Server=localhost;Database=mydb;Trusted_Connection=True" DBCLI_DBTYPE="sqlserver" dbcli query "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Users'"
Check Column Exists
DBCLI_CONNECTION="Data Source=app.db" dbcli query "PRAGMA table_info(Users)"
DBCLI_CONNECTION="Server=localhost;Database=mydb;Trusted_Connection=True" DBCLI_DBTYPE="sqlserver" dbcli query "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Users' AND COLUMN_NAME = 'Email'"
Check Index Exists
DBCLI_CONNECTION="Data Source=app.db" dbcli query "SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='Users' AND name='idx_users_email'"
Common Patterns
Idempotent DDL (Safe Re-run)
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "DROP TABLE IF EXISTS TempTable"
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE TempTable (Id INTEGER PRIMARY KEY, Data TEXT)"
DBCLI_CONNECTION="Data Source=app.db" dbcli ddl "CREATE TABLE IF NOT EXISTS Settings (Key TEXT PRIMARY KEY, Value TEXT)"
Database Initialization
#!/bin/bash
CONNECTION="Data Source=app.db"
DBCLI_CONNECTION="$CONNECTION" dbcli ddl -F schema/001_users.sql
DBCLI_CONNECTION="$CONNECTION" dbcli ddl -F schema/002_orders.sql
DBCLI_CONNECTION="$CONNECTION" dbcli ddl -F schema/003_products.sql
DBCLI_CONNECTION="$CONNECTION" dbcli ddl -F schema/004_indexes.sql
DBCLI_CONNECTION="$CONNECTION" dbcli ddl -F schema/005_views.sql
echo "Database initialized"
Schema Migration
#!/bin/bash
CONNECTION="Data Source=app.db"
BACKUP_DIR="backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
cp app.db "${BACKUP_DIR}/app_${TIMESTAMP}.db"
for migration in migrations/*.sql; do
echo "Running $migration..."
DBCLI_CONNECTION="$CONNECTION" dbcli ddl -F "$migration"
if [ $? -ne 0 ]; then
echo "Migration failed: $migration"
echo "Restoring from backup..."
cp "${BACKUP_DIR}/app_${TIMESTAMP}.db" app.db
exit 1
fi
done
echo "All migrations completed successfully"
Security Best Practices
- Always backup before DROP/ALTER - Cannot emphasize enough
- Test DDL on backup database first
- Use transactions for multiple DDL operations when supported
- Document schema changes with timestamps and reasons
- Version control all DDL scripts
- Limit DDL permissions to admin users only
- Review constraints before adding (can block future inserts)