Theo như tôi biết, không có cách nào để ORM phát hành số lượng chèn hàng loạt. Tôi tin rằng lý do cơ bản là SQLAlchemy cần theo dõi danh tính của từng đối tượng (tức là các khóa chính mới) và việc chèn hàng loạt can thiệp vào điều đó. Ví dụ: giả sử foo
bảng của bạn chứa một id
cột và được ánh xạ tới một Foo
lớp:
x = Foo(bar=1)
print x.id
# None
session.add(x)
session.flush()
# BEGIN
# INSERT INTO foo (bar) VALUES(1)
# COMMIT
print x.id
# 1
Vì SQLAlchemy chọn giá trị cho x.id
mà không đưa ra một truy vấn khác, chúng ta có thể suy ra rằng nó nhận giá trị trực tiếp từ INSERT
câu lệnh. Nếu bạn không cần quyền truy cập tiếp theo vào các đối tượng đã tạo thông qua các phiên bản giống nhau , bạn có thể bỏ qua lớp ORM cho phần chèn của mình:
Foo.__table__.insert().execute([{'bar': 1}, {'bar': 2}, {'bar': 3}])
# INSERT INTO foo (bar) VALUES ((1,), (2,), (3,))
SQLAlchemy không thể đối sánh các hàng mới này với bất kỳ đối tượng hiện có nào, vì vậy bạn sẽ phải truy vấn lại chúng cho bất kỳ hoạt động tiếp theo nào.
Đối với dữ liệu cũ có liên quan, sẽ rất hữu ích khi nhớ rằng phiên không có cách tích hợp nào để biết khi nào cơ sở dữ liệu được thay đổi bên ngoài phiên. Để truy cập dữ liệu được sửa đổi bên ngoài thông qua các phiên bản hiện có, các phiên bản phải được đánh dấu là đã hết hạn . Điều này xảy ra theo mặc định trên session.commit()
, nhưng có thể được thực hiện thủ công bằng cách gọi session.expire_all()
hoặc session.expire(instance)
. Một ví dụ (SQL bị bỏ qua):
x = Foo(bar=1)
session.add(x)
session.commit()
print x.bar
# 1
foo.update().execute(bar=42)
print x.bar
# 1
session.expire(x)
print x.bar
# 42
session.commit()
hết hạn x
, vì vậy câu lệnh in đầu tiên mặc nhiên mở một giao dịch mới và x
các thuộc tính của truy vấn lại . Nếu bạn nhận xét ra câu lệnh in đầu tiên, bạn sẽ nhận thấy rằng câu lệnh thứ hai bây giờ chọn giá trị chính xác, vì truy vấn mới không được phát cho đến sau khi cập nhật.
Điều này có ý nghĩa theo quan điểm của cách ly giao dịch - bạn chỉ nên chọn các sửa đổi bên ngoài giữa các giao dịch. Nếu điều này khiến bạn gặp rắc rối, tôi khuyên bạn nên làm rõ hoặc suy nghĩ lại ranh giới giao dịch của ứng dụng của bạn thay vì ngay lập tức tiếp cận session.expire_all()
.