Полагаю, вы могли смешать команду SQL BEGIN
(расширение Postgresql) и блок PL / pgSQL .Команда SQL DO
выполняет блок анонимного кода, как если бы это была анонимная функция без параметров и возвращающая void
.Другими словами, в
DO $$
BEGIN
...
END;
$$;
пара BEGIN
/ END;
обозначает блок кода, а не транзакцию.Стоит отметить, что начиная с Postgresql версии 11 можно управлять транзакциями в DO
блоке , учитывая, что он не выполняется в блоке транзакций , но команды дляэто COMMIT
и ROLLBACK
, а не ключевое слово END
.
Проблема в том, что ваши изменения не зафиксированы, хотя ваши команды явно выполняются - что подтверждается ошибкой, если она не запущенас подходящими привилегиями.Эта проблема вызвана , как работает функция автоматической фиксации SQLAlchemy .Короче говоря, он проверяет ваш оператор / команду и пытается определить, является ли это операцией изменения данных или оператором DDL.Это работает для основных операций, таких как INSERT
, DELETE
, UPDATE
и т. П., Но не идеально.Фактически, невозможно всегда правильно определить, изменяет ли оператор данные;например SELECT my_mutating_procedure()
это такое утверждение.Так что нужна помощь, если делать более сложные операции.Один из способов - указать механизму автоматической фиксации, что он должен выполнить фиксацию, заключив строку SQL в конструкцию text()
и , используя execution_options()
:
engine.execute(text("SELECT my_mutating_procedure()").
execution_options(autocommit=True))
Также возможно явно указать SQLAlchemy, что команда является литеральным оператором DDL, используя конструкцию DDL
:
from sqlalchemy.schema import DDL
def execute_sql_file(engine, path):
try:
with open(path) as file:
stmt = file.read()
# Not strictly DDL, but a series of DO commands that execute DDL
ddl_stmt = DDL(stmt)
engine.execute(ddl_stmt)
except ProgrammingError:
raise MyCustomError
except FileNotFoundError:
raise MyCustomError
Что касается того, почему она работает с pgAdmin, вероятно, по умолчаниюфиксирует, если не было ошибок.