Working with Stored Procedures

1. Creating Stored Procedures

DBSyntax
Postgres 11+CREATE PROCEDURE name(...) LANGUAGE plpgsql AS $$ ... $$;
MySQLCREATE PROCEDURE name(...) BEGIN ... END;
SQL ServerCREATE PROCEDURE name AS BEGIN ... END;
OracleCREATE PROCEDURE name IS BEGIN ... END;
Difference vs FunctionProcedures can issue COMMIT/ROLLBACK; functions usually cannot

2. Defining Procedure Parameters

ModeDirection
INInput (default)
OUTOutput only
INOUTBoth in and out
DEFAULT valueOptional argument
VARIADICVariable-length args (PG)

3. Using Variables in Procedures

Example: PL/pgSQL Variables

CREATE PROCEDURE transfer(p_from BIGINT, p_to BIGINT, p_amt NUMERIC)
LANGUAGE plpgsql AS $
DECLARE
  v_balance NUMERIC;
BEGIN
  SELECT balance INTO v_balance FROM accounts WHERE id = p_from FOR UPDATE;
  IF v_balance < p_amt THEN
    RAISE EXCEPTION 'insufficient funds';
  END IF;
  UPDATE accounts SET balance = balance - p_amt WHERE id = p_from;
  UPDATE accounts SET balance = balance + p_amt WHERE id = p_to;
END;
$;
DeclarationExample
Scalarv_count INTEGER := 0;
Row typev_row orders%ROWTYPE;
CursorDECLARE cur CURSOR FOR SELECT ...;

4. Implementing Control Flow

ConstructSyntax
IFIF cond THEN ... ELSIF ... ELSE ... END IF;
CASECASE x WHEN ... THEN ... END CASE;
LOOP / EXITInfinite loop with explicit exit
WHILE / FORConditional and counted loops
CONTINUESkip to next iteration

5. Handling Errors in Procedures

MechanismDetail
RAISE EXCEPTIONThrow error with message + SQLSTATE
EXCEPTION block (PG)BEGIN ... EXCEPTION WHEN ... THEN ... END;
DECLARE HANDLER (MySQL)DECLARE EXIT HANDLER FOR SQLSTATE '...' ...
SQLCODE / SQLERRMInspect current error

6. Executing Stored Procedures

DBCall
PostgresCALL transfer(1, 2, 100);
MySQLCALL transfer(1, 2, 100);
SQL ServerEXEC transfer @from=1, @to=2, @amt=100;
OracleBEGIN transfer(1,2,100); END; /

7. Returning Result Sets

DBMechanism
PostgresREFCURSOR OUT param, or use functions returning SETOF
MySQLSELECT inside procedure returns to client
SQL ServerSELECT inside proc; OUTPUT params for scalars
OracleSYS_REFCURSOR OUT param

8. Using Dynamic SQL in Procedures

DBSyntax
PL/pgSQLEXECUTE 'SELECT ...' INTO var USING param;
MySQLPREPARE stmt FROM '...'; EXECUTE stmt USING @p; DEALLOCATE PREPARE stmt;
SQL Serversp_executesql N'...', N'@p INT', @p = 1;
OracleEXECUTE IMMEDIATE 'SELECT ...' INTO var USING param;
Warning: Always use parameter binding in dynamic SQL — string concatenation enables SQL injection.

9. Managing Procedure Security

ConceptDetail
SECURITY DEFINERRuns with creator's privileges
SECURITY INVOKER (default)Runs with caller's privileges
GRANT EXECUTEAllow role to call
search_path (PG)SET inside DEFINER procs to prevent hijacking

10. Optimizing Procedure Performance

TipDetail
Avoid row-by-row loopsUse set-based SQL
Prepared plansReuses parsed plan
Bulk bindingOracle FORALL, PG arrays
ProfileUse EXPLAIN ANALYZE on internal queries
Watch parameter sniffingSQL Server: use OPTION (RECOMPILE) or local vars