Complete Unabridged Guide
SELECT [DISTINCT | ALL]
column_list | * | expression
FROM table_name
[WHERE condition]
[GROUP BY column_list]
[HAVING condition]
[ORDER BY column_list [ASC | DESC]]
[LIMIT number]
[OFFSET number]
*, column_name, table.column, expression, column AS aliasFROM table_nameFROM table1, table2FROM table_name AS aliasFROM (SELECT ...) AS aliasComparison Operators: =, !=, <>, <, >, <=, >=
Logical Operators: AND, OR, NOT
Pattern Matching:
LIKE (% - Zero or more chars, _ - Single char)NOT LIKERange & Set Operations: BETWEEN x AND y, NOT BETWEEN, IN (a, b), NOT IN, IS NULL, IS NOT NULL
Exists: EXISTS (subquery), NOT EXISTS (subquery)
GROUP BY column1, column2, ...
Aggregate Functions:
COUNT(*), COUNT(column), COUNT(DISTINCT column)SUM(column), AVG(column)MIN(column), MAX(column)STDDEV(column), VARIANCE(column)Filter groups (used with GROUP BY)
HAVING aggregate_condition
ORDER BY column1 [ASC|DESC], column2 [ASC|DESC]
Options: NULLS FIRST, NULLS LAST
LIMIT number -- Restrict number of rows
OFFSET number -- Skip number of rows
Returns matching rows from both tables
SELECT columns
FROM table1
INNER JOIN table2 ON table1.column = table2.column
Returns all rows from left table, matching rows from right
SELECT columns
FROM table1
LEFT JOIN table2 ON table1.column = table2.column
Returns all rows from right table, matching rows from left
SELECT columns
FROM table1
RIGHT JOIN table2 ON table1.column = table2.column
Returns all rows when match in either table
SELECT columns
FROM table1
FULL OUTER JOIN table2 ON table1.column = table2.column
Cartesian product of both tables
SELECT columns
FROM table1
CROSS JOIN table2
Join table to itself
SELECT columns
FROM table1 t1
JOIN table1 t2 ON t1.column = t2.column
Automatic join based on columns with same names
SELECT columns
FROM table1
NATURAL JOIN table2
Returns single value
SELECT column
FROM table
WHERE column = (SELECT MAX(column) FROM table)
Returns single row
SELECT *
FROM table
WHERE (column1, column2) = (SELECT col1, col2 FROM table WHERE ...)
Returns multiple rows/columns
SELECT *
FROM table
WHERE column IN (SELECT column FROM other_table)
References outer query
SELECT t1.column
FROM table1 t1
WHERE EXISTS (SELECT 1 FROM table2 t2 WHERE t2.id = t1.id)
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...);
INSERT INTO table_name (column1, column2, ...)
VALUES
(value1a, value2a, ...),
(value1b, value2b, ...);
INSERT INTO table_name (column1, column2, ...)
SELECT column1, column2, ...
FROM other_table
WHERE condition;
INSERT INTO table_name (column1, column2)
VALUES (value1, DEFAULT);
UPDATE table_name
SET column1 = value1, column2 = value2
WHERE condition;
UPDATE table_name
SET column = column + 10
WHERE condition;
UPDATE table_name
SET column = (SELECT column FROM other_table WHERE ...)
WHERE condition;
UPDATE table1
SET table1.column = table2.column
FROM table1
JOIN table2 ON table1.id = table2.id
WHERE condition;
DELETE FROM table_name
WHERE condition;
DELETE FROM table_name;
DELETE FROM table_name
WHERE column IN (SELECT column FROM other_table WHERE ...);
MERGE INTO target_table
USING source_table
ON target_table.id = source_table.id
WHEN MATCHED THEN
UPDATE SET column = source_table.column
WHEN NOT MATCHED THEN
INSERT (column1, column2) VALUES (source.col1, source.col2);
CREATE DATABASE database_name
[CHARACTER SET charset_name]
[COLLATE collation_name];
CREATE TABLE table_name (
column1 datatype [constraints],
column2 datatype [constraints],
...,
[table_constraints]
);
Common Data Types:
Column Constraints:
NOT NULL - Cannot be nullNULL - Can be null (default)DEFAULT value - Default valueUNIQUE - All values must be uniquePRIMARY KEY - Unique identifierFOREIGN KEY - References another tableCHECK (condition) - Value must satisfy conditionAUTO_INCREMENT - Automatically increment (MySQL)IDENTITY - Auto-increment (SQL Server)SERIAL - Auto-increment (PostgreSQL)Table Constraints Example:
PRIMARY KEY (column1, column2),
FOREIGN KEY (column) REFERENCES other_table(column),
UNIQUE (column1, column2),
CHECK (condition),
CONSTRAINT constraint_name ...
CREATE TABLE new_table AS
SELECT columns
FROM existing_table
WHERE condition;
CREATE TEMPORARY TABLE temp_table (
column1 datatype,
column2 datatype
);
CREATE [UNIQUE] INDEX index_name
ON table_name (column1 [ASC|DESC], column2, ...);
CREATE [OR REPLACE] VIEW view_name AS
SELECT columns
FROM tables
WHERE condition;
CREATE PROCEDURE procedure_name (parameters)
BEGIN
-- SQL statements
END;
CREATE FUNCTION function_name (parameters)
RETURNS return_type
BEGIN
-- SQL statements
RETURN value;
END;
CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON table_name
FOR EACH ROW
BEGIN
-- SQL statements
END;
CREATE SCHEMA schema_name
[AUTHORIZATION user_name];
ALTER TABLE table_name
ADD column_name datatype [constraints];
ALTER TABLE table_name
DROP COLUMN column_name;
ALTER TABLE table_name
MODIFY COLUMN column_name new_datatype;
-- Or (PostgreSQL)
ALTER TABLE table_name
ALTER COLUMN column_name TYPE new_datatype;
ALTER TABLE table_name
RENAME COLUMN old_name TO new_name;
ALTER TABLE table_name
ADD CONSTRAINT constraint_name PRIMARY KEY (column);
ALTER TABLE table_name
ADD CONSTRAINT constraint_name FOREIGN KEY (column)
REFERENCES other_table(column);
ALTER TABLE table_name
ADD CONSTRAINT constraint_name UNIQUE (column);
ALTER TABLE table_name
ADD CONSTRAINT constraint_name CHECK (condition);
ALTER TABLE table_name
DROP CONSTRAINT constraint_name;
ALTER TABLE old_table_name
RENAME TO new_table_name;
DROP DATABASE [IF EXISTS] database_name;
DROP TABLE [IF EXISTS] table_name [CASCADE | RESTRICT];
DROP INDEX [IF EXISTS] index_name ON table_name;
DROP VIEW [IF EXISTS] view_name;
DROP PROCEDURE [IF EXISTS] procedure_name;
DROP FUNCTION [IF EXISTS] function_name;
DROP TRIGGER [IF EXISTS] trigger_name;
TRUNCATE TABLE table_name;
Removes all rows, resets auto-increment, faster than DELETE
GRANT privilege_list
ON object
TO user [WITH GRANT OPTION];
Privileges:
SELECT - Read dataINSERT - Insert dataUPDATE - Update dataDELETE - Delete dataEXECUTE - Execute procedures/functionsREFERENCES - Create foreign keysALL PRIVILEGES - All available privilegesExamples:
GRANT SELECT, INSERT ON database.table TO 'user'@'host';
GRANT ALL PRIVILEGES ON database.* TO 'user'@'host';
GRANT EXECUTE ON PROCEDURE procedure_name TO user;
REVOKE privilege_list
ON object
FROM user;
Example:
REVOKE INSERT, UPDATE ON database.table FROM 'user'@'host';
REVOKE ALL PRIVILEGES ON database.* FROM 'user'@'host';
BEGIN TRANSACTION;
-- or
START TRANSACTION;
-- or
BEGIN;
COMMIT;
Saves all changes made in current transaction
ROLLBACK;
Undoes all changes made in current transaction
SAVEPOINT savepoint_name;
ROLLBACK TO SAVEPOINT savepoint_name;
RELEASE SAVEPOINT savepoint_name;
SET TRANSACTION
[READ WRITE | READ ONLY]
[ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}];
Isolation Levels:
READ UNCOMMITTED - Dirty reads possibleREAD COMMITTED - No dirty readsREPEATABLE READ - Consistent reads within transactionSERIALIZABLE - Fully isolated transactionsCombines results, removes duplicates
SELECT columns FROM table1
UNION
SELECT columns FROM table2;
Combines results, keeps duplicates
SELECT columns FROM table1
UNION ALL
SELECT columns FROM table2;
Returns common rows
SELECT columns FROM table1
INTERSECT
SELECT columns FROM table2;
Returns rows in first query but not in second
SELECT columns FROM table1
EXCEPT
SELECT columns FROM table2;
WITH cte_name AS (
SELECT columns
FROM table
WHERE condition
)
SELECT *
FROM cte_name;
WITH
cte1 AS (SELECT ...),
cte2 AS (SELECT ...),
cte3 AS (SELECT ...)
SELECT *
FROM cte1
JOIN cte2 ON ...
JOIN cte3 ON ...;
WITH RECURSIVE cte_name AS (
-- Anchor member
SELECT columns FROM table WHERE condition
UNION ALL
-- Recursive member
SELECT columns FROM table
JOIN cte_name ON condition
)
SELECT * FROM cte_name;
function_name([arguments])
OVER (
[PARTITION BY partition_expression]
[ORDER BY sort_expression [ASC | DESC]]
[frame_clause]
)
ROW_NUMBER() - Sequential number for each rowRANK() - Rank with gaps for tiesDENSE_RANK() - Rank without gapsNTILE(n) - Divide rows into n groupsPERCENT_RANK() - Relative rank (0-1)CUME_DIST() - Cumulative distributionSUM(column) OVER (...)AVG(column) OVER (...)COUNT(column) OVER (...)MIN(column) OVER (...)MAX(column) OVER (...)FIRST_VALUE(column) - First value in windowLAST_VALUE(column) - Last value in windowNTH_VALUE(column, n) - Nth value in windowLAG(column, offset) - Value from previous rowLEAD(column, offset) - Value from next row{ROWS | RANGE} BETWEEN frame_start AND frame_end
Frame Options:
UNBOUNDED PRECEDING - Start of partitionn PRECEDING - n rows before currentCURRENT ROW - Current rown FOLLOWING - n rows after currentUNBOUNDED FOLLOWING - End of partitionExample:
SELECT
column,
SUM(amount) OVER (
PARTITION BY category
ORDER BY date
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) as running_total
FROM table;
CASE column
WHEN value1 THEN result1
WHEN value2 THEN result2
ELSE default_result
END
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
ELSE default_result
END
Returns first non-NULL value
COALESCE(column1, column2, default_value)
Returns NULL if two values are equal
NULLIF(expression1, expression2)
CAST(expression AS datatype)
CONVERT(datatype, expression)
CONCAT(str1, str2, ...) - Concatenate stringsSUBSTRING(str, start, length) - Extract substringLENGTH(str) or LEN(str) - String lengthUPPER(str) - Convert to uppercaseLOWER(str) - Convert to lowercaseTRIM(str) - Remove leading/trailing spacesLTRIM(str) - Remove leading spacesRTRIM(str) - Remove trailing spacesREPLACE(str, find, replace) - Replace substringLEFT(str, n) - Get leftmost n charactersRIGHT(str, n) - Get rightmost n charactersREVERSE(str) - Reverse stringCHARINDEX(find, str) or INSTR(str, find) - Find positionSTUFF(str, start, length, new) - Insert/replaceABS(n) - Absolute valueROUND(n, decimals) - Round numberCEILING(n) or CEIL(n) - Round upFLOOR(n) - Round downPOWER(base, exp) or POW(base, exp) - PowerSQRT(n) - Square rootMOD(n, divisor) - ModuloSIGN(n) - Sign of numberRAND() or RANDOM() - Random numberPI() - Pi constantEXP(n) - e raised to powerLOG(n) - Natural logarithmLOG10(n) - Base-10 logarithmNOW() or GETDATE() - Current date/timeCURDATE() or CURRENT_DATE - Current dateCURTIME() or CURRENT_TIME - Current timeDATE(datetime) - Extract dateTIME(datetime) - Extract timeYEAR(date) - Extract yearMONTH(date) - Extract monthDAY(date) - Extract dayHOUR(time) - Extract hourMINUTE(time) - Extract minuteSECOND(time) - Extract secondDAYNAME(date) - Day nameMONTHNAME(date) - Month nameDAYOFWEEK(date) - Day of week numberDAYOFYEAR(date) - Day of yearWEEK(date) - Week numberQUARTER(date) - Quarter numberDATEDIFF(date1, date2) - Difference in daysDATE_ADD(date, INTERVAL value unit) - Add intervalDATE_SUB(date, INTERVAL value unit) - Subtract intervalDATEADD(unit, value, date) - Add to dateDATEPART(unit, date) - Extract date partLAST_DAY(date) - Last day of monthIF(condition, true_value, false_value) - MySQLIIF(condition, true_value, false_value) - SQL ServerGREATEST(val1, val2, ...) - Maximum valueLEAST(val1, val2, ...) - Minimum valueCREATE INDEX idx_name ON table_name(column);
CREATE UNIQUE INDEX idx_name ON table_name(column);
CREATE INDEX idx_name ON table_name(column1, column2, column3);
CREATE INDEX idx_name ON table_name(column) WHERE condition;
CREATE FULLTEXT INDEX idx_name ON table_name(column);
CREATE SPATIAL INDEX idx_name ON table_name(geometry_column);
CREATE INDEX idx_name ON table_name(column1) INCLUDE (column2, column3);
-- Column level
CREATE TABLE table_name (id INT PRIMARY KEY);
-- Table level
CREATE TABLE table_name (id INT, PRIMARY KEY (id));
-- Composite
PRIMARY KEY (column1, column2)
FOREIGN KEY (column) REFERENCES parent_table(parent_column)
[ON DELETE {CASCADE | SET NULL | SET DEFAULT | RESTRICT | NO ACTION}]
[ON UPDATE {CASCADE | SET NULL | SET DEFAULT | RESTRICT | NO ACTION}]
Referential Actions:
CASCADE - Delete/update related rowsSET NULL - Set foreign key to NULLSET DEFAULT - Set to default valueRESTRICT - Prevent operationNO ACTION - Same as RESTRICT-- Column level
column_name datatype UNIQUE
-- Table level
UNIQUE (column1, column2)
CHECK (condition)
CONSTRAINT chk_name CHECK (condition)
column_name datatype DEFAULT default_value
column_name datatype NOT NULL
CREATE VIEW view_name AS
SELECT columns
FROM tables
WHERE condition;
CREATE OR REPLACE VIEW view_name AS
SELECT columns
FROM tables
WHERE condition;
Views are updatable if they meet criteria: Single table, No aggregate functions, No DISTINCT, GROUP BY, HAVING, No UNION.
CREATE MATERIALIZED VIEW view_name AS
SELECT columns
FROM tables
WHERE condition;
-- Refresh
REFRESH MATERIALIZED VIEW view_name;
CREATE PROCEDURE procedure_name (
IN param1 datatype,
OUT param2 datatype,
INOUT param3 datatype
)
BEGIN
DECLARE variable datatype;
-- SQL statements
SELECT column INTO variable FROM table;
IF condition THEN
-- statements
ELSEIF condition THEN
-- statements
ELSE
-- statements
END IF;
WHILE condition DO
-- statements
END WHILE;
REPEAT
-- statements
UNTIL condition
END REPEAT;
LOOP
-- statements
IF condition THEN
LEAVE loop_label;
END IF;
END LOOP;
SET param2 = value;
END;
CALL procedure_name(arg1, @out_var, arg3);
CREATE FUNCTION function_name (param1 datatype, param2 datatype)
RETURNS return_datatype
[DETERMINISTIC | NOT DETERMINISTIC]
BEGIN
DECLARE result datatype;
-- Logic
SET result = calculation;
RETURN result;
END;
SELECT function_name(value1, value2);
CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON table_name
FOR EACH ROW
BEGIN
-- Access OLD values: OLD.column_name
-- Access NEW values: NEW.column_name
IF condition THEN
-- statements
END IF;
END;
Trigger Events:
BEFORE INSERT - Before row insertedAFTER INSERT - After row insertedBEFORE UPDATE - Before row updatedAFTER UPDATE - After row updatedBEFORE DELETE - Before row deletedAFTER DELETE - After row deletedDROP TRIGGER [IF EXISTS] trigger_name;
DECLARE cursor_name CURSOR FOR
SELECT columns FROM table WHERE condition;
OPEN cursor_name;
FETCH cursor_name INTO variable1, variable2, ...;
CLOSE cursor_name;
DEALLOCATE cursor_name;
DECLARE @var1 datatype, @var2 datatype;
DECLARE cursor_name CURSOR FOR
SELECT column1, column2 FROM table WHERE condition;
OPEN cursor_name;
FETCH NEXT FROM cursor_name INTO @var1, @var2;
WHILE @@FETCH_STATUS = 0
BEGIN
-- Process row
FETCH NEXT FROM cursor_name INTO @var1, @var2;
END;
CLOSE cursor_name;
DEALLOCATE cursor_name;
BEGIN TRY
-- SQL statements
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine;
-- Handle error
ROLLBACK TRANSACTION;
END CATCH;
DECLARE exit_handler BOOLEAN DEFAULT FALSE;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
SET exit_handler = TRUE;
-- Handle error
END;
DECLARE CONTINUE HANDLER FOR NOT FOUND
BEGIN
-- Handle not found
END;
EXPLAIN SELECT * FROM table WHERE condition;
EXPLAIN ANALYZE SELECT * FROM table WHERE condition;
-- Index hint
SELECT * FROM table USE INDEX (index_name) WHERE condition;
SELECT * FROM table FORCE INDEX (index_name) WHERE condition;
SELECT * FROM table IGNORE INDEX (index_name) WHERE condition;
-- Join hints (SQL Server)
SELECT * FROM table1
INNER LOOP JOIN table2 ON ...; -- Nested loop
INNER HASH JOIN table2 ON ...; -- Hash join
INNER MERGE JOIN table2 ON ...; -- Merge join
-- Analyze table
ANALYZE TABLE table_name;
-- Update statistics
UPDATE STATISTICS table_name;
SHOW DATABASES;
-- or
SELECT schema_name FROM information_schema.schemata;
SHOW TABLES;
-- or
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'database_name';
SHOW COLUMNS FROM table_name;
-- or
DESCRIBE table_name;
-- or
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'table_name';
SHOW INDEXES FROM table_name;
-- or
SELECT * FROM information_schema.statistics
WHERE table_name = 'table_name';
SHOW CREATE TABLE table_name;
information_schema.tables - Table metadatainformation_schema.columns - Column metadatainformation_schema.constraints - Constraint metadatainformation_schema.key_column_usage - Key column infoinformation_schema.table_constraints - Table constraintsinformation_schema.referential_constraints - Foreign keysinformation_schema.views - View definitionsinformation_schema.routines - Stored procedures/functionsinformation_schema.triggers - Trigger definitionsmysqldump -u username -p database_name > backup.sql
mysqldump -u username -p --all-databases > all_backup.sql
mysql -u username -p database_name < backup.sql
pg_dump database_name > backup.sql
pg_dumpall > all_backup.sql
psql database_name < backup.sql
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
DROP USER 'username'@'host';
ALTER USER 'username'@'host' IDENTIFIED BY 'new_password';
SET PASSWORD FOR 'username'@'host' = PASSWORD('new_password');
SELECT user, host FROM mysql.user;
SHOW GRANTS FOR 'username'@'host';
-- Create role
CREATE ROLE role_name;
-- Grant privileges to role
GRANT SELECT, INSERT ON database.* TO role_name;
-- Assign role to user
GRANT role_name TO 'username'@'host';
-- Set default role
SET DEFAULT ROLE role_name TO 'username'@'host';
-- Drop role
DROP ROLE role_name;
-- SQL Server
SELECT *
FROM (
SELECT category, year, sales
FROM sales_data
) AS source
PIVOT (
SUM(sales)
FOR year IN ([2021], [2022], [2023])
) AS pivot_table;
-- MySQL/PostgreSQL (using CASE)
SELECT
category,
SUM(CASE WHEN year = 2021 THEN sales ELSE 0 END) AS '2021',
SUM(CASE WHEN year = 2022 THEN sales ELSE 0 END) AS '2022',
SUM(CASE WHEN year = 2023 THEN sales ELSE 0 END) AS '2023'
FROM sales_data
GROUP BY category;
-- SQL Server
SELECT category, year, sales
FROM sales_data
UNPIVOT (
sales FOR year IN (Y2021, Y2022, Y2023)
) AS unpivot_table;
-- MySQL/PostgreSQL (using UNION)
SELECT category, '2021' AS year, Y2021 AS sales FROM sales_data
UNION ALL
SELECT category, '2022' AS year, Y2022 AS sales FROM sales_data
UNION ALL
SELECT category, '2023' AS year, Y2023 AS sales FROM sales_data;
-- SQL Server
DECLARE @sql NVARCHAR(MAX);
SET @sql = 'SELECT * FROM ' + @table_name + ' WHERE id = ' + CAST(@id AS VARCHAR);
EXEC sp_executesql @sql;
-- MySQL
SET @sql = CONCAT('SELECT * FROM ', table_name, ' WHERE id = ', id);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- PostgreSQL
EXECUTE 'SELECT * FROM ' || table_name || ' WHERE id = ' || id;
-- MySQL
JSON_EXTRACT(json_column, '$.path.to.value')
json_column->>'$.path'
-- PostgreSQL
json_column->>'key'
json_column#>>'{key,nested}'
jsonb_column @> '{"key": "value"}'
-- MySQL
JSON_OBJECT('key1', value1, 'key2', value2)
JSON_ARRAY(value1, value2, value3)
-- PostgreSQL
json_build_object('key1', value1, 'key2', value2)
json_build_array(value1, value2, value3)
-- MySQL
JSON_SET(json_column, '$.path', new_value)
JSON_INSERT(json_column, '$.path', new_value)
JSON_REPLACE(json_column, '$.path', new_value)
JSON_REMOVE(json_column, '$.path')
-- PostgreSQL
jsonb_set(json_column, '{path}', new_value)
json_column || '{"new_key": "value"}'
-- MySQL
SELECT * FROM table
WHERE JSON_CONTAINS(json_array_column, '"value"');
-- PostgreSQL
SELECT * FROM table
WHERE json_column @> '[{"key": "value"}]';
CREATE FULLTEXT INDEX idx_fulltext ON table_name(column1, column2);
SELECT * FROM table_name
WHERE MATCH(column1, column2) AGAINST('search terms');
SELECT * FROM table_name
WHERE MATCH(column1, column2)
AGAINST('+required -excluded "exact phrase"' IN BOOLEAN MODE);
Boolean Operators: +word (Must contain), -word (Must not), "phrase", word* (Wildcard), word1 word2 (At least one).
SELECT * FROM table_name
WHERE MATCH(column1, column2)
AGAINST('search terms' WITH QUERY EXPANSION);
ALTER TABLE table_name
ADD COLUMN tsv tsvector;
UPDATE table_name
SET tsv = to_tsvector('english', column1 || ' ' || column2);
CREATE INDEX idx_tsv ON table_name USING GIN(tsv);
SELECT * FROM table_name
WHERE tsv @@ to_tsquery('english', 'word1 & word2');
SELECT * FROM table_name
WHERE tsv @@ plainto_tsquery('english', 'search terms');
SELECT *, ts_rank(tsv, query) AS rank
FROM table_name, to_tsquery('search') query
WHERE tsv @@ query
ORDER BY rank DESC;
CREATE TABLE sales (
id INT,
sale_date DATE,
amount DECIMAL(10,2)
)
PARTITION BY RANGE (YEAR(sale_date)) (
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
CREATE TABLE customers (
id INT,
name VARCHAR(100),
country VARCHAR(50)
)
PARTITION BY LIST (country) (
PARTITION p_usa VALUES IN ('USA'),
PARTITION p_europe VALUES IN ('UK', 'France', 'Germany'),
PARTITION p_asia VALUES IN ('China', 'Japan', 'India')
);
CREATE TABLE orders (
id INT,
customer_id INT,
order_date DATE
)
PARTITION BY HASH(customer_id)
PARTITIONS 4;
CREATE TABLE users (
id INT,
username VARCHAR(50),
email VARCHAR(100)
)
PARTITION BY KEY(id)
PARTITIONS 8;
CREATE TABLE logs (
id INT,
log_date DATE,
server_id INT
)
PARTITION BY RANGE (YEAR(log_date))
SUBPARTITION BY HASH(server_id)
SUBPARTITIONS 4 (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025)
);
-- Add partition
ALTER TABLE table_name ADD PARTITION (
PARTITION p2024 VALUES LESS THAN (2025)
);
-- Drop partition
ALTER TABLE table_name DROP PARTITION p2020;
-- Truncate partition
ALTER TABLE table_name TRUNCATE PARTITION p2020;
-- Reorganize partition
ALTER TABLE table_name REORGANIZE PARTITION p_future INTO (
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
-- Create sequence
CREATE SEQUENCE sequence_name
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 999999
CACHE 20;
-- Use sequence
INSERT INTO table_name (id, name)
VALUES (nextval('sequence_name'), 'value');
-- Get current value
SELECT currval('sequence_name');
-- Set sequence value
SELECT setval('sequence_name', 100);
-- Drop sequence
DROP SEQUENCE sequence_name;
-- Create table with auto-increment
CREATE TABLE table_name (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100)
);
-- Set auto-increment value
ALTER TABLE table_name AUTO_INCREMENT = 1000;
-- Get last inserted ID
SELECT LAST_INSERT_ID();
-- Create table with identity
CREATE TABLE table_name (
id INT IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(100)
);
-- Get last inserted ID
SELECT SCOPE_IDENTITY();
SELECT @@IDENTITY;
-- Reseed identity
DBCC CHECKIDENT ('table_name', RESEED, 1000);
POINT - Single locationLINESTRING - Sequence of pointsPOLYGON - Closed areaMULTIPOINT, MULTILINESTRING, MULTIPOLYGONGEOMETRYCOLLECTIONCREATE TABLE locations (
id INT PRIMARY KEY,
name VARCHAR(100),
coordinates POINT NOT NULL,
SPATIAL INDEX(coordinates)
);
-- MySQL
INSERT INTO locations (id, name, coordinates)
VALUES (1, 'Store A', ST_GeomFromText('POINT(40.7128 -74.0060)'));
-- PostgreSQL (PostGIS)
INSERT INTO locations (id, name, coordinates)
VALUES (1, 'Store A', ST_SetSRID(ST_MakePoint(-74.0060, 40.7128), 4326));
SELECT name,
ST_Distance(coordinates, ST_GeomFromText('POINT(40.7128 -74.0060)')) AS distance
FROM locations
ORDER BY distance;
SELECT * FROM locations
WHERE ST_Distance_Sphere(
coordinates,
ST_GeomFromText('POINT(40.7128 -74.0060)')
) <= 5000; -- 5km
SELECT * FROM locations
WHERE ST_Contains(
polygon_column,
ST_GeomFromText('POINT(40.7128 -74.0060)')
);
SELECT * FROM locations
WHERE ST_Intersects(geometry1, geometry2);
SELECT ST_Buffer(coordinates, 0.01) AS buffer_zone
FROM locations;
-- Create temporal table
CREATE TABLE Employee (
EmployeeID INT PRIMARY KEY,
Name VARCHAR(100),
Position VARCHAR(100),
Department VARCHAR(100),
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.EmployeeHistory));
-- Query current data
SELECT * FROM Employee;
-- Query historical data
SELECT * FROM Employee
FOR SYSTEM_TIME AS OF '2023-01-01';
-- Query all versions
SELECT * FROM Employee
FOR SYSTEM_TIME ALL
WHERE EmployeeID = 1;
-- Query between dates
SELECT * FROM Employee
FOR SYSTEM_TIME BETWEEN '2023-01-01' AND '2023-12-31'
WHERE EmployeeID = 1;
CREATE TABLE audit_log (
audit_id INT AUTO_INCREMENT PRIMARY KEY,
table_name VARCHAR(50),
operation VARCHAR(10),
old_values JSON,
new_values JSON,
user_id INT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Trigger for audit
CREATE TRIGGER audit_employee_update
AFTER UPDATE ON employee
FOR EACH ROW
BEGIN
INSERT INTO audit_log (table_name, operation, old_values, new_values, user_id)
VALUES (
'employee',
'UPDATE',
JSON_OBJECT('name', OLD.name, 'salary', OLD.salary),
JSON_OBJECT('name', NEW.name, 'salary', NEW.salary),
CURRENT_USER()
);
END;
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(100),
price DECIMAL(10,2),
deleted_at TIMESTAMP NULL,
deleted_by INT NULL
);
-- Soft delete
UPDATE products
SET deleted_at = NOW(), deleted_by = @user_id
WHERE id = 1;
-- Query active records
SELECT * FROM products WHERE deleted_at IS NULL;
-- Restore
UPDATE products
SET deleted_at = NULL, deleted_by = NULL
WHERE id = 1;
CREATE TABLE categories (
id INT PRIMARY KEY,
name VARCHAR(100),
parent_id INT,
FOREIGN KEY (parent_id) REFERENCES categories(id)
);
-- Get all children
WITH RECURSIVE category_tree AS (
SELECT id, name, parent_id, 0 AS level
FROM categories
WHERE id = 1
UNION ALL
SELECT c.id, c.name, c.parent_id, ct.level + 1
FROM categories c
JOIN category_tree ct ON c.parent_id = ct.id
)
SELECT * FROM category_tree;
CREATE TABLE categories (
id INT PRIMARY KEY,
name VARCHAR(100),
lft INT NOT NULL,
rgt INT NOT NULL
);
-- Get entire subtree
SELECT * FROM categories
WHERE lft >= @node_lft AND rgt <= @node_rgt
ORDER BY lft;
-- Get path to node
SELECT * FROM categories
WHERE lft <= @node_lft AND rgt >= @node_rgt
ORDER BY lft;
CREATE TABLE comments (
id INT PRIMARY KEY,
commentable_type VARCHAR(50),
commentable_id INT,
content TEXT,
INDEX (commentable_type, commentable_id)
);
-- Query comments for specific entity
SELECT * FROM comments
WHERE commentable_type = 'Post' AND commentable_id = 123;
CREATE TABLE student_courses (
student_id INT,
course_id INT,
enrollment_date DATE,
grade VARCHAR(2),
credits INT,
PRIMARY KEY (student_id, course_id),
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
-- Bad: Function on indexed column
SELECT * FROM orders WHERE YEAR(order_date) = 2023;
-- Good: Use range
SELECT * FROM orders
WHERE order_date >= '2023-01-01' AND order_date < '2024-01-01';
-- Bad: Leading wildcard
SELECT * FROM products WHERE name LIKE '%phone';
-- Good: Trailing wildcard (can use index)
SELECT * FROM products WHERE name LIKE 'phone%';
-- Bad: OR with different columns
SELECT * FROM customers WHERE name = 'John' OR email = 'john@example.com';
-- Good: Use UNION
SELECT * FROM customers WHERE name = 'John'
UNION
SELECT * FROM customers WHERE email = 'john@example.com';
-- Bad: SELECT *
SELECT * FROM large_table;
-- Good: Select only needed columns
SELECT id, name, email FROM large_table;
-- Use EXPLAIN to check join order
EXPLAIN SELECT * FROM large_table l
JOIN small_table s ON l.id = s.large_id;
-- Consider join order (smaller table first usually better)
-- Use STRAIGHT_JOIN to force join order (MySQL)
SELECT * FROM small_table
STRAIGHT_JOIN large_table ON small_table.id = large_table.small_id;
-- Often slower (correlated subquery)
SELECT name FROM products p
WHERE price > (SELECT AVG(price) FROM products WHERE category = p.category);
-- Usually faster (JOIN with aggregation)
SELECT p.name
FROM products p
JOIN (
SELECT category, AVG(price) as avg_price
FROM products
GROUP BY category
) avg_prices ON p.category = avg_prices.category
WHERE p.price > avg_prices.avg_price;
-- Bad: Large offset
SELECT * FROM large_table ORDER BY id LIMIT 1000000, 10;
-- Good: Use WHERE with last seen value
SELECT * FROM large_table
WHERE id > @last_seen_id
ORDER BY id
LIMIT 10;
TINYINT - 1 byte (-128 to 127 or 0 to 255)SMALLINT - 2 bytes (-32,768 to 32,767)MEDIUMINT - 3 bytes (-8,388,608 to 8,388,607)INT / INTEGER - 4 bytes (-2 billion to 2 billion)BIGINT - 8 bytes (-9 quintillion to 9 quintillion)DECIMAL(p,s) - Exact numeric, p=precision, s=scaleNUMERIC(p,s) - Same as DECIMALFLOAT - 4 bytes, single precisionDOUBLE - 8 bytes, double precisionREAL - Implementation dependentCHAR(n) - Fixed length, max 255VARCHAR(n) - Variable length, max 65,535TINYTEXT - Max 255 bytesTEXT - Max 65,535 bytesMEDIUMTEXT - Max 16MBLONGTEXT - Max 4GBBINARY(n) - Fixed binaryVARBINARY(n) - Variable binaryTINYBLOB, BLOB, MEDIUMBLOB, LONGBLOBDATE - YYYY-MM-DDTIME - HH:MM:SSDATETIME - YYYY-MM-DD HH:MM:SSTIMESTAMP - Unix timestampYEAR - YYYYBOOLEAN / BOOL - True/False (0/1)ENUM('val1', 'val2', ...) - One of predefined valuesSET('val1', 'val2', ...) - Zero or more of predefined valuesJSON - JSON documentUUID - Universally unique identifierGEOMETRY - Spatial dataPOINT - Spatial pointLINESTRING - Spatial linePOLYGON - Spatial polygonTransaction reads uncommitted data from another transaction
Same query returns different results within transaction
New rows appear in result set during transaction
-- Explicit table lock
LOCK TABLES table_name READ;
LOCK TABLES table_name WRITE;
UNLOCK TABLES;
-- Row-level locking
SELECT * FROM table_name WHERE id = 1 FOR UPDATE;
SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;
SELECT column, COUNT(*) as count
FROM table_name
GROUP BY column
HAVING COUNT(*) > 1;
DELETE t1 FROM table_name t1
INNER JOIN table_name t2
WHERE t1.id > t2.id AND t1.column = t2.column;
SELECT t1.id + 1 AS missing_id
FROM table_name t1
LEFT JOIN table_name t2 ON t1.id + 1 = t2.id
WHERE t2.id IS NULL;
SELECT date, amount,
SUM(amount) OVER (ORDER BY date) AS running_total
FROM transactions;
SELECT
id,
value,
LAG(value, 1) OVER (ORDER BY id) AS previous_value,
LEAD(value, 1) OVER (ORDER BY id) AS next_value
FROM table_name;
SELECT
category,
product,
sales,
RANK() OVER (PARTITION BY category ORDER BY sales DESC) AS rank_in_category
FROM products;
SELECT DISTINCT
category,
FIRST_VALUE(product) OVER (PARTITION BY category ORDER BY sales DESC) AS top_product,
LAST_VALUE(product) OVER (PARTITION BY category ORDER BY sales DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS bottom_product
FROM products;
SELECT AVG(value) AS median
FROM (
SELECT value,
ROW_NUMBER() OVER (ORDER BY value) AS rn,
COUNT(*) OVER () AS cnt
FROM table_name
) sub
WHERE rn IN (FLOOR((cnt + 1) / 2), CEIL((cnt + 1) / 2));
WITH numbered AS (
SELECT
id,
ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM table_name
),
islands AS (
SELECT
id,
id - rn AS island
FROM numbered
)
SELECT
MIN(id) AS start_id,
MAX(id) AS end_id,
COUNT(*) AS island_size
FROM islands
GROUP BY island;
SELECT * FROM products
ORDER BY id
LIMIT @page_size OFFSET (@page_number - 1) * @page_size;
-- Instead of:
SELECT * FROM users WHERE username = '" + userInput + "';
-- Use parameterized:
PREPARE stmt FROM 'SELECT * FROM users WHERE username = ?';
SET @username = userInput;
EXECUTE stmt USING @username;
End of SQL Master Reference Notes