SQL Dialects

You now know standard SQL, and that's most of what any database needs. But each system has its own dialect: different functions, data types and conveniences. This lesson gathers the differences you're most likely to meet when moving between SQLite, PostgreSQL, MySQL, SQL Server and Oracle.

The same query, five ways

"The five most recent orders with the customer's full details" uses identical joins everywhere — only the row limit differs:

SQL postgresql-mysql-sqlite
SELECT o.id, c.name FROM orders o JOIN customers c ON c.id = o.customer_id
ORDER BY o.order_date DESC LIMIT 5;
SQL sql-server
SELECT TOP 5 o.id, c.name FROM orders o JOIN customers c ON c.id = o.customer_id
ORDER BY o.order_date DESC;
SQL oracle-and-standard
SELECT o.id, c.name FROM orders o JOIN customers c ON c.id = o.customer_id
ORDER BY o.order_date DESC FETCH FIRST 5 ROWS ONLY;

Common differences

FeaturePostgreSQLMySQLSQL ServerOracleSQLite
Limit rowsLIMITLIMITTOP / OFFSET FETCHFETCH FIRSTLIMIT
Concatenate||CONCAT()+ / CONCAT()||||
Auto-incrementIDENTITY / SERIALAUTO_INCREMENTIDENTITYIDENTITYINTEGER PRIMARY KEY
Current timenow()NOW()GETDATE()SYSDATEdatetime('now')
Null defaultCOALESCEIFNULLISNULLNVLIFNULL
Boolean typeBOOLEANTINYINT(1)BITBOOLEAN (23ai)integer 0/1
Quoting names"name"`name`[name]"name""name"
UpsertON CONFLICTON DUPLICATE KEYMERGEMERGEON CONFLICT
Case-insensitive matchILIKELIKE (default collation)LIKE (default collation)UPPER() both sidesLIKE (ASCII)

COALESCE, CASE, CAST, joins, CTEs and window functions are standard and work in all five.

Exploring a database's structure

SQL postgresql-mysql-sql-server
SELECT table_name, column_name, data_type
FROM information_schema.columns
WHERE table_name = 'customers';
SQL
SELECT name, type, "notnull", pk FROM pragma_table_info('customers');
Result 6 rows
nametypenotnullpk
idINTEGER01
nameTEXT10
emailTEXT00
cityTEXT00
countryTEXT10
signup_dateDATE10

The standard information_schema views describe tables and columns in PostgreSQL, MySQL and SQL Server. SQLite uses sqlite_schema and pragma_table_info; Oracle has its own data dictionary views (USER_TABLES, USER_TAB_COLUMNS).

Procedural extensions

Each server database adds a procedural language for stored procedures and functions — variables, loops and error handling running inside the database:

DatabaseLanguage
PostgreSQLPL/pgSQL (and others, such as PL/Python)
SQL ServerT-SQL
OraclePL/SQL
MySQLStored procedures in SQL/PSM style
SQLiteNone — logic lives in the application
SQL postgresql
CREATE FUNCTION order_total(p_order_id integer) RETURNS numeric AS $$
  SELECT SUM(quantity * unit_price) FROM order_items WHERE order_id = p_order_id;
$$ LANGUAGE sql STABLE;

SELECT id, order_total(id) FROM orders;

Choosing a database

  • SQLite — embedded in an app, mobile, desktop, tests, small sites; one file, zero setup.
  • PostgreSQL — a strong default for new server applications: standards-compliant, extensible, rich types (JSONB, arrays, full-text, geospatial with PostGIS).
  • MySQL / MariaDB — widespread on web hosting and in many established platforms.
  • SQL Server / Oracle — common in enterprises with existing Microsoft or Oracle ecosystems.
  • Cloud warehouses (BigQuery, Snowflake, Redshift, Databricks) — analytics over very large datasets, with their own SQL dialects.

Writing portable SQL

  • Prefer standard features: COALESCE over IFNULL, CASE over IF, CAST over ::.
  • Use ISO date strings and explicit casts.
  • Don't rely on implicit behaviours: the order of rows without ORDER BY, case sensitivity, integer division, where NULLs sort.
  • Test against the database you'll actually run in production.

Try it yourself

Inspect the demo database's own structure.

Try it yourself
Result