Vấn đề ở đây là cách sqlalchemy quyết định đưa ra một cam kết sau mỗi câu lệnh.
nếu một văn bản được chuyển tới engine.execute
, sqlalchemy sẽ cố gắng xác định xem văn bản là DML hay DDL bằng cách sử dụng regex sau đây. Bạn có thể tìm thấy nó trong các nguồn ở đây
AUTOCOMMIT_REGEXP = re.compile(
r"\s*(?:UPDATE|INSERT|CREATE|DELETE|DROP|ALTER)", re.I | re.UNICODE
)
Điều này chỉ phát hiện các từ nếu chúng ở đầu văn bản, bỏ qua bất kỳ khoảng trắng nào ở đầu. Vì vậy, trong khi lần thử đầu tiên của bạn # works fine
, ví dụ thứ hai không nhận ra rằng một cam kết cần được phát hành sau khi câu lệnh được thực thi vì từ đầu tiên là SET
.
Thay vào đó, sqlalchemy đưa ra một bản khôi phục, vì vậy nó # appears to succeed/does NOT throw any error
.
giải pháp đơn giản nhất là cam kết thủ công.
ví dụ:
engine.execute("SET ROLE read_write; CREATE table testpublic (id int, val text); COMMIT;")
hoặc bọc sql trong text
và đặt autocommit=True
, như được hiển thị trong tài liệu
stmt = text('set role read_write; create table testpublic (id int, val text);').execution_options(autocommit=True)
e.execute(stmt)