Как исправить ошибку DEFAULT для expires_at в PostgreSQL

    При создании таблицы verification в PostgreSQL разработчики часто сталкиваются с ошибкой: cannot use column reference in DEFAULT expression. Это происходит, когда в качестве значения по умолчанию пытаются использовать ссылку на другую колонку (created_at) или функцию, зависящую от времени создания строки. В этой статье объясняем, почему так происходит и как правильно настроить автоматическое вычисление expires_at.

    Причина ошибки column reference в DEFAULT

    В PostgreSQL выражение DEFAULT не может ссылаться на другие столбцы той же таблицы. Запрос DEFAULT dateadd(day, 7, getdate()) некорректен, так как getdate() не является стандартной функцией PostgreSQL, а dateadd отсутствует. Вместо этого нужно использовать NOW() или CURRENT_TIMESTAMP и прибавлять интервал.

    Правильный синтаксис DEFAULT для expires_at

    Чтобы expires_at автоматически устанавливался на 7 дней позже created_at, используйте выражение:

    CREATE TABLE verification (
        id serial PRIMARY KEY NOT NULL,
        user_id text NOT NULL,
        identifier text NOT NULL,
        value boolean DEFAULT false,
        expires_at timestamp DEFAULT (NOW() + INTERVAL '7 days') NOT NULL,
        created_at timestamp DEFAULT NOW() NOT NULL,
        updated_at timestamp DEFAULT NOW() NOT NULL
    );

    Здесь NOW() + INTERVAL '7 days' - корректное значение по умолчанию, которое не ссылается на другие колонки.

    Альтернатива: триггер для гибкости

    Если нужно, чтобы expires_at зависел именно от created_at (например, при ручной вставке), используйте триггер:

    CREATE OR REPLACE FUNCTION set_expires_at()
    RETURNS TRIGGER AS $$
    BEGIN
        NEW.expires_at := NEW.created_at + INTERVAL '7 days';
        RETURN NEW;
    END;
    $$ LANGUAGE plpgsql;
    
    CREATE TRIGGER trg_set_expires_at
    BEFORE INSERT ON verification
    FOR EACH ROW EXECUTE FUNCTION set_expires_at();

    Этот подход гарантирует, что expires_at всегда будет на 7 дней позже created_at, даже если created_at передан явно.

    Распространённые ошибки при DEFAULT в PostgreSQL

    • Использование GETDATE() - функция из SQL Server, в PostgreSQL замените на NOW() или CURRENT_TIMESTAMP.
    • DATEADD - не существует в PostgreSQL; используйте INTERVAL.
    • Ссылка на колонку в DEFAULT - недопустима, применяйте триггеры или вычисляйте значение на стороне приложения.

    Заключение

    Ошибка cannot use column reference in DEFAULT expression решается заменой некорректных функций на NOW() + INTERVAL или использованием триггера. Теперь ваша таблица verification будет создаваться без ошибок, а expires_at - автоматически получать значение через 7 дней.

    Часто задаваемые вопросы