Using SQL Functions

1. Using String Functions

FunctionResult
LENGTH(s)Char count
UPPER(s) / LOWER(s)Case conversion
TRIM(s) / LTRIM / RTRIMStrip whitespace
SUBSTRING(s FROM x FOR n)Slice
REPLACE(s, a, b)Substitute
CONCAT(a,b) / a || bConcatenate
POSITION(sub IN s)Find index
SPLIT_PART(s, d, n)Nth split (PG)
REGEXP_REPLACE / REGEXP_MATCHRegex ops
FORMAT(fmt, args)printf-like (PG)

2. Using Numeric Functions

FunctionReturns
ABS, SIGNMagnitude / sign
CEIL, FLOOR, ROUND(x, n)Rounding
MOD(a,b) / %Remainder
POWER(x, y), SQRT(x)Exponent / root
LN, LOG, EXPLogs / exponential
SIN/COS/TAN/...Trig
RANDOM()0–1 random (PG); MySQL: RAND()
GREATEST / LEASTMax/min across args

3. Using Date Functions

FunctionUse
NOW() / CURRENT_TIMESTAMPNow (with tz)
CURRENT_DATE / CURRENT_TIMEDate / time only
date_trunc('month', ts)Truncate to unit (PG)
EXTRACT(YEAR FROM ts)Get field
AGE(t1, t2) / t1 - t2Interval
+/- INTERVAL '1 day'Arithmetic
to_char(ts, 'YYYY-MM-DD')Format
to_timestamp(text, fmt)Parse

4. Using Conversion Functions

FunctionUse
CAST(x AS type)Standard conversion
x::typePostgres shorthand
CONVERT(type, x)SQL Server / MySQL
to_number / to_char / to_dateFormat-specific (PG/Oracle)
TRY_CAST / SAFE_CASTReturn NULL on failure (some DBs)

5. Using Conditional Functions

FunctionExample
CASECASE WHEN x > 0 THEN 'pos' WHEN x < 0 THEN 'neg' ELSE 'zero' END
COALESCEFirst non-null
NULLIFNULL if a=b
IIF (SQL Server)IIF(cond, then, else)
IF (MySQL)IF(cond, then, else)
DECODE (Oracle)Legacy switch

6. Using Window Functions

FunctionPurpose
ROW_NUMBER()Sequential rank per partition
RANK() / DENSE_RANK()With ties (gap / no gap)
NTILE(n)Buckets 1..n
LAG(col, n) / LEAD(col, n)Previous / next row value
FIRST_VALUE / LAST_VALUEWindow endpoints
PERCENT_RANK / CUME_DISTPercentile

Example: Greatest-N-per-group

SELECT *
FROM (
  SELECT o.*, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY placed_at DESC) AS rn
  FROM orders o
) x
WHERE rn <= 3;  -- 3 most recent per customer

7. Using Aggregate Window Functions

PatternExample
Running totalSUM(amt) OVER (ORDER BY ts ROWS UNBOUNDED PRECEDING)
Moving averageAVG(x) OVER (ORDER BY ts ROWS 6 PRECEDING)
Per-group totalSUM(x) OVER (PARTITION BY region)
FrameROWS / RANGE / GROUPS modes

8. Creating User-Defined Functions

AspectDetail
LanguagesSQL, PL/pgSQL, PL/Python, PL/V8, Java (Oracle)
Volatility (PG)IMMUTABLE, STABLE, VOLATILE — affects caching
SECURITY DEFINERRun as creator (use cautiously)
InliningSimple SQL fns may be inlined into plans

Example: PL/pgSQL Function

CREATE FUNCTION discount(p NUMERIC, pct NUMERIC)
RETURNS NUMERIC LANGUAGE plpgsql IMMUTABLE AS $
BEGIN
  RETURN p * (1 - pct/100.0);
END;
$;

9. Creating Scalar Functions

PropertyDetail
ReturnsSingle value per call
Use inSELECT, WHERE, ORDER BY, CHECK
CaveatCan prevent index use if applied to indexed column
MitigationUse generated columns or function-based indexes

10. Creating Table-Valued Functions

TypeDetail
Inline TVFSingle SELECT, planner can inline
Multi-statement TVFReturns built-up rows, opaque to planner
SETOF / TABLE returnPG syntax for table-returning functions
UseSELECT * FROM my_fn(args)

Example: SETOF Function (PG)

CREATE FUNCTION recent_orders(cust BIGINT, days INT)
RETURNS TABLE(id BIGINT, total NUMERIC, placed_at TIMESTAMPTZ)
LANGUAGE sql STABLE AS $
  SELECT id, total, placed_at FROM orders
  WHERE customer_id = cust AND placed_at >= NOW() - (days || ' days')::INTERVAL
$;