2013-01-17 13 views
9

Potrzebuję wstawić/zaktualizować zbiorcze wiersze za pośrednictwem SQLAlchemy. I wstawiaj wstawione wiersze.SQLAlchemy: zapobiec automatycznemu zamykaniu

Próbowałem to zrobić z session.execute:

>>> posts = db.session.execute(Post.__table__.insert(), [{'title': 'dfghdfg', 'content': 'sdfgsdf', 'topic': topic}]*2) 
>>> posts.fetchall() 

ResourceClosedError      Traceback (most recent call last) 

I z silnikiem:

In [17]: conn = db.engine.connect() 

In [18]: result = conn.execute(Post.__table__.insert(), [{'title': 'title', 'content': 'content', 'topic': topic}]*2) 

In [19]: print result.fetchall() 
ResourceClosedError: This result object does not return rows. It has been closed automatically. 

Taka sama reakcja jest obiekt został zamknięty automatycznie. Jak temu zapobiec?

Odpowiedz

8

Pierwsza odpowiedź - w sprawie "zapobiegania automatycznemu zamykaniu".

SQLAlchemy uruchamia polecenie DBAPI execute() lub executemany() z insertem i nie wykonuje żadnych wybranych zapytań. Tak więc wyjątek stanowi oczekiwane zachowanie. Obiekt ResultProxy zwrócony po wykonaniu kwerendy wstawiania zawija kursor DB-API, który nie pozwala na wykonanie na nim .fetchall(). Po niepowodzeniu metody .fetchall() funkcja ResultProxy zwraca użytkownikowi wyjątek dla piły.

Jedyne informacje, które można uzyskać po operacji wstawiania/aktualizacji/usuwania, to liczba dotkniętych wierszy lub wartość klucza podstawowego po automatycznym zwiększeniu (w zależności od sterownika bazy danych i bazy danych).

Jeśli twoim celem jest, aby otrzymać ten rodzaj informacji, należy rozważyć sprawdzenie ResultProxy methods and attributes jak:

  • .inserted_primary_key
  • .last_inserted_params()
  • .lastrowid
  • itp

Druga odpowiedź - "jak zrobić luzem wstawić/zaktualizować i uzyskać wynik ng wierszy ".

Nie ma możliwości załadowania wstawionych wierszy podczas wykonywania kwerendy z pojedynczym wstawieniem przy użyciu DBAPI. Interfejs API SQLAlchemy SQL Expression, którego używasz do robienia wstawiania/aktualizowania zbiorczego, również nie zapewnia takiej funkcjonalności. SQLAlchemy uruchamia wywołanie DBAPI executemany() i polega na implementacji sterownika. Aby uzyskać szczegółowe informacje, patrz this section of documentation.

Rozwiązaniem byłoby zaprojektowanie twojej tabeli w taki sposób, aby każdy rekord miał naturalny klucz do identyfikacji rekordów (kombinacja wartości kolumn, które identyfikują rekord w unikalny sposób). Tak więc kwerendy wstawiania/aktualizowania/wybierania mogą być ukierunkowane na jeden rekord. Po wykonaniu tej czynności możliwe będzie najpierw masowe wstawianie/aktualizowanie, a następnie wykonywanie zapytania według klucza. W związku z tym nie trzeba znać wartości klucza podstawowego, która jest automatycznie zwiększana.

Inna opcja: możesz użyć SQLAlchemy Object Relational API do tworzenia obiektów - wtedy SQLAlchemy może spróbować zoptymalizować wstawkę, aby wykonać jedno zapytanie z executemany. To działało dla mnie podczas korzystania z Oracle DB. Nie będzie żadnej optymalizacji dla aktualizacji po wyjęciu z pudełka. Sprawdź this SO question, aby uzyskać skuteczne pomysły dotyczące aktualizacji zbiorczej.

+2

Dzięki, zainspirowałeś mnie. – I159

Powiązane problemy