Porting T-SQL to PL/pgSQL — Migrating Procedures and Functions

The data is over, the schema stands — and then there are 200 stored procedures sitting there that no tool translates for you. pgloader migrates tables and data, but the logic in procedures, functions, and triggers stays behind. This is the phase that’s actually work: porting T-SQL to PL/pgSQL, line by line, with understanding instead of search-and-replace. The … Read more

PL/pgSQL Table-Returning Functions — RETURNS TABLE, SETOF and When a View Is Better

A view is the most elegant way to encapsulate a recurring query — right up to the moment the query needs an argument from outside. A view has no parameters. As soon as a value belongs in the WHERE that the caller supplies, the table-valued function is the tool of choice: a function that returns an entire result set … Read more

PL/pgSQL Function Conventions — Volatility, RETURNS and the Boundary to Procedures

A PL/pgSQL function without a volatility marker is VOLATILE by default. That sounds harmless but has a real cost: the planner calls the function again for every row, never pre-computes it once, and excludes it from every functional index. The damage is invisible — until the same query suddenly takes seconds instead of milliseconds. Good PL/pgSQL function conventions start … Read more

Deriving SQL Conventions with Claude Code — the Generate-Refine-Derive Loop

An AI writes you a stored procedure in seconds. It compiles, it runs – and it looks like a stranger wrote it. The next artifact looks different again. Generated SQL is technically correct but stylistically arbitrary – and without an enforced convention, a generated collection drifts apart just like one five developers write by hand. The obvious … Read more

SQL Conventions // PL/pgSQL Procedures You Can Still Read in Two Years

If you write a stored procedure, you write it for someone who doesn’t know it — usually for yourself, 18 months later, at 11 p.m., while an ETL run is stuck. Readability isn’t cosmetics, it’s debugging time. PostgreSQL forces almost nothing on you: names are free, indentation doesn’t matter, a RAISE EXCEPTION swallows any string you assemble inline. That’s exactly … Read more