Migrating a MariaDB contacts table into a single-file SQLite database using a Python script with schema mapping, safe parameterized imports, auditing SQL artifacts, and verification.
This lesson demonstrates migrating a small MariaDB database into a single-file SQLite database. The goal is to read schema and data from a local MariaDB instance and produce a SQLite file containing the same records and an approximation of the schema — suitable for low-traffic or archival databases where the operational overhead of running MariaDB is unnecessary.We use a compact, iterative workflow: start with a concise prompt to generate an approach, then expand to a reproducible Python script when the quick approach is brittle.
TEXT (ISO formats: YYYY-MM-DD / YYYY-MM-DD HH:MM:SS)
Note: SQLite uses type affinity, so these are pragmatic mappings rather than exact conversions. Document and review columns with special constraints (e.g., unsigned integers, auto-increment semantics).
Practical run — repository inspection and initial interaction
The model inspected repository files (contacts CSV, contacts_data.sql, migration.md) and asked for connection info. Never share production credentials in untrusted environments — use a local test account or pass secrets at runtime.
Do not share production credentials or secrets in an environment you do not control. Use local test credentials or create scripts that accept credentials at runtime (environment variables or interactive input) rather than embedding secrets in chat history or files.
Sample connection details used interactively for testing:
A naive pipeline that reads mysql tab-separated output and pipes it into sqlite3 (with sed and shell parsing) often fails on real data: names with apostrophes, embedded tabs, newline characters in text fields, or other quoting issues break the parsing and produce invalid SQL.Example brittle approach (DO NOT use in production):
Copy
mysql -h localhost -u jeremy -ppassword123 contactsdb -e "SELECT * FROM contacts;" \ | sed 's/\t/|/g' | tail -n +2 \ | while IFS='|' read -r id first_name last_name job_title email; do sqlite3 contacts.db "INSERT INTO contacts (id, first_name, last_name, job_title, email) VALUES ('$id', '$first_name', '$last_name', '$job_title', '$email');" done
Common failure: apostrophes in names (e.g., O’Connolly) or embedded separators break quoting and allow SQL injection.
Verify row counts and sample rows after migration.Row count comparison:
Copy
sqlite3 contacts.db "SELECT COUNT(*) as total_records FROM contacts;"mysql -h localhost -u jeremy -ppassword123 contactsdb -e "SELECT COUNT(*) as total_records FROM contacts;"# => total_records# 1000
Sample rows from SQLite:
Copy
sqlite3 contacts.db "SELECT * FROM contacts LIMIT 5;"# Example output:# 1|Britt|Hyne|Senior Editor|bhyne@lulu.com# 2|Merrel|Cornew|VP Product Management|mcornew1@indiegogo.com# 3|Emmit|Glasard|Senior Editor|eglasard2@behance.net
For simple tables, a compact Python script using mysql-connector-python + sqlite3 is reliable and avoids quoting pitfalls.
For complex schemas (foreign keys, triggers, stored routines), plan for manual mapping or schema redesign; SQLite lacks some MariaDB features.
Always test migrations in a sandbox and verify row counts and spot-check data.
Prefer parameterized queries to avoid quoting and injection issues.
Keep a dump (.sql) or TSV export for auditing and replay.
This migration converted 1,000 contacts from MariaDB (contactsdb.contacts) into a single-file SQLite database (contacts.db) and produced a reproducible migration script suitable for reruns or adaptation.