Ich habe Probleme beim Entfernen von Datensätzen aus einer has_many-Zuordnung in Rails, ohne unnötige Abfragen auszulösen. Im Wesentlichen habe ich ein Modell, das eine has_many-Beziehung hat, und ich möchte basierend auf einigen Kriterien mehrere Datensätze daraus entfernen. Ich möchte in der Lage sein, gleichzeitig die Verbindung auf dem neuesten Stand zu halten, aber auch die Datensätze aus der Datenbank zu entfernen, und dazu nur eine DELETE-Abfrage zu benötigen. Ich habe versucht, der Beziehung mit den neuen Objekten zuzuweisen (was unnötige UPDATE-Abfragen generiert) und delete_all aufruft (wodurch eine Abfrage erstellt wird, die Verknüpfung jedoch nicht aktualisiert wird).Entfernen von Datensätzen aus has_many Rails-Zuordnung mit einer einzigen Abfrage
1
A
Antwort
0
Es gibt zwei Methoden zum Löschen von Datensätzen aus einer Beziehung. destroy
löscht alle zugehörigen Datensätze nacheinander, wobei die Rückrufe für jeden gelöschten Datensatz ausgeführt werden. delete_all
löscht alle Datensätze in einer Abfrage und führt die Rückrufe nicht aus.
in einem Modell So könnten Sie haben:
class Customer < ApplicationRecord
has_many :statements, dependent: :delete_all
und wenn Sie den Kunden löschen
pry(main) foo = Customer.first
pry(main)> foo.destroy
(0.3ms) BEGIN
SQL (290.4ms) DELETE FROM `statements` WHERE `statements`.`customer_id` = 3
SQL (2.6ms) DELETE FROM `customers` WHERE `customers`.`id` = 3
Alles in einem Seegang foop getan, keine Rückrufe auf die gelöscht.
oder -
class Customer < ApplicationRecord
has_many :statements, dependent: :destroy
und wenn Sie die Kunden löschen
pry(main) foo = Customer.first
pry(main)> foo.destroy
(0.4ms) BEGIN
Statement Load (25.0ms) SELECT `statements`.* FROM `statements` WHERE `statements`.`customer_id` = 4
SQL (0.5ms) DELETE FROM `statements` WHERE `statements`.`id` = 9023
SQL (0.3ms) DELETE FROM `statements` WHERE `statements`.`id` = 9024
SQL (0.3ms) DELETE FROM `statements` WHERE `statements`.`id` = 9025
. . . etc etc etc . . .
Jede abhängige Aufzeichnung eines nach dem anderen gelöscht, laufen Rückrufe auf jedem gelöscht.
Und delete_all
und destroy
kann auf jedem Ergebnissatz mit ähnlichen Auswirkungen ausgeführt werden. Also, wenn Sie wollte etwas Filter auf die zugehörigen Datensätze haben:
pry(main) foo = Customer.first
pry(main)> bar = foo.statements.where(some_param: 42)
pry(main)> bar.delete_all
SQL (4.2ms) DELETE FROM `statements` WHERE `statements`.`customer_id` = 7 AND `notices`.`some_param` = 42
=> 2
oder -
pry(main) foo = Customer.first
pry(main)> bar = foo.statements.where(some_param: 42)
pry(main)> bar.destroy_all
(0.2ms) BEGIN
SQL (0.6ms) DELETE FROM `notices` WHERE `notices`.`id` = 4639
(0.5ms) COMMIT
(0.2ms) BEGIN
SQL (0.5ms) DELETE FROM `notices` WHERE `notices`.`id` = 4640
(0.4ms) COMMIT
(0.1ms) BEGIN
SQL (0.5ms) DELETE FROM `notices` WHERE `notices`.`id` = 4641
(0.5ms) COMMIT
. . . etc etc etc . . .
Verwandte Themen
- 1. Entfernen Sie mehrere Dokumente aus Mongo in einer einzigen Abfrage
- 2. select count und anderen Datensätzen in einer einzigen Abfrage
- 3. Abfrage von ähnlichen, aber nicht zusammenhängenden Datensätzen in einer einzigen SQL-Abfrage
- 4. R: Entfernen von Zeiträumen aus Datensätzen
- 5. Entfernen von doppelten Datensätzen
- 6. Entfernen von doppelten Zeilen aus einer Tabelle in DB2 in einer einzigen Abfrage
- 7. Löschen mehrerer Zeilen mit einer einzigen Abfrage
- 8. mehr View-Tabellen aus einer einzigen Abfrage
- 9. Erhalten Sie alle Datensätze in einer has_many durch Beziehung aus einer Sammlung von Datensätzen
- 10. Wie mehrere Zeilen aus einer einzigen Abfrage mit beredten/fließend
- 11. Löschen und Aktualisieren von Operationen aus einer einzigen Abfrage
- 12. in einer einzigen Abfrage
- 13. Aktuelles Objekt aus has_many ausschließen_zu Abfrage
- 14. Ausschließen von in einer Abfrage vorhandenen Datensätzen
- 15. Entfernen Sie zusätzliches Delimeter aus den Datensätzen
- 16. Zum Löschen von Datensätzen mit Abfrage
- 17. Werte aus zwei separaten Datensätzen in einem einzigen Datensatz abgleichen
- 18. Ergebnisse entfernen aus einer Linq-Abfrage
- 19. Mehrere Zeilen mit einer einzigen Abfrage einfügen
- 20. Join 3 Tabellen mit einer einzigen Abfrage
- 21. Abrufen von ALTERNATE-Datensätzen aus einer Tabelle.
- 22. effizienteste Weg has_many Beziehungen eines Arrays von Datensätzen
- 23. Entfernen Sie einige Zeichen aus Datensätzen mit SQL
- 24. Abfrage-Filterung mit Rails has_many durch
- 25. Recreating diese benutzerdefinierte Abfrage has_many mit
- 26. Fill Grid mit einer einzigen Spalte von linq Abfrage
- 27. Daten aus mehreren Datensätzen in einem einzigen Feld
- 28. SSRS - Mehrere Parameter aus verschiedenen Datensätzen in einem einzigen Bericht
- 29. wie aus dem geburtsdatum in einer einzigen sql abfrage
- 30. Refactoring for-Schleife Linq Abfrage in einer einzigen Abfrage
Rails müssen jedes Objekt suchen Sie löschen möchten die Rückrufe ('before_' laufen und' after_' destroy) auf jedem. Wenn Sie diesen Prozess, der ein rutschiger Hang ist, überspringen möchten, möchten Sie möglicherweise ein Serviceobjekt erstellen, das alle Logik über "alle verwandten Objekte löschen" enthält und die Zuordnung zurücksetzen – MrYoshiji
Ich denke, das Zurücksetzen der Zuordnung ist auch nicht optimal, Denn wenn später auf die Assoziation zugegriffen wird, müssen die Objekte erneut abgerufen werden, obwohl wir wissen, was in der Relation sein sollte. – mp94
IMO, sollten Sie nicht versuchen, die SQL-Abfragen zu reduzieren und das Verhalten von Rails neu zu definieren. Es kann zu verschiedenen Problemen führen, die auf den ersten Blick nicht sichtbar sind, aber viel später, wenn die ganze App sie seit Monaten benutzt ... – MrYoshiji