Dynamic typing
A SQLite type declaration is an affinity hint, not a
constraint, so a column declared INTEGER can hold
text in real rows. The conversion follows the declaration, so
retype the columns your data has outgrown in the type-mapping
review.
Generated keys
Maps SQLite INTEGER PRIMARY KEY /
AUTOINCREMENT (which is tied to
ROWID) to MySQL AUTO_INCREMENT on
the PK column, and reseeds above the loaded maximum key
value - so the application's next insert does not
collide.
Dates and booleans
SQLite has no date or boolean type: applications store dates
as ISO-8601 text and booleans as 0/1 integers. Those columns
arrive as the type they were declared with, so pick
DATETIME or TINYINT(1) for them in the
type-mapping review. A column already declared
DATETIME in SQLite comes across as
DATETIME.
Dialect differences
Rewrites SQLite double-quoted identifiers into backtick MySQL
form on the target, generates MySQL-flavored DDL (replacing
SQLite AUTOINCREMENT, pragmas, and transaction
syntax), and creates target columns as utf8mb4
so Unicode round-trips safely.
CHECK constraints and objects to recreate
Supported SQLite CHECK expressions are transferred
to MySQL. Rules that cannot be translated or that existing rows
violate are omitted and named in the log; the rows are kept.
Review CHECK constraints
after the run. SQLite triggers, procedural code and
WITHOUT ROWID table specifics must be recreated manually.
Application code is a separate pass: anything written around SQLite
locking, pragmas, date storage conventions, or SQLite-specific SQL still
needs review before the application points at MySQL.