SQL Minifier

Paste one or more SQL statements to squeeze them onto as few characters as the dialect allows. The query is validated first, so broken SQL is reported instead of compressed.

Input

Settings

History

Load from URL

Why minify a query

Databases ignore formatting, but many places that carry SQL do not. A query embedded in a JSON config, a YAML pipeline, an environment variable or a Java string literal is easier to handle on one line. Logging and APM tools group queries by text, so stripping comments and layout makes the same statement look the same everywhere. ORMs and query builders sometimes emit SQL with odd spacing that a minifier normalises. And for comparing two versions of a query, minifying both removes formatting noise from the diff.

The savings are modest compared with code minifiers, because SQL has no names to shorten: the report query in the first example goes from 163 to 115 bytes. The value is in a predictable, compact form rather than raw size.

What is removed and what is kept

Minification works on the token stream from a dialect-aware tokenizer, so strings, quoted identifiers and comments are recognised exactly as your database would read them.

  • Line comments (-- ...) and block comments (/* ... */) are dropped.
  • Optimizer hints of the form /*+ INDEX(o idx_orders_created) */ are kept, since removing them can change the execution plan. Oracle’s line hints (--+ FULL(o)) are kept too and still end their line.
  • MySQL executable comments, /*!40101 SET NAMES utf8mb4 */ as found in every mysqldump file, are kept because MySQL runs their contents.
  • Whitespace is removed wherever two tokens can touch without changing meaning, and a single space is kept only where gluing them would merge or alter tokens: between two words, between two operators (so a - -1 never becomes a--1, which would start a comment), and between a minus and a number.
  • Client batch separators stay on their own lines: T-SQL GO with the T-SQL (SQL Server) dialect and the SQL*Plus / after a PL/SQL block with PL/SQL (Oracle). Those tools only recognise them alone on a line.

String literals, including doubled quotes as in 'Ben O''Brien', quoted identifiers and keyword case are left exactly as written. Statements stay in order, separated by their semicolons.

Choose the right Dialect

The Dialect option matters more when minifying than it seems, because it decides which characters start strings, identifiers, parameters and comments. Backticks quote identifiers in MySQL and BigQuery, square brackets do so in T-SQL, $$ ... $$ encloses a string body in PostgreSQL and Snowflake, and # starts a comment in MySQL but not in PostgreSQL. That last difference shows why it matters: SELECT 1 # note loses # note under MySQL, yet keeps it under PostgreSQL, where # is the bitwise XOR operator. Pick the database the query is written for and the tokenizer will treat each character the way that engine does. Names quoted in another dialect’s style, such as [Order Date] in a PostgreSQL query, produce a warning that suggests the matching dialect.

The formatting options (Keyword case, Indent style, Commas and so on) only shape beautified output; the minifier never rewrites keywords.

Validation and privacy

Minify mode still runs the full sql-formatter parse used for beautifying, so an unterminated string, an unclosed bracket or a statement that stops after WHERE halts with the same error and position you would get when formatting. Switch views with Ctrl/Cmd+Shift+M and copy with Ctrl/Cmd+Shift+C. Queries are minified inside your browser, which matters when they contain table names, customer IDs or literal values from production.

Examples

Oracle report query with an optimizer hint

Both comments disappear but the /*+ */ hint stays, and the :since bind variable is accepted under the PL/SQL dialect.

Input
-- daily revenue report
SELECT /*+ INDEX(o idx_orders_created) */
  o.id,
  o.total   -- gross
FROM orders o
WHERE o.created_at >= :since
  AND o.status = 'paid';
Output
SELECT/*+ INDEX(o idx_orders_created) */o.id,o.total FROM orders o WHERE o.created_at>= :since AND o.status='paid';
Open this example in the tool

mysqldump excerpt with an executable comment

The /*!40101 … */ comment is kept because MySQL executes it, and the doubled quote inside the string is not touched.

Input
/*!40101 SET NAMES utf8mb4 */;
-- seed data
INSERT INTO customers (id, name, email)
VALUES
  (1, 'Aisha Tan', '[email protected]'),
  (2, 'Ben O''Brien', '[email protected]');
Output
/*!40101 SET NAMES utf8mb4 */;INSERT INTO customers(id,name,email)VALUES(1,'Aisha Tan','[email protected]'),(2,'Ben O''Brien','[email protected]');
Open this example in the tool

SQL Server script with GO batches

Each batch is compacted onto one line, while every GO stays alone on its own line so sqlcmd and SSMS still split the script.

Input
CREATE TABLE dbo.Orders (
  Id INT NOT NULL PRIMARY KEY,
  Total DECIMAL(10, 2) NOT NULL -- gross amount
);
GO
/* seed */
INSERT INTO dbo.Orders (Id, Total) VALUES (1, 129.90);
GO
Output
CREATE TABLE dbo.Orders(Id INT NOT NULL PRIMARY KEY,Total DECIMAL(10,2)NOT NULL);
GO
INSERT INTO dbo.Orders(Id,Total)VALUES(1,129.90);
GO
Open this example in the tool

PL/SQL block followed by a query

The slash that tells SQL*Plus to run the block keeps its own line, and the space between the minus and 365 is kept.

Input
BEGIN
  -- archive old rows
  DELETE FROM orders_archive WHERE created_at < SYSDATE - 365;
  COMMIT;
END;
/
SELECT COUNT(*) FROM orders_archive;
Output
BEGIN DELETE FROM orders_archive WHERE created_at<SYSDATE- 365;COMMIT;END;
/
SELECT COUNT(*)FROM orders_archive;
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
This string is never closed — the ' has no matching '
Explained
A string literal is missing its closing quote, often because an apostrophe in a name was not doubled.Close the string, and write an apostrophe inside a string as two quotes: ‘O’‘Brien’.
This '(' is never closed
Explained
An opening parenthesis in a function call, IN list or subquery has no partner.Add the missing ) where the expression ends. The column points at the unmatched (.
The statement ends with "WHERE" but nothing follows itThe query was cut off after a keyword or operator, for example when a condition was built dynamically and came out empty.Complete the clause or remove the keyword. The same check applies to a trailing comma or a dangling = at the end of a statement.
This /* comment is never closedA block comment opens with /* but has no */, so the rest of the script would be swallowed by it.Add */ where the comment should end.

Frequently asked questions

Does the SQL minifier remove optimizer hints?

No. Comments starting with /+ are kept, as are Oracle --+ line hints and MySQL /! */ executable comments, because the database acts on them.

Will minified SQL run the same?

Yes. Only comments and whitespace that cannot affect tokenisation are removed, and a space is kept wherever two tokens would otherwise merge.

Can I minify several statements at once?

Yes. Statements keep their semicolons and order. T-SQL GO and the PL/SQL / separator are written on their own lines when the matching dialect is selected.

Does it change keyword case?

No. Minify keeps keywords as written. To normalise case, beautify with the Keyword case option first and then minify the result.

Related tools