+ You can use this SQL Minifier to clean and optimize your SQL queries
+ by removing comments and extra spaces. Just paste your SQL and get a
+ minified result instantly. Made with 💜 by the developers building
+ Jam.
+
+
+
+
+
How to Use the SQL Minifier
+
+ Whether you're working with large queries or optimizing database
+ performance, our SQL Minifier helps streamline your SQL code in
+ seconds—no signup required.
+
+
+ The tool ensures your SQL remains functional while improving
+ readability and execution speed.
+
+
+
+
+
Benefits of Minifying SQL
+
+ Minified SQL reduces unnecessary whitespace and removes comments,
+ making queries more efficient and easier to process.
+
+
+
+ Performance Optimization: Minified SQL runs faster by
+ eliminating extra spaces and comments.
+
+
+ Reduced Query Size: Smaller queries help in better
+ database management and quicker execution.
+
+
+ Clean Code: Removing comments and extra whitespace
+ results in neater, more readable queries.
+
+
+
+
+
+
FAQs
+
+
+ What does the SQL Minifier do? It removes comments,
+ extra spaces, and unnecessary formatting to create optimized SQL
+ queries.
+
+
+ Does minifying SQL improve performance? Yes, minified
+ SQL executes slightly faster and is easier to store and transfer.
+
+
+ Will my SQL logic remain intact? Absolutely! This tool
+ only removes unnecessary characters without altering the query
+ logic.
+
+
+ Is the SQL Minifier free? Yes, it's completely free
+ and accessible without any signup or installation.
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/components/utils/sql-minifier.utils.test.ts b/components/utils/sql-minifier.utils.test.ts
new file mode 100644
index 0000000..2337c74
--- /dev/null
+++ b/components/utils/sql-minifier.utils.test.ts
@@ -0,0 +1,183 @@
+import { minifySQL, validateSQLInput } from './sql-minifier.utils';
+
+describe('sql-minifier.utils', () => {
+ describe('minifySQL', () => {
+ test('should handle basic SQL without comments', () => {
+ const input = 'SELECT * FROM users WHERE id = 1';
+ const expected = 'SELECT * FROM users WHERE id = 1';
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should remove single-line comments', () => {
+ const input = `SELECT * FROM users -- this is a comment
+WHERE id = 1`;
+ const expected = 'SELECT * FROM users WHERE id = 1';
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should remove multi-line comments', () => {
+ const input = `SELECT * /* this is a
+multi-line comment */ FROM users WHERE id = 1`;
+ const expected = 'SELECT * FROM users WHERE id = 1';
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should preserve strings with spaces', () => {
+ const input = `SELECT 'hello world' FROM users WHERE name = 'John Doe'`;
+ const expected = `SELECT 'hello world' FROM users WHERE name = 'John Doe'`;
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should not remove double dashes inside strings', () => {
+ const input = `SELECT 'this -- is not a comment' FROM users`;
+ const expected = `SELECT 'this -- is not a comment' FROM users`;
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle single quotes inside double quotes', () => {
+ const input = `SELECT "It's a test" FROM users`;
+ const expected = `SELECT "It's a test" FROM users`;
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle double quotes inside single quotes', () => {
+ const input = `SELECT 'He said "hello"' FROM users`;
+ const expected = `SELECT 'He said "hello"' FROM users`;
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle escaped quotes in strings', () => {
+ const input = `SELECT 'It''s a test' FROM users WHERE name = "John ""Big"" Doe"`;
+ const expected = `SELECT 'It''s a test' FROM users WHERE name = "John ""Big"" Doe"`;
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle complex query with mixed content', () => {
+ const input = `
+ SELECT
+ u.name, -- user name
+ u.email,
+ p.title /* post title */
+ FROM users u
+ JOIN posts p ON u.id = p.user_id
+ WHERE u.name = 'John -- not a comment'
+ AND p.created_at > '2023-01-01'
+ /* AND p.status = 'published' -- this is commented out */
+ `;
+ const expected = `SELECT u.name, u.email, p.title FROM users u JOIN posts p ON u.id = p.user_id WHERE u.name = 'John -- not a comment' AND p.created_at > '2023-01-01'`;
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle comments at end of line correctly', () => {
+ const input = `SELECT * FROM users WHERE id = 1 -- comment`;
+ const expected = 'SELECT * FROM users WHERE id = 1';
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle comments in middle of line', () => {
+ const input = `SELECT * /* comment */ FROM users`;
+ const expected = 'SELECT * FROM users';
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle multiple consecutive comments', () => {
+ const input = `SELECT * -- comment1
+-- comment2
+FROM users /* comment3 */ /* comment4 */`;
+ const expected = 'SELECT * FROM users';
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should preserve necessary whitespace around operators', () => {
+ const input = `SELECT * FROM users WHERE id=1 AND name<>'test'`;
+ const expected = `SELECT * FROM users WHERE id=1 AND name<>'test'`;
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle empty input', () => {
+ expect(minifySQL('')).toBe('');
+ expect(minifySQL(' ')).toBe('');
+ });
+
+ test('should handle input with only comments', () => {
+ const input = `-- just a comment
+/* another comment */`;
+ expect(minifySQL(input)).toBe('');
+ });
+
+ test('should throw error for non-string input', () => {
+ expect(() => minifySQL(null as unknown as string)).toThrow('Input must be a string');
+ expect(() => minifySQL(undefined as unknown as string)).toThrow('Input must be a string');
+ expect(() => minifySQL(123 as unknown as string)).toThrow('Input must be a string');
+ });
+
+ test('should handle nested comment-like patterns in strings', () => {
+ const input = `SELECT 'Price: $/* not a comment */' FROM products`;
+ const expected = `SELECT 'Price: $/* not a comment */' FROM products`;
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle SQL with line breaks and tabs', () => {
+ const input = `SELECT\t*\nFROM\tusers\n\tWHERE\tid = 1`;
+ const expected = 'SELECT * FROM users WHERE id = 1';
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle malformed comments gracefully', () => {
+ // Unclosed multi-line comment should be treated as comment to end of string
+ const input = `SELECT * FROM users /* unclosed comment`;
+ const expected = 'SELECT * FROM users';
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should preserve strings with newlines', () => {
+ const input = `SELECT 'line1\nline2' FROM users`;
+ const expected = `SELECT 'line1\nline2' FROM users`;
+ expect(minifySQL(input)).toBe(expected);
+ });
+
+ test('should handle multiple single-line comments on same line', () => {
+ const input = `SELECT * FROM users -- comment1 -- comment2`;
+ const expected = 'SELECT * FROM users';
+ expect(minifySQL(input)).toBe(expected);
+ });
+ });
+
+ describe('validateSQLInput', () => {
+ test('should validate correct string input', () => {
+ const result = validateSQLInput('SELECT * FROM users');
+ expect(result.isValid).toBe(true);
+ expect(result.error).toBeUndefined();
+ });
+
+ test('should reject non-string input', () => {
+ const result = validateSQLInput(123 as unknown as string);
+ expect(result.isValid).toBe(false);
+ expect(result.error).toBe('Input must be a string');
+ });
+
+ test('should reject empty input', () => {
+ const result = validateSQLInput('');
+ expect(result.isValid).toBe(false);
+ expect(result.error).toBe('Input cannot be empty');
+ });
+
+ test('should reject whitespace-only input', () => {
+ const result = validateSQLInput(' ');
+ expect(result.isValid).toBe(false);
+ expect(result.error).toBe('Input cannot be empty');
+ });
+
+ test('should validate input with comments', () => {
+ const result = validateSQLInput('SELECT * FROM users -- comment');
+ expect(result.isValid).toBe(true);
+ expect(result.error).toBeUndefined();
+ });
+
+ test('should validate input with strings containing special characters', () => {
+ const result = validateSQLInput(`SELECT 'test -- not comment' FROM users`);
+ expect(result.isValid).toBe(true);
+ expect(result.error).toBeUndefined();
+ });
+ });
+});
\ No newline at end of file
diff --git a/components/utils/sql-minifier.utils.ts b/components/utils/sql-minifier.utils.ts
new file mode 100644
index 0000000..3ab1d19
--- /dev/null
+++ b/components/utils/sql-minifier.utils.ts
@@ -0,0 +1,205 @@
+/**
+ * SQL Minifier utility that safely removes comments and unnecessary whitespace
+ * while preserving string literals and essential SQL syntax
+ */
+
+/**
+ * Minifies SQL by removing comments and unnecessary whitespace while preserving string literals
+ */
+export function minifySQL(sql: string): string {
+ if (typeof sql !== 'string') {
+ throw new Error('Input must be a string');
+ }
+
+ if (sql.trim() === '') {
+ return '';
+ }
+
+ try {
+ let result = '';
+ let i = 0;
+
+ while (i < sql.length) {
+ const char = sql[i];
+
+ // Handle single-quoted strings
+ if (char === "'") {
+ let stringContent = "'";
+ i++; // skip opening quote
+
+ while (i < sql.length) {
+ stringContent += sql[i];
+ if (sql[i] === "'") {
+ // Check if it's escaped (doubled quote)
+ if (i + 1 < sql.length && sql[i + 1] === "'") {
+ i++; // skip first quote
+ stringContent += sql[i]; // add second quote
+ } else {
+ // End of string
+ break;
+ }
+ }
+ i++;
+ }
+
+ result += stringContent;
+ i++;
+ continue;
+ }
+
+ // Handle double-quoted strings
+ if (char === '"') {
+ let stringContent = '"';
+ i++; // skip opening quote
+
+ while (i < sql.length) {
+ stringContent += sql[i];
+ if (sql[i] === '"') {
+ // Check if it's escaped (doubled quote)
+ if (i + 1 < sql.length && sql[i + 1] === '"') {
+ i++; // skip first quote
+ stringContent += sql[i]; // add second quote
+ } else {
+ // End of string
+ break;
+ }
+ }
+ i++;
+ }
+
+ result += stringContent;
+ i++;
+ continue;
+ }
+
+ // Handle multi-line comments /* ... */
+ if (char === '/' && i + 1 < sql.length && sql[i + 1] === '*') {
+ i += 2; // skip /*
+
+ // Find closing */ or end of string
+ let found = false;
+ while (i < sql.length - 1) {
+ if (sql[i] === '*' && sql[i + 1] === '/') {
+ i += 2; // skip */
+ found = true;
+ break;
+ }
+ i++;
+ }
+
+ // If we didn't find closing */, we consumed everything to the end
+ if (!found) {
+ i = sql.length;
+ }
+
+ // Add space if we removed a comment between words
+ if (result.length > 0 && /\w/.test(result.slice(-1))) {
+ // Look ahead to see if next non-whitespace character is a word character
+ let j = i;
+ while (j < sql.length && /\s/.test(sql[j])) {
+ j++;
+ }
+ if (j < sql.length && /\w/.test(sql[j])) {
+ result += ' ';
+ }
+ }
+ continue;
+ }
+
+ // Handle single-line comments --
+ if (char === '-' && i + 1 < sql.length && sql[i + 1] === '-') {
+ // Find end of line or end of string
+ while (i < sql.length && sql[i] !== '\n' && sql[i] !== '\r') {
+ i++;
+ }
+
+ // Add space if we removed a comment between words and there's more content
+ if (result.length > 0 && /\w/.test(result.slice(-1))) {
+ // Look ahead to see if there's more content after the newline
+ let j = i;
+ while (j < sql.length && /[\r\n\s]/.test(sql[j])) {
+ j++;
+ }
+ if (j < sql.length && /\w/.test(sql[j])) {
+ result += ' ';
+ }
+ }
+ continue;
+ }
+
+ // Handle regular characters and whitespace
+ if (/\s/.test(char)) {
+ // Replace multiple whitespace characters with single space
+ // but only if we don't already have a space at the end
+ if (result.length > 0 && !result.endsWith(' ')) {
+ result += ' ';
+ }
+
+ // Skip additional whitespace
+ while (i + 1 < sql.length && /\s/.test(sql[i + 1])) {
+ i++;
+ }
+ } else {
+ // Regular character
+ result += char;
+ }
+
+ i++;
+ }
+
+ // Final cleanup
+ return result.trim();
+ } catch (error) {
+ throw new Error(`Failed to minify SQL: ${error instanceof Error ? error.message : 'Unknown error'}`);
+ }
+}
+
+/**
+ * Validates that the input is a valid string for SQL minification
+ */
+export function validateSQLInput(input: string): { isValid: boolean; error?: string } {
+ if (typeof input !== 'string') {
+ return { isValid: false, error: 'Input must be a string' };
+ }
+
+ if (input.trim() === '') {
+ return { isValid: false, error: 'Input cannot be empty' };
+ }
+
+ // Basic validation - check for unmatched quotes
+ let singleQuoteCount = 0;
+ let doubleQuoteCount = 0;
+ let i = 0;
+
+ while (i < input.length) {
+ if (input[i] === "'") {
+ if (i + 1 < input.length && input[i + 1] === "'") {
+ // Skip escaped quote
+ i += 2;
+ } else {
+ singleQuoteCount++;
+ i++;
+ }
+ } else if (input[i] === '"') {
+ if (i + 1 < input.length && input[i + 1] === '"') {
+ // Skip escaped quote
+ i += 2;
+ } else {
+ doubleQuoteCount++;
+ i++;
+ }
+ } else {
+ i++;
+ }
+ }
+
+ if (singleQuoteCount % 2 !== 0) {
+ return { isValid: false, error: 'Unmatched single quote' };
+ }
+
+ if (doubleQuoteCount % 2 !== 0) {
+ return { isValid: false, error: 'Unmatched double quote' };
+ }
+
+ return { isValid: true };
+}
\ No newline at end of file
diff --git a/components/utils/tools-list.ts b/components/utils/tools-list.ts
index ac99700..ef41923 100644
--- a/components/utils/tools-list.ts
+++ b/components/utils/tools-list.ts
@@ -143,4 +143,10 @@ export const tools = [
"Convert images to WebP format with batch processing and quality control. Reduce file sizes while maintaining image quality.",
link: "/utilities/webp-converter",
},
+ {
+ title: "SQL Minifier",
+ description:
+ "Minify SQL by removing comments, extra spaces, and formatting for cleaner, optimized queries.",
+ link: "/utilities/sql-minifier",
+ },
];
diff --git a/pages/utilities/sql-minifier.tsx b/pages/utilities/sql-minifier.tsx
new file mode 100644
index 0000000..c9cfa13
--- /dev/null
+++ b/pages/utilities/sql-minifier.tsx
@@ -0,0 +1,103 @@
+import { useCallback, useState } from "react";
+import { Textarea } from "@/components/ds/TextareaComponent";
+import PageHeader from "@/components/PageHeader";
+import { Card } from "@/components/ds/CardComponent";
+import { Button } from "@/components/ds/ButtonComponent";
+import { Label } from "@/components/ds/LabelComponent";
+import Header from "@/components/Header";
+import { useCopyToClipboard } from "@/components/hooks/useCopyToClipboard";
+import { CMDK } from "@/components/CMDK";
+import CallToActionGrid from "../../components/CallToActionGrid";
+import Meta from "@/components/Meta";
+import SQLMinifierSEO from "@/components/seo/SQLMinifierSEO";
+import { minifySQL, validateSQLInput } from "@/components/utils/sql-minifier.utils";
+
+export default function SQLMinifier() {
+ const [input, setInput] = useState("");
+ const [output, setOutput] = useState("");
+ const [error, setError] = useState("");
+ const { buttonText, handleCopy } = useCopyToClipboard();
+
+ const handleChange = useCallback(
+ (event: React.ChangeEvent) => {
+ const { value } = event.currentTarget;
+ setInput(value);
+ setError("");
+
+ if (value.trim() === "") {
+ setOutput("");
+ return;
+ }
+
+ const validation = validateSQLInput(value);
+ if (!validation.isValid) {
+ setError(validation.error || "Invalid input");
+ setOutput("");
+ return;
+ }
+
+ try {
+ const minified = minifySQL(value);
+ setOutput(minified);
+ } catch (err) {
+ const errorMessage = err instanceof Error ? err.message : "Failed to minify SQL";
+ setError(errorMessage);
+ setOutput("");
+ }
+ },
+ []
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file