The basics
What is a SQL file?
A .sql file holds SQL statements as plain text. Nothing happens until a database client reads the file and sends the statements to a database server (or, for SQLite, to a database file). It's how database structure, data and changes travel between people, servers and version control.
- Schema scripts create tables, indexes and views for a new database.
- Migrations are small numbered scripts that change an existing database step by step, applied in order by a tool.
- Dumps are backups: a script that recreates a whole database, data included, written by
pg_dump,mysqldumpor SQLite's.dump. - Seed data and reports: inserts for test data, or saved queries someone runs by hand.
Three things a SQL file is not:
- Not a database. The data lives in the database server or in a database file (
.dbor.sqlitefor SQLite,.mdffor SQL Server). A.sqlfile is instructions, though a dump can contain every row asINSERTorCOPYstatements. - Not one language. The ISO standard is the common core, and every database extends it differently. A script written for MySQL often fails on PostgreSQL, and the other way round.
- Not safe to run blindly. It can delete tables as easily as create them. Read a script, and try it on a copy, before running it against data you care about.
Anatomy
What's inside a SQL file
A SQL script is a list of statements separated by semicolons. The database runs them top to bottom, exactly as if you typed them one by one. This small script, which runs unchanged on PostgreSQL, MySQL and SQLite, uses the main kinds, part by part.
-- library.sql: books and loans
DROP TABLE IF EXISTS loans;
DROP TABLE IF EXISTS books;
CREATE TABLE books (
id INTEGER PRIMARY KEY,
title VARCHAR(200) NOT NULL,
year INTEGER CHECK (year > 1400)
);
CREATE TABLE loans (
book_id INTEGER NOT NULL REFERENCES books (id),
borrower VARCHAR(80) NOT NULL,
due_on DATE NOT NULL
);
INSERT INTO books (id, title, year) VALUES
(1, 'Example Tales', 1998),
(2, 'The O''Example Atlas', 2021);
BEGIN;
INSERT INTO loans VALUES (2, 'Ada Example', '2026-11-10');
COMMIT;
/* Which books are out, and until when? */
SELECT b.title, l.borrower, l.due_on
FROM books b
JOIN loans l ON l.book_id = b.id
ORDER BY l.due_on;- 1
-- library.sql: books and loansA comment
Two hyphens start a comment that runs to the end of the line. MySQL needs a space after them.
/* … */comments can span lines. - 2
DROP TABLE IF EXISTS loans;Starting clean
Deletes the table if it's there, so the script can run twice.
loansgoes first because it refers tobooks. On a real database this deletes data: read a script before you run it. - 3
CREATE TABLE books ( … );Data definition (DDL)
Defines a table: its columns, their types and the rules the data must follow.
CREATE,ALTERandDROPchange the structure, not the data. - 4
PRIMARY KEY / NOT NULL / CHECK (year > 1400)Constraints
Rules the database enforces on every row. An insert that breaks one fails with an error instead of storing bad data.
- 5
REFERENCES books (id)A foreign key
Every loan must point at a book that exists. SQLite only enforces this after
PRAGMA foreign_keys = ON; PostgreSQL and MySQL always do. - 6
INSERT INTO books … VALUES …;Data manipulation (DML)
Adds rows;
UPDATEchanges them andDELETEremoves them. Several rows can go in one statement. - 7
'The O''Example Atlas'A string literal
Text goes in single quotes, and a quote inside the text is written twice. Double quotes are for names of tables and columns in standard SQL, not for text.
- 8
BEGIN; … COMMIT;A transaction
The statements in between take effect together, at
COMMIT, or not at all if youROLLBACK. - 9
SELECT … FROM books b JOIN loans l …A query
Reads data, here combining two tables. A script's queries print their results in the terminal or tool that runs it.
- 10
ORDER BY l.due_on;The final semicolon
Ends the last statement. Command-line clients wait for it before sending a statement to the database.
How to
How to run a .sql file
Each database has a command-line client that reads a script from a file. Open a terminal (Command Prompt or PowerShell on Windows, Terminal on macOS and Linux) and run:
# PostgreSQL: stop at the first error; -1 runs it all in one transaction
psql -d shop -v ON_ERROR_STOP=1 -f script.sql
psql -d shop -v ON_ERROR_STOP=1 -1 -f script.sql
# MySQL or MariaDB: stops at the first error unless you add --force
mysql --default-character-set=utf8mb4 shop < script.sql
# SQLite: creates shop.db if it doesn't exist; -bail stops at the first error
sqlite3 -bail shop.db < script.sql
# SQL Server: put ":On Error exit" at the top of the script to stop at the first error
sqlcmd -S localhost -d shop -i script.sql| On an error, by default | Inside an interactive session | |
|---|---|---|
psql (PostgreSQL) | Prints it and carries on with the next statement | \i script.sql |
mysql (MySQL, MariaDB) | Stops | source script.sql |
sqlite3 (SQLite) | Prints it, carries on, and exits with an error code | .read script.sql |
sqlcmd (SQL Server) | Prints it; :On Error exit in the script makes it stop | :r script.sql |
- Graphical tools: in SSMS (SQL Server Management Studio), DBeaver, pgAdmin or MySQL Workbench, open the file and click Execute or Run. On Windows, double-clicking a
.sqlfile usually opens it in SSMS or an editor, depending on what's installed; it doesn't run it. - The database must exist first, unless the script creates it.
createdb shop(PostgreSQL),CREATE DATABASE shop(MySQL) or simply naming a new file (SQLite) does that. - The output of
SELECTstatements goes to the terminal. Add-o file.txttopsqlor redirect with> out.txtto keep it.
Compatibility
Why a script for one database fails on another
RFC 6922, which registered application/sql, says it plainly: although a standard exists, vendor implementations vary significantly. The basics in the anatomy above work almost everywhere; these are the places where they differ:
| PostgreSQL | MySQL | SQLite | SQL Server | |
|---|---|---|---|---|
| Quoting names | "name" | Backticks around the name | "name", or backticks | [name] or "name" |
| Auto-numbered key | GENERATED ALWAYS AS IDENTITY or SERIAL | AUTO_INCREMENT | INTEGER PRIMARY KEY | IDENTITY(1,1) |
| Joining strings | a || b | CONCAT(a, b) | a || b | a + b or CONCAT |
| First n rows | LIMIT n | LIMIT n | LIMIT n | TOP (n) or OFFSET … FETCH |
| True and false | boolean | TINYINT(1), written TRUE/FALSE | Integers 1 and 0 | BIT |
| Backslash in strings | Plain character | Escape character | Plain character | Plain character |
CREATE TABLE inside a transaction | Rolled back with the rest | Commits the transaction first | Rolled back with the rest | Rolled back with the rest |
| Client-only commands in scripts | \set, \echo, \copy… | DELIMITER, source | .read, .mode… | GO, :r, :setvar |
- Unquoted names change case. PostgreSQL folds them to lowercase, so
CREATE TABLE Usersmakesusers, andSELECT * FROM "Users"then fails. The SQL standard folds to uppercase instead. Either always quote a name or never quote it. - Types are looser in SQLite. It gives a
DECIMAL(10,2)column numeric affinity and ignores the precision, so19.00comes back as19and a sum as34.0. - Client commands aren't SQL. Lines like
\set,DELIMITER //orGOare read by one particular client and never reach the server. Run the script in another tool and they're syntax errors.
-- The same idea in Transact-SQL (SQL Server), run with sqlcmd or SSMS
CREATE TABLE dbo.books (
id INT IDENTITY(1,1) PRIMARY KEY,
title NVARCHAR(200) NOT NULL
);
GO
BEGIN TRANSACTION;
INSERT INTO dbo.books (title) VALUES (N'Example Tales');
COMMIT TRANSACTION;
GO
SELECT TOP (5) id, title FROM dbo.books ORDER BY id;
GOBackups and changes
Dump files vs migration files
| Dump | Migration | |
|---|---|---|
| Made by | pg_dump, mysqldump, sqlite3 db .dump | A person, often with a framework's help |
| Contains | The whole database: structure and every row | One change: add a column, create an index, fix some data |
| Typical name | shop-2026-10-27.sql | V3__add_phone_column.sql, 20261027_add_phone.up.sql |
| Applied | Once, into an empty database | In order, each one once, by a tool that remembers which have run |
| Portable between databases | No: full of the source database's dialect | Usually written for one database |
- Restore a PostgreSQL dump into a new, empty database with
psql -X -d newdb -f dump.sql. A plain-text dump loads its data withCOPY … FROM stdinblocks, which onlypsqlunderstands. Dumps in pg_dump's custom format (-Fc) aren't SQL at all and needpg_restore. - Restore a MySQL dump with
mysql newdb < dump.sql. A dump made with--databasesor--all-databasescontains its ownCREATE DATABASEandUSEstatements. - Recent pg_dump versions start the file with a
\restrictline and a random key, and end it with\unrestrict. In between,psqlrefuses all other backslash commands, a fix for CVE-2025-8714, in which a malicious superuser of the source server could plant commands in a dump to run on the computer restoring it.
Doing it safely
Transactions in scripts: all or nothing
When a script fails halfway, the statements before the error have already run. Without a transaction, you're left with half a change: a table created but not filled, money taken from one account but not added to the other.
- Wrap related changes in
BEGIN;…COMMIT;(START TRANSACTIONin MySQL,BEGIN TRANSACTIONin SQL Server). - In psql, combine
--single-transactionwithON_ERROR_STOP. psql then sendsBEGINfirst andCOMMITat the end, orROLLBACKif anything fails. PostgreSQL's documentation suggests both options for restoring dumps. - In MySQL, DDL ends the transaction.
CREATE TABLE,ALTER TABLEandDROP TABLEcommit whatever was pending before they run, and can't be rolled back.sample-mysql.sqlbelow shows a row surviving aROLLBACKfor this reason. - Make scripts safe to re-run with
IF EXISTSandIF NOT EXISTS, so running one twice doesn't fail or duplicate data.
Characters
Encoding: why names turn into é in the database
A SQL file doesn't say which encoding it's in, and RFC 6922 warns against guessing. The client reads the bytes in its own client encoding and the server converts them to the database's encoding. If the client guesses wrong, the database stores the wrong characters, and the damage is permanent until someone fixes the data.
- Save scripts as UTF-8. In our tests,
psql16, the MySQL 8.0 client andsqlite33.45 all accepted a UTF-8 byte order mark and CRLF line endings, but older tools may not. - MySQL: use
utf8mb4. MySQL's olderutf8(now calledutf8mb3) stores at most 3 bytes per character, so it can't hold emoji. The MySQL manual recommendsutf8mb4for everything new. - MySQL: name the client character set. The
mysqlclient picks its character set from the system locale. On a server with no UTF-8 locale, that can belatin1, and UTF-8 text gets stored double-encoded. Runmysql --default-character-set=utf8mb4or start the script withSET NAMES utf8mb4;. - PostgreSQL: the client encoding depends on how
psqlis started and on thePGCLIENTENCODINGvariable.SET client_encoding = 'UTF8';at the top of a script removes the doubt, andpg_dumpwrites that line for you.
Troubleshooting
Errors people hit when running SQL files
| Error | Usual cause | Fix |
|---|---|---|
| PostgreSQL: syntax error at or near "AUTO_INCREMENT" | A MySQL script run on PostgreSQL (or any script in the wrong dialect) | Convert the dialect-specific parts, or run it on the database it was written for |
| MySQL: ERROR 1064 You have an error in your SQL syntax | A typo, a reserved word used as a name, or another dialect's syntax | Check the statement at the line number shown; quote names with backticks |
| relation "Users" does not exist | PostgreSQL folded an unquoted Users to users, or the table is in another schema or database | Use the same quoting everywhere; check you're connected to the right database |
| ERROR 1046 (3D000): No database selected | mysql < script.sql without a database name, and no USE in the script | mysql shop < script.sql, or add USE shop; at the top |
| Illegal mix of collations | MySQL comparing two strings stored with different collations, for example a column and a procedure parameter | Use one character set and collation for the whole database, or COLLATE in the comparison |
| Incorrect string value: '\xF0\x9F\x91\x8B' for column | Emoji or other 4-byte characters going into a MySQL utf8mb3 column | Convert the table to utf8mb4 |
| duplicate key value violates unique constraint | The script ran twice, or into a database that already had the data | Restore into an empty database; use IF NOT EXISTS or upserts for re-runnable scripts |
| A dump restore that stops halfway | An error early on (a missing role, an existing table), with later statements depending on it | Restore into an empty database with ON_ERROR_STOP and fix the first error, not the last |
Security
Opening, editing and security: SQL injection and dumps
Any text editor opens a .sql file. VS Code, JetBrains DataGrip and DBeaver add syntax highlighting and can run the statements against a connection; formatters such as pg_format and sqlfluff tidy and check them. Opening the file runs nothing.
- Running a script is running code. It can drop tables, change permissions or, in some databases, read server files. Run scripts from others as a database user with only the rights the script needs, and against a copy first.
- Dumps contain everything. Customer names, email addresses, password hashes and anything else in the database ends up in the file in readable text. Treat a dump like the database itself: encrypt it, limit who has it, and delete old ones. Under the GDPR, personal data in a backup is still personal data.
- Dumps can carry client commands.
psqlbackslash commands such as\!, which runs a shell command, are why recentpg_dumpversions add\restrict. Only restore dumps from sources you trust.
SQL injection is the best-known database attack, and it happens in application code, not in .sql files. It occurs when a program builds a query by pasting user input into SQL text: if the input contains a quote, the rest of it is read as SQL, and the attacker can change what the query does, for example to return every row instead of one. The fix, as the OWASP cheat sheet sets out, is parameterised queries (prepared statements): the query is sent with placeholders, and the values travel separately, so they are never read as SQL. Escaping input by hand is unreliable, and least-privilege database accounts limit the damage if something slips through.
Free downloads
Sample SQL files to download
Free sample SQL files for testing database clients, migration tools, syntax highlighters, upload filters and size limits. All data is fictional. We ran each one on PostgreSQL 16, MySQL 8.0 and SQLite 3.45 (the dialect-specific ones on their own database) and parsed them with sqlglot and pglast.
Loading…What's inside sample-schema.sql
The file is commented: open it in a text editor and each numbered comment marks one of these parts. It runs unchanged on PostgreSQL, MySQL and SQLite, so it's a good first test of any SQL tool.
Comments 1 and 2: comments and a clean start
Both comment styles, then
DROP VIEW IF EXISTSandDROP TABLE IF EXISTSin dependency order, so the script can run again.Comments 3 to 6: tables
Four tables with primary keys,
UNIQUE,NOT NULL,DEFAULTandCHECKconstraints, exactDECIMALmoney columns, foreign keys and an index.Comment 7: data
Multi-row
INSERTstatements with fictional customers, products and orders. A name with an apostrophe shows quote doubling; dates are writtenYYYY-MM-DD.Comment 8: a transaction
Two
UPDATEstatements betweenBEGINandCOMMIT, after all the DDL, so MySQL's implicit commits don't interfere.Comment 9: a view
order_totalsjoins three tables and sums each order; later queries select from it like a table.Comments 10 to 12: queries
Results you can check: orders 101, 102 and 103 total 34.00, 19.00 and 40.00; Ada Example spent 74.00 in total; a
LEFT JOINwithCOUNTandLIMIT.
All sample SQL files
Portable schema, data and queries
sample-schema.sql · 4.8 KB (4,932 bytes)
A small shop database that runs unchanged on PostgreSQL, MySQL and SQLite: tables with constraints and foreign keys, an index, inserts, a transaction, a view and three queries with known results, with numbered comments.
- A first test of any SQL client, tool or highlighter
- Teaching DDL, DML, transactions and joins
PostgreSQL script with psql commands
sample-postgresql.sql · 3.0 KB (3,056 bytes)
\set ON_ERROR_STOP, an enum type, an identity column,TIMESTAMPTZ,JSONBqueries, a PL/pgSQL function in dollar quotes,ON CONFLICTupserts,RETURNING, and aCREATE TABLErolled back inside a transaction.- Testing PostgreSQL-specific syntax in tools and highlighters
- Showing what psql-only lines look like
MySQL script with DELIMITER and a procedure
sample-mysql.sql · 2.7 KB (2,803 bytes)
SET NAMES utf8mb4, backtick quoting,AUTO_INCREMENT, aJSONcolumn, backslash escapes,ON DUPLICATE KEY UPDATE, a stored procedure defined withDELIMITER, and a row that survivesROLLBACKbecauseCREATE TABLEcommitted it.- Testing MySQL-specific syntax and the DELIMITER command
- Demonstrating implicit commits
Real pg_dump output
sample-pg-dump.sql · 5.5 KB (5,648 bytes)
The database from
sample-schema.sql, dumped bypg_dump16 in plain format with--no-owner --no-privileges, unedited apart from a comment block at the top:SETlines,\restrict,CREATE TABLE,COPY … FROM stdindata blocks and constraints added after the data.- Testing restore pipelines and dump parsers
- Seeing what a real dump file looks like
UTF-8 with BOM and CRLF, many scripts
sample-utf8-bom-crlf.sql · 1.9 KB (1,923 bytes)
Starts with the UTF-8 byte order mark and uses Windows line endings. Inserts greetings in 15 languages and scripts, including Arabic, Hindi, Chinese, emoji and curly quotes, then selects them back.
- Spotting encoding problems in clients, imports and pipelines
- Testing BOM and CRLF handling
100 KB SQL file
sample-100kb.sql · 100 KB (102,400 bytes)
A portable script that creates one table and inserts 2,200 fictional sensor readings in batches of 100 rows, padded with comment lines to exactly 102,400 bytes.
- Upload and size-limit tests
- Import speed and batch-size tests
Ways to test with them
- Clients and CI: run
sample-schema.sqlwith your client and compare the results: order totals 34.00, 19.00 and 40.00, then Ada Example with 2 orders and 74.00. - Error handling: add a typo to a copy of
sample-schema.sqland run it with and withoutON_ERROR_STOP(psql),--force(mysql) or-bail(sqlite3), to see whether your pipeline stops where you expect. - Encoding: load
sample-utf8-bom-crlf.sqland select the rows back. AnyÃ,â€or?means a step didn't treat the file as UTF-8; in MySQL, also check the column isutf8mb4. - Restores: create an empty PostgreSQL database and restore
sample-pg-dump.sqlwithpsql -X -v ON_ERROR_STOP=1;SELECT * FROM order_totalsshould match the schema sample. - Upload limits:
sample-100kb.sqlis exactly 102,400 bytes and inserts exactly 2,200 rows.
Free to use for testing, teaching and demos, commercially or not, with no attribution needed. A link back to this page is always appreciated.
Put it online
Have a SQL file? Give it a link.
Drop a .sql file on 99helpers and it gets its own web address. Anyone who opens the link reads the script as plain text in their browser: it is never executed against any database, which makes it a simple way to share a schema, a migration or a query for review.
Questions
SQL files, frequently asked
What is a .sql file?
A plain-text script of SQL statements: commands that create tables, add or change data and run queries. A database client reads it and sends the statements to a database.
How do I open a .sql file?
Any text editor shows it, from Notepad to VS Code. To run it, open it in a database tool such as SSMS, DBeaver, pgAdmin or MySQL Workbench, or use a command-line client.
How do I run a .sql file?
With the client for your database: psql -d mydb -f file.sql for PostgreSQL, mysql mydb < file.sql for MySQL, sqlite3 my.db < file.sql for SQLite, or sqlcmd -i file.sql for SQL Server.
How do I import a .sql file into MySQL?
Create the database, then run mysql -u user -p mydb < file.sql in a terminal, or source file.sql at the mysql> prompt. In MySQL Workbench, use Server, Data Import, or open the file and execute it.
Why does my SQL file work in MySQL but not in PostgreSQL?
Each database speaks its own dialect. Backtick quoting, AUTO_INCREMENT, backslash escapes and DELIMITER are MySQL-only; PostgreSQL uses double quotes, identity columns and dollar quoting. Scripts have to be converted, by hand or with a tool.
Is a .sql file a database?
No. It's a text file of instructions. The data lives in the database server, or in a .db or .sqlite file for SQLite. A dump file can recreate a database, including all its data.
Is it safe to open a .sql file?
Opening it in an editor is safe; it's text. Running it is different: a script can delete or change data. Read it first and try it on a copy. Dumps may also contain personal data and should be kept private.
What is the MIME type of a .sql file?
application/sql, registered in RFC 6922 in 2013. Some systems send text/x-sql or text/plain instead.
Related formats
Other file types explained
Keep going
Related
Sources
- RFC 6922: The application/sql Media Type
- PostgreSQL documentation: SQL dump
- MySQL 8.4 manual: executing SQL statements from a text file
- SQLite: command line shell
- Microsoft Learn: GO (Transact-SQL)
- OWASP SQL Injection Prevention Cheat Sheet
Last reviewed 27 October 2026.