Declares a variable with type, optional NOT NULL, CONSTANT, DEFAULT, and COLLATION.
DECLARE
<name> [CONSTANT] <type> [NOT NULL] [DEFAULT <expr>] [COLLATE '<collation>'];
## Overview Variable declarations in the DECLARE section define typed, scoped variables for use within a PL/pgSQL block. Each variable has a name, a data type, and optional modifiers (CONSTANT, NOT NULL, DEFAULT, COLLATE). ## Behavior - Declarations are processed in order during block entry. Default expressions are evaluated sequentially, so later declarations can reference earlier ones. - Variables without a DEFAULT are initialized to NULL. If NOT NULL is specified without a DEFAULT, the first assignment must provide a non-NULL value before the variable is read. - CONSTANT variables are assigned once (from the DEFAULT expression) and cannot be reassigned. Attempting to assign to a CONSTANT raises a runtime error. - Data types map to Arrow/DataFusion types internally: INT to Int32, BIGINT to Int64, TEXT to Utf8, NUMERIC to Decimal128, BOOLEAN to Boolean, DATE to Date32, TIMESTAMP to TimestampMicrosecond, and arrays to List types. - RECORD variables are declared without a fixed schema. Their fields are populated dynamically when assigned from query results or explicit field assignments. - The COLLATE clause is parsed and stored but does not currently affect string comparison behavior in the DataFusion execution engine. - Variables are block-scoped. They are created when the block's DECLARE is processed and destroyed when the block exits (scope pop). ## Differences from PostgreSQL - `%TYPE` and `%ROWTYPE` are supported for type inference from table columns (e.g., `v_name table.column%TYPE`, `v_row schema.table%ROWTYPE`). - COLLATE is parsed but has no runtime effect. All string comparisons use the default DataFusion collation. - RECORD variables in DeltaForge use an IndexMap for field ordering, which preserves insertion order. Field access is by name (dot notation), consistent with PostgreSQL.
| Name | Type | Description |
|---|---|---|
name | Assign a unique identifier for the variable within its block scope. | |
data_type | Specify the data type (INT, BIGINT, TEXT, NUMERIC, BOOLEAN, DATE, TIMESTAMP, arrays, RECORD, etc.). | |
not_null | Enforce a NOT NULL constraint. Assignment of NULL to this variable raises a runtime error. | |
constant | Mark the variable as read-only after its initial value is set. Subsequent assignments raise an error. | |
default | Set the initial value. Use DEFAULT or := syntax. Without a default, the variable is initialized to NULL. |
DO $$
DECLARE
counter INT := 0;
BEGIN
counter := counter + 1;
PRINT counter;
END;
$$;
DO $$
DECLARE
user_name TEXT NOT NULL DEFAULT 'unknown';
PI CONSTANT NUMERIC := 3.14159;
BEGIN
PRINT user_name;
PRINT PI;
END;
$$;
DO $$
DECLARE
start_ts TIMESTAMP := now();
batch_id BIGINT;
is_active BOOLEAN := true;
tags TEXT[] := ARRAY['etl', 'daily'];
BEGIN
PRINT 'Started at:', start_ts;
PRINT 'Active:', is_active;
FOREACH tag IN ARRAY tags LOOP
PRINT tag;
END LOOP;
END;
$$;
DO $$
DECLARE
rec RECORD;
row_count INT;
BEGIN
FOR rec IN SELECT id, name FROM employees LIMIT 5 LOOP
PRINT rec.id, rec.name;
END LOOP;
GET DIAGNOSTICS row_count = ROW_COUNT;
PRINT 'Processed', row_count, 'rows';
END;
$$;
DO $$
DECLARE
threshold CONSTANT INT := 100;
total INT := 0;
BEGIN
SELECT sum(amount) INTO total FROM orders;
IF total > threshold THEN
PRINT 'Threshold exceeded:', total;
END IF;
END;
$$;