Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Locate oder SELECT / Wie Problem lösen? (https://www.delphipraxis.net/101056-locate-oder-select-wie-problem-loesen.html)

gullatrulla 7. Okt 2007 22:19

Datenbank: Firebird • Version: 2.01 • Zugriff über: FibPlus

Locate oder SELECT / Wie Problem lösen?
 
Hallo zusammen

Es würde mich wirklich interessieren, wie ein Firebird-Crack
folgendes Problem lösen würde:

Es besteht eine TStringlist mit 1000 Einträgen (auch doppelte),
welche in eine Tabelle eingefügt werden sollen.
Aber nur dann wenn diese Einträge in der Tabelle nicht schon bestehen.

Man könnte nun die ganze Tabelle in den Zugriff nehmen und
mittels LOCATE den Wert suchen. Wenn Locate = false liefert
dann würde der Eintrag mittels Append in die Tabelle eingefügt.

Irgendwie habe ich aber das Gefühl, dass dies unter einem Netzwerk
nicht die richtige Lösung ist. (langsam)

Andererseits glaube ich, dass 1000x SELECT auch nicht unbedingt
korrekt ist.

Wie löst Ihr einen solchen Fall.

Herzlichen Dank und Gruss zum voraus
Roland

mkinzler 7. Okt 2007 22:24

Re: Locate oder SELECT / Wie Problem lösen?
 
Am besten mit dem MERGE-Befehl (ab FB2.1)

RavenIV 8. Okt 2007 08:57

Re: Locate oder SELECT / Wie Problem lösen?
 
Zitat:

Zitat von gullatrulla
Es besteht eine TStringlist mit 1000 Einträgen (auch doppelte),
welche in eine Tabelle eingefügt werden sollen.
Aber nur dann wenn diese Einträge in der Tabelle nicht schon bestehen.

Ich kenn jetzt die FibPlus nicht so gut.
Aber ich würde den "Holzhammer" nehmen. Immer ein INSERT machen.
Wenn der Datensatz schon besteht, dann wirft FibPlus hoffentlich eine Exception.
Diese kann man abfangen und dann weitermachen.
Vorrausgesetzt wird natürlich, dass die DB entsprechend konfiguriert ist.

TRomano 8. Okt 2007 09:53

Re: Locate oder SELECT / Wie Problem lösen?
 
Als erstes würde ich entweder verhindern, wenn möglich, dass doppelte Einträge in die Liste kommen (siehe TStringList.Duplicates) oder diese vor dem Insert entfernen.
Um ein Abfragen durch SELECT zu verhindern (Netzwerkverkehr minimieren), kann man in der Firebird-DB einen Unique-Index auf die Insert-Tabelle und das Feld setzen. z.B. mit:
"CREATE UNIQUE ASC INDEX IndexName ON IndexTabelle COMPUTED BY (upper(FeldName))" bei einem VARCHAR-Field
Dieser verhindert dann bei einem Insert doppelte Werte in der Firebird-Tabelle. (Exception durch DB)

Bei einem Multi-User-Betrieb würde ich kein lokales LOCATE benutzen, da Du ja nur eine zum Zeitpunkt des Öffnens eine aktuelle View auf diese Tabelle hast und in der Zwischenzeit eventuell schon Einträge auf dem DB-Server geändert wurden (insert/update/delete)

marabu 8. Okt 2007 11:26

Re: Locate oder SELECT / Wie Problem lösen?
 
Hallo,

es ist nicht nötig Exceptions oder Constraints für die Behandlung der Duplikate einzusetzen. Ich würde die 1.000 Tupel in eine (vorzugsweise temporäre) Tabelle laden und eine Mengen-Operation durchführen:

SQL-Code:
insert into tgt select distinct * from src where item not in (select item from tgt)
So wird genau die Differenzmenge mit der Zielmenge vereinigt. Das sollte auch mit älteren SQL-Implementierungen funktionieren.

Grüße vom marabu

gullatrulla 8. Okt 2007 13:08

Re: Locate oder SELECT / Wie Problem lösen?
 
Hallo,

Erstmal herzlichen Dank an alle. Ich denke, dass ich nun
Denkansätze habe wie ich das Problem lösen kann.

Nur noch eine kleine Frage zu LOCATE...

Bis anhin habe ich bei kleineren Tabellen LOCATE eingesetzt.
Zuerst habe ich die Tabelle mittels SELECT eingeschränkt,
um danach mit LOCATE zu suchen.

Sehe ich das richtig, dass LOCATE trotz vorherigem SELECT-
Befehl die komplette Tabelle holt?.
Das heisst, dass der SELECT-Befehl gar nichts bringt?

Herzlichen Dank und Gruss zum voraus
Roland

Hansa 8. Okt 2007 13:21

Re: Locate oder SELECT / Wie Problem lösen?
 
Warum immer so kompliziert ? :gruebel: Lasse das doch die Datenbank machen :

SQL-Code:
CREATE PROCEDURE SP (
    NR INTEGER, FELDX)
AS
DECLARE VARIABLE AENDERN INTEGER;
BEGIN
  AENDERN = -1;
  SELECT NR FROM TABLEX WHERE (NR = :NR) INTO :AENDERN; /* falls nichts da, bleibt AENDERN = -1 */
  IF (AENDERN < 0) THEN BEGIN /* noch nicht vorhanden */

    INSERT INTO TABLEX (NR,FELDX)
           VALUES (:NR,:FELDX);
  END
  ELSE BEGIN
/*    UPDATE, nichts tun oder sonstwas */
  END
  SUSPEND;
END^

SET TERM ; ^
Lege im Programm eine FIBStoredProcedure an, übergebe die Parameter, ausführen mit SP.ExecProc und fertig.

P.S.: wo kommen auf einmal so viele FIBPlus-User her ? :shock:

P.S.: das wäre die "Holz-Methode", aber ohne Hammer. :lol:

P.S.3 : SP war nicht richtig, Hektik.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:11 Uhr.

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