Невозможно использовать объявленную переменную в DDL - PullRequest
0 голосов
/ 28 октября 2019

Пожалуйста, рассмотрите ниже простой код

DO $$
DECLARE
    _VARCHAR_SIZE int := 200;
BEGIN
    create table mytable(
        id int primary key,
        name varchar( _VARCHAR_SIZE )
    );
END $$;

При выполнении вышеуказанного кода я получаю ошибку

ERROR:  syntax error at or near "_VARCHAR_SIZE"
LINE 14:   name character varying(_VARCHAR_SIZE) NOT NULL,
                                  ^
SQL state: 42601
Character: 222

Почему postgres не распознает объявленную переменную в DDL

Iне хочу использовать EXECUTE, чтобы сделать весь оператор динамическим.

Ответы [ 3 ]

1 голос
/ 29 октября 2019

Если вы используете PSQL, попробуйте:

\set a 1

CREATE TABLE a (a varchar(:a));
1 голос
/ 29 октября 2019

Внутренне Postgres знает два типа команд - команды (CREATE, ALTER, DROP, ..) и запросы (SELECT, INSERT, UPDATE, DELETE). Каждая команда имеет специальную реализацию. Запросы реализуются вместе с шагами: разбор, анализ, оптимизация, выполнение. Существует высокая вероятность того, что запросы будут выполняться повторно. Команды обычно не выполняются больше раз. Затем запросы имеют специальную оптимизацию для повторного выполнения - параметризованный план. План представляет собой последовательность шагов выполнения запроса. Обычно это одно и то же, но параметры (переменные) разные - вы можете искать Павла или Томаса, вы можете вставить Павла или Томаса. Нет ничего похожего на команды.

Вы можете использовать переменные plpgsql везде, где возможно использование параметров плана. Присоединяйтесь к нему во время выполнения PlpgSQL. И вы не можете использовать переменные где-либо еще. Операторы DDL (у команд нет планов), и тогда вы не сможете использовать там переменные. Единственная альтернатива - это динамическая команда sql - EXECUTE в PLpgSQL.

0 голосов
/ 28 октября 2019

Вы не можете передать это как параметр запроса. Для этого вам нужен динамический SQL:

DO $$
DECLARE
    _VARCHAR_SIZE int := 200;
BEGIN
    EXECUTE format(
        'create table mytable(id int primary key, name varchar( %s ));',
        _VARCHAR_SIZE
    );
END $$;

Демонстрация по БД Fiddle

...