Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Richtiges Aktualisieren einer Query (https://www.delphipraxis.net/198677-richtiges-aktualisieren-einer-query.html)

mariusbenz 23. Nov 2018 07:23

Datenbank: Advantage Database, SQL-Server • Version: ? • Zugriff über: UNIDAC

Richtiges Aktualisieren einer Query
 
Guten Morgen,

folgende Situation: TDBGrid mit TDataSource mit TUniQuery als Dataset.
Wie aktualisiert man jetzt zuverlässig die Datenmenge?

Eigentlich ja mit "Query.Refresh". Allerdings hat mein Kollege den (evtl. Irr-)Glauben, dass das nicht immer funktioniert, was wir aber noch nicht nachstellen konnten.

Laut Delphi-Hilfe ist das auch berechtigt:
Anmerkung: Die Methode Refresh funktioniert nicht bei allen von TDataSet abgeleiteten Klassen. Insbesondere TQuery-Komponenten unterstützen Refresh nicht, wenn die Abfrage nicht "live" ist. Um ein statisches TQuery-Objekt zu aktualisieren, schließen und öffnen Sie die Datenmenge.

Was ist der Unterschied zwischen "live" und "statisch" in diesem Fall?
Ein Close und Open der Query hat natürlich zur Folge, dass z.B. AfterOpens der Query ausgeführt werden, das Grid neugezeichnet wird, man die letzte ausgewählte Zeile erneut suchen muss, etc.

hoika 23. Nov 2018 07:48

AW: Richtiges Aktualisieren einer Query
 
Hallo,
Open/Close ist meine erste Wahl.
Es kann sich ja zwischenzeitlich etwas geändert haben.
Das Refresh kommt noch aus der guten alten TTable-Zeit.

Zitat:

Ein Close und Open der Query hat natürlich zur Folge, dass z.B. AfterOpens der Query ausgeführt werden, das Grid neugezeichnet wird, man die letzte ausgewählte Zeile erneut suchen muss, etc.
Das lasse ich nicht gelten, weil ich keine datensensitiven Elemente (z.B. TDBGrid) benutze.
Was benutzt du denn?

Uwe Raabe 23. Nov 2018 08:13

AW: Richtiges Aktualisieren einer Query
 
Zitat:

Zitat von hoika (Beitrag 1418878)
Zitat:

Ein Close und Open der Query hat natürlich zur Folge, dass z.B. AfterOpens der Query ausgeführt werden, das Grid neugezeichnet wird, man die letzte ausgewählte Zeile erneut suchen muss, etc.
Das lasse ich nicht gelten, weil ich keine datensensitiven Elemente (z.B. TDBGrid) benutze.

Die Notwendigkeit, auf den zuletzt aktiven Datensatz zu positionieren ist erstmal unabhängig vom Einsatz datensensitiver Controls. Für das Argument mit AfterOpen gilt sinngemäß dasselbe.

mariusbenz 23. Nov 2018 08:15

AW: Richtiges Aktualisieren einer Query
 
Zitat:

Zitat von hoika (Beitrag 1418878)
Hallo,
Open/Close ist meine erste Wahl.
Es kann sich ja zwischenzeitlich etwas geändert haben.

Um das zu testen haben wir uns eine aktuelle Datenmenge anzeigen lassen, dann in der Datenbank Werte geändert (sodass sich nur bestimmte Werte ändern oder durch Filterung Zeilen dazukommen/verschwinden), und schließlich mit einem einfachen Refresh aktualisiert -> alle Änderungen wurden im Grid angezeigt.

Lemmy 23. Nov 2018 08:32

AW: Richtiges Aktualisieren einer Query
 
Zitat:

Zitat von mariusbenz (Beitrag 1418881)
Um das zu testen haben wir uns eine aktuelle Datenmenge anzeigen lassen, dann in der Datenbank Werte geändert (sodass sich nur bestimmte Werte ändern oder durch Filterung Zeilen dazukommen/verschwinden), und schließlich mit einem einfachen Refresh aktualisiert -> alle Änderungen wurden im Grid angezeigt.


dann ist doch gut, wenn es bei Dir funktioniert.

gestern habe ich mit pgDac gespielt (Devart Komponenten für PostgreSQL) - da hat ein Refresh nicht funktioniert. und bei IBObjects mach ich inzwischen einen großen Bogen sowohl um Refresh als auch um locate.

Interessant wäre jetzt wie TUniQuery das Refrehs umsetzt - vielleicht macht das intern einen Open-Close mit Positionierung auf den letzt gewählten Datensatz (falls möglich)... Schon mal in den Source rein geschaut?

mariusbenz 23. Nov 2018 09:05

AW: Richtiges Aktualisieren einer Query
 
Zitat:

Zitat von Lemmy (Beitrag 1418882)
Interessant wäre jetzt wie TUniQuery das Refrehs umsetzt - vielleicht macht das intern einen Open-Close mit Positionierung auf den letzt gewählten Datensatz (falls möglich)... Schon mal in den Source rein geschaut?

Delphi-Quellcode:
procedure TDataSet.Refresh;
begin
  DoBeforeRefresh;
  CheckBrowseMode;
  UpdateCursorPos;
  try
    InternalRefresh;
  finally
    Resync([]);
    DoAfterRefresh;
  end;
end;
Hab mal drübergschaut, die Aktualisierung der Daten passiert im InternalRefresh. Ein Strg+Klick führt mich da in eine leere Prozedur, über F7 beim debuggen verliert es sich dann irgendwann in ASM

mariusbenz 23. Nov 2018 09:08

AW: Richtiges Aktualisieren einer Query
 
Zitat:

Zitat von mariusbenz (Beitrag 1418876)
Laut Delphi-Hilfe ist das auch berechtigt:
Anmerkung: Die Methode Refresh funktioniert nicht bei allen von TDataSet abgeleiteten Klassen. Insbesondere TQuery-Komponenten unterstützen Refresh nicht, wenn die Abfrage nicht "live" ist. Um ein statisches TQuery-Objekt zu aktualisieren, schließen und öffnen Sie die Datenmenge.

Was ist der Unterschied zwischen "live" und "statisch" in diesem Fall?

Weiß jemand was das genau bedeutet? Hat das evtl. damit zu tun, wie das SQL-Statement aufgebaut ist?

Schokohase 23. Nov 2018 09:09

AW: Richtiges Aktualisieren einer Query
 
Zitat:

Zitat von mariusbenz (Beitrag 1418889)
Hab mal drübergschaut, die Aktualisierung der Daten passiert im InternalRefresh. Ein Strg+Klick führt mich da in eine leere Prozedur, über F7 beim debuggen verliert es sich dann irgendwann in ASM

Natürlich, denn das ist eine virtuelle Methode die dann von Nachfolgern wie z.B.
Delphi-Quellcode:
TUniQuery
überschrieben werden kann. Man muss also dort nachschauen und nicht bei
Delphi-Quellcode:
TDataSet
.

RSF 23. Nov 2018 09:37

AW: Richtiges Aktualisieren einer Query
 
Zitat:

Zitat von mariusbenz (Beitrag 1418890)
Zitat:

Zitat von mariusbenz (Beitrag 1418876)
Laut Delphi-Hilfe ist das auch berechtigt:
Anmerkung: Die Methode Refresh funktioniert nicht bei allen von TDataSet abgeleiteten Klassen. Insbesondere TQuery-Komponenten unterstützen Refresh nicht, wenn die Abfrage nicht "live" ist. Um ein statisches TQuery-Objekt zu aktualisieren, schließen und öffnen Sie die Datenmenge.

Was ist der Unterschied zwischen "live" und "statisch" in diesem Fall?

Weiß jemand was das genau bedeutet? Hat das evtl. damit zu tun, wie das SQL-Statement aufgebaut ist?

Live: Die Datenmenge kann bearbeitet werden. Normale SQL-Abfrage
Statisch: Die Datenmenge kann nicht bearbeitet werden. z.B. wenn einer Abfrage aus Felder mehreren Tabellen zusammen gesetzt ist.

mariusbenz 23. Nov 2018 09:43

AW: Richtiges Aktualisieren einer Query
 
Zitat:

Zitat von RSF (Beitrag 1418898)
Zitat:

Zitat von mariusbenz (Beitrag 1418890)
Zitat:

Zitat von mariusbenz (Beitrag 1418876)
Laut Delphi-Hilfe ist das auch berechtigt:
Anmerkung: Die Methode Refresh funktioniert nicht bei allen von TDataSet abgeleiteten Klassen. Insbesondere TQuery-Komponenten unterstützen Refresh nicht, wenn die Abfrage nicht "live" ist. Um ein statisches TQuery-Objekt zu aktualisieren, schließen und öffnen Sie die Datenmenge.

Was ist der Unterschied zwischen "live" und "statisch" in diesem Fall?

Weiß jemand was das genau bedeutet? Hat das evtl. damit zu tun, wie das SQL-Statement aufgebaut ist?

Live: Die Datenmenge kann bearbeitet werden. Normale SQL-Abfrage
Statisch: Die Datenmenge kann nicht bearbeitet werden. z.B. wenn einer Abfrage aus Felder mehreren Tabellen zusammen gesetzt ist.

Kann man bei statischen Querys dann auch kein Query.Edit und Query.Post durchführen?
Weil bei der Query habe ich zwei LEFT JOINS drin, also müsste es ja eine statische Query sein (?), dennoch funktionieren Refresh, Edit und Post dabei.

RSF 23. Nov 2018 10:03

AW: Richtiges Aktualisieren einer Query
 
siehe http://devzone.advantagedatabase.com...1.1/index.html

Zitat:

A live cursor is constructed by essentially putting a filter on the base table so that only the requested rows are visible. Conversely, a static cursor is actually a new table dynamically built with the requested rows of the original table or tables. Because the live cursor does not move any records around, it is faster to retrieve as a rowset. However, a static cursor is not completely populated when it is created.

A form of "caching" is used to add a certain number of rows at a time to the static cursor, so that control is returned to client in a reasonable time. The static cursor is populated as the rowset is traversed. This results in a more immediate response to the query, and processing is not wasted if only the first portion of the rowset is traversed. Note that the following operations will cause the static cursor rowset to be fully populated: Last (or Go Bottom), RecCount, Create Index.

For either live or static cursors, a cursor handle is utilized in a manner analogous to a table handle. This cursor handle can be used to navigate the resulting cursor in a fully scrollable manner. For all intents and purposes, the cursor can be treated like a table. Static cursors cannot be modified, but modifications on live cursors are reflected in the source table.

A live cursor can be much faster than a static cursor. However, this performance difference has a trade-off against features that can only be used on a static cursor. A live cursor is used if the SELECT statement does not contain any of the following:
• • DISTINCT in the SELECT clause
• • Joins (inner, outer, self, or UNION)
• • Any aggregate function
• • GROUP BY or HAVING clauses
• • Subqueries
• • Certain scalar functions (see Scalar Functions in a WHERE Clause)
• • If a memo field is used in a WHERE clause (e.g., WHERE memo is null)
• • LIKE operator is used in a WHERE clause (e.g.,. WHERE lastname LIKE 'Smith%)
• • Expressions or scalar functions in the select list (e.g., select UCASE(lastname) … )
• • TOP in the SELECT clause
• • WHERE clause contains a large expression that is not supported by the expression engine

It is possible to force Advantage to produce a static cursor on a SELECT statement that would normally result in a live cursor. To do this, use the {static} escape sequence after the SELECT keyword. For example:



SELECT {static} * FROM emp WHERE hire_date < '1990-01-14'



Without the escape sequence, Advantage would create a live cursor for that query. With {static} specified, though, Advantage will create a static cursor. From a performance standpoint, it is probably better in most circumstances to allow Advantage to create live cursors when possible.

If, though, the WHERE clause is very restrictive (thus producing a small rowset) and the base table is very large, it may be faster to force a static cursor. This is because the live cursor would be implemented with a filter on the server. If the client application were to traverse the rowset multiple times, the server would have to filter the rowset each time. If the client forced the cursor to be static, however, the server may be able to quickly seek directly to the data for the rowset with minimal cost. And once the cursor is created, the server would not be required to do any filtering when the client traversed the rowset.



Alle Zeitangaben in WEZ +1. Es ist jetzt 07:01 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz