Seite 1 von 1

Update einer SQL-Tabelle

Verfasst: Sa, 06. Apr 2013 11:51
von DSE
Hallo Zusammen,

folgendes Problem:

Ich muß einen täglichen Update von einer DBF-Datenbank in eine SQL-Tabelle durchführen. Bestehende Datensätze müßten aktualisiert werden und neue Datensätze sollten hinzugefügt werden.
Wie stelle ich es am besten an?

Dank im voraus.

Viele Grüße
Ayhan

Re: Update einer SQL-Tabelle

Verfasst: Sa, 06. Apr 2013 12:09
von brandelh
Für Datenabgleich habe ich immer ein extra Feld in der DBF vorgesehen, welches den Status enthält.

Code: Alles auswählen

0=Neu => INSERT
1=Erledigt, nichts machen
2=Unklar / geändert => UPDATE
? ...
falls es bei SQL jedoch im Befehl UPDATE/INSERT gibt, der das je nach Vorhandensein selbst regelt, könnte man auf den Status verzichten.

Ansonsten bliebe nur, bei jedem Satz per Abfrage zu prüfen ob INSERT / UPDATE nötig ist.

Was man auf jeden Fall braucht ist ein eindeutiger Schlüsselbegriff.

Re: Update einer SQL-Tabelle

Verfasst: Sa, 06. Apr 2013 12:23
von DSE
Hallo Hubert,

verständnis Frage:

Bei Xbase:

Code: Alles auswählen

select 1
use Tabelle1 index key1
select 2
use Tabelle2 index key2
Do while !Eof()
     select 2
     seek(tabelle1->key)
     if eof()
        Append Blank
        ...Replace Anweisung
     else 
        ....Replace Anweisung
     endif 
     select 1
     skip
enddo
wie würde es bei SQL aussehen?

Viele Grüße
Ayhan

Re: Update einer SQL-Tabelle

Verfasst: Sa, 06. Apr 2013 12:48
von brandelh
Ich bin NICHT der SQL Experte ;-)

INSERT entspricht einem append blank mit replace ...
UPDATE entspricht einem dbseek und replace ...

Re: Update einer SQL-Tabelle

Verfasst: Sa, 06. Apr 2013 14:25
von Tom
Hallo, Ayhan.

Du kannst eine SQL-Datenbank via ODBCDBE öffnen und im Prinzip exakt so verfahren, wie Du das mit der normalen DBE machst. Wenn es um überschaubare Strukturen und Datenmengen geht, ist das vielleicht sogar ein sinnvoller Weg. Die ODBCDBE ist in der Prof. Subscription enthalten.

Ansonsten sei Boris Borzics "SQLexpress" empfohlen, das ist sowieso ein unverzichtbares Tool, kostet nicht viel - und bringt Beispielcodes für solche Fälle gleich mit:

www.sqlexpress.net

Re: Update einer SQL-Tabelle

Verfasst: Sa, 06. Apr 2013 15:42
von georg
Hallo,


falls Du mit MySQL arbeitest, könnte die REPLACE.Anweisung interessant sein:

http://dev.mysql.com/doc/refman/5.6/en/replace.html

Im Moment kann ich leider nicht sagen, ob REPLACE im SQL-Standard enthalten ist oder nicht.

Re: Update einer SQL-Tabelle

Verfasst: So, 07. Apr 2013 9:10
von DSE
Hallo Zusammen,

vielen Dank für die Infos.

habe es so gelöst. Zuerst versuche ich ein Update fals Update einen Wert von <=0 zurück gibt. mache ich einen Insert.

Code: Alles auswählen

function DownloadCubiscan( cfelder)
   Local oConn := DefaultSQLConnection()
   Local oClient, cSQL, nUpdate, lRet := .f.
   Local x := String2Array(cfelder, ",")
 
   x[_PACKSIZE] := ltrim(str(max(1,val(x[_PACKSIZE]))))
   x[_ITEM_NUM] := xb2sql(x[_ITEM_NUM])
 
   cSQL := "UPDATE artikel SET" +;
            " length="     + x[_LENGTH] +;
            ",width="     + x[_WIDTH ] +;
            ",height="    + x[_HEIGHT] +;
            ",weight="    + x[_WEIGHT] +;
            ",volume="    + x[_VOLUME] +;
            ",dim_weight="+ x[_DIM_WEIGHT] + " WHERE product=" + x[_ITEM_NUM] + " AND packsize=" + x[_PACKSIZE]
 
   nUpdate := oConn:execute(cSQL)
 
   if nUpdate == SQL_XPP_ERROR
      cError := "FAILED: " + cRow
      LogEvent( cError )
      LogEvent( cSQL )
      Return .f.
 
   elseif nUpdate <= 0
      // new product - insert into Artikel table
 
      cSQL := "INSERT INTO artikel (product,packsize,length,width,height,weight,volume,dim_weight) VALUES (" +;
           x[_ITEM_NUM]+","+x[_PACKSIZE]+","+x[_LENGTH]+","+x[_WIDTH]+","+x[_HEIGHT]+","+x[_WEIGHT]+","+x[_VOLUME]+","+x[_DIM_WEIGHT]+")"
 
      if oConn:Execute(cSQL) == SQL_XPP_ERROR
         cError := "FAILED: " + cRow
         LogEvent( cError )
         LogEvent( cSQL )
         Return .f.
      endif
   endif
   Return .t.

Re: Update einer SQL-Tabelle [erledigt]

Verfasst: So, 12. Okt 2014 17:03
von Fischkopp
Hallo,
sowas hab ich auch gerade gebaut, mit Hector`s sql-Baukasten, sieht im Kern so aus:

oTbl := MyResult():New(oCon,,"products",,,,1)
y := 1
DO WHILE y<=m
sqlbef="UPDATE products SET `products_image`='"+aFotomain[y,3] + "' where `products_id` =" + aFotomain[y,2] + " ;"
oTbl:ExecuteSql(sqlbef)
y := y + 1
ENDDO

Meine Frage:
gibt es alternativ einen sql-Befehl, der eine Liste solcher Änderungen en Block ausführt statt die Schleife einzeln abzuarbeiten ?
Ich will die anderen Felder von `products` nicht antasten, `products_id` ist hier das eindeutige Feld, die Infos des Arrays liegen lokal.
So läuft das zwar, aber was, wenn die Menge der Updates ausartet?

Vielleicht hat ja jemand eine Idee, mir fällt dazu nichts ein :(

Re: Update einer SQL-Tabelle

Verfasst: So, 12. Okt 2014 20:52
von AUGE_OHR
DSE hat geschrieben:Ich muß einen täglichen Update von einer DBF-Datenbank in eine SQL-Tabelle durchführen.
Bestehende Datensätze müßten aktualisiert werden und neue Datensätze sollten hinzugefügt werden.
Wie stelle ich es am besten an?
Die grundsätzlich Frage hast du ja gelöst, aber der Weg ist wohl eher für kleine Datenmengen gedacht.
wenn wir nun von > 100.000 Datensätzen sprechen sollte man ein anderes Konzept wählen wo man dem SQL Server die Arbeit überlässt ;)

Unter PostgreSQL gibt es den COPY Befehl und in MySQL den LOAD DATA Befehl womit man schnell Daten in eine (temporäre) SQL Table importieren/exportieren kann.
Den Code für die Logik würde ich als Function in SQL anlegen welche vom Client mit

Code: Alles auswählen

SELECT machmal()
dann auf dem SQL Server ausgeführt wird.

Re: Update einer SQL-Tabelle

Verfasst: Mo, 13. Okt 2014 8:46
von brandelh
eventuell kann man die Befehle verketten, damit z.B. 10 Updates auf einmal durchgeführt werden,
bei einem IMPORT hat das damals die Geschindigkeit deutlich verbessert, aber bei 100.000 Sätzen ist auch das zu langsam.
In solchen Fällen erstelle ich eine SQL Anweisungsdatei (Vorlage ist die Datensicherungsdatei ;-) )
und lasse diese auf dem Server direkt ausführen.

Da das aber schon wieder eine Weile her ist (und ich nicht auf SQL umgestiegen bin) fehlen mir Beispiele.

Re: Update einer SQL-Tabelle

Verfasst: Mo, 13. Okt 2014 9:29
von georg
Hallo, Reiner -


eine Überlegung könnte es sein, das Array in eine temporäre SQL-Tabelle zu laden:

CREATE TEMPORARY TABLE pi_uploaded (pi_loaded text, pi_id int, primary key (pi_id))

Das Laden sollte ja recht fix gehen, und dann:

UPDATE products SET products_image = pi_loaded where products_id = pi_id INNER JOIN pi_uploaded ON products_id = pi_id

(Das Thema wird im Internet mehrfach behandelt, weil's eben auch ein paar Fallstricke hat, wie man z.b. hier nachlesen kann: http://stackoverflow.com/questions/2247 ... a-id-match)

Re: Update einer SQL-Tabelle

Verfasst: Mo, 13. Okt 2014 14:06
von Fischkopp
Hallo, erst mal Danke für die Anregungen
also doch nichts direktes, sondern einen upload in eine temporäre Tabelle, und auf dem Server den Rest der Arbeit, ok :)
Die wäre ja schlank nur mit den relevanten Daten, ob ich dann eine function auf dem Server anlege, weiß ich aber noch nicht.
- Jimmy
`load data infile` ist auf fast allen online-Servern, zumindest was Shops angeht, standard-mäßig deaktiviert, aus Sicherheitsgründen ! :wink:
würde auch nur beim anlegen einer temporären Tabelle helfen, ansonsten muß ich alle Felder füllen !

Da ich noch kein putty installiert habe, übe ich im Moment eh noch `trocken`, über Zeitbedarf etc kann ich also noch nichts definitives sagen.

Also erst mal vielen Dank und

Re: Update einer SQL-Tabelle

Verfasst: Mo, 13. Okt 2014 14:25
von AUGE_OHR
brandelh hat geschrieben:bei einem IMPORT hat das damals die Geschindigkeit deutlich verbessert, aber bei 100.000 Sätzen ist auch das zu langsam.
hm ... um 600.000 Sätze aus eine DBF in eine *.CSV zu schreiben benötige ich ca. 24 Sec.
Der Import mit dem Console Befehl COPY ( PostgreSQL ) oder LOAD DATA ( MySQL ) dauert ca. 3 Sec.

wenn man das mit einem INSERT machen würde dauert es Stunden ...

Re: Update einer SQL-Tabelle

Verfasst: Mo, 13. Okt 2014 15:27
von georg
Hallo, Reiner -


putty.exe ist quasi eine "portable App", die braucht keine Installation. Runterladen, starten, fertig.

Re: Update einer SQL-Tabelle

Verfasst: Mo, 13. Okt 2014 17:59
von brandelh
AUGE_OHR hat geschrieben:
brandelh hat geschrieben:bei einem IMPORT hat das damals die Geschindigkeit deutlich verbessert, aber bei 100.000 Sätzen ist auch das zu langsam.
hm ... um 600.000 Sätze aus eine DBF in eine *.CSV zu schreiben benötige ich ca. 24 Sec.
Der Import mit dem Console Befehl COPY ( PostgreSQL ) oder LOAD DATA ( MySQL ) dauert ca. 3 Sec.

wenn man das mit einem INSERT machen würde dauert es Stunden ...
du solltest genauer lesen was ich schreibe ;-)

die Aussage, dass es zu lange dauert bezog sich auf einen IMPORT mit SQLexpress bei dem ich 10 INSERT Befehle in einen Aufruf gepackt habe (das ging aber nur bei MySQL).
Für größere Datenmengen habe ich empfohlen für den Server Ladedateien zu erstellen, ich denke dass du das mit LOAD DATA gemeint hast ;-)

Re: Update einer SQL-Tabelle

Verfasst: Mo, 13. Okt 2014 23:42
von Fischkopp
Hallo erstmal
macht doch bitte keine Prinzipien-Diskussion aus meiner einfachen Frage [-X
Meine Frage bezog sich auf ein einfaches `update` von einzelnen Feldern bestimmter Datensätze einer Tabelle !
Ergo ist `insert` nicht das Thema, und `load data infile` nur möglich, wenn ich alle Felder der betroffenen Sätze überschreibe, d.h. kenne !
Ein Abgleich wäre sonst nur möglich, wenn ich die Tabelle kmpl. downloade, abgleiche und dann (nur geänderte Sätze) wieder hochlade.
So mach ich das schon seit 10 Jahren, aber nicht direkt ( d.h. über PHPMyAdmin mit csv-Dateien).
Ich werde mal probieren, ob ich per putty auch so arbeiten kann, d.h. `load data` da ausführbar ist.......
Ansonsten muß man wohl einfach schauen, was für welchen Einsatz sinnvoll ist :)

Wenn ich `meine` Lösung habe, werde ich sie hier vorstellen,
ansonsten halte ich das Thema erst mal für beendet!

bis dann

Re: Update einer SQL-Tabelle

Verfasst: Di, 14. Okt 2014 0:20
von AUGE_OHR
Fischkopp hat geschrieben:macht doch bitte keine Prinzipien-Diskussion aus meiner einfachen Frage [-X
Der Punkt ist ob man bei SQL dem Server oder dem Client die Arbeit überlasst.
Fischkopp hat geschrieben:Meine Frage bezog sich auf ein einfaches `update` von einzelnen Feldern bestimmter Datensätze einer Tabelle !
Ergo ist `insert` nicht das Thema, und `load data infile` nur möglich, wenn ich alle Felder der betroffenen Sätze überschreibe, d.h. kenne !
Ein Abgleich wäre sonst nur möglich, wenn ich die Tabelle kmpl. downloade, abgleiche und dann (nur geänderte Sätze) wieder hochlade.
Du vergleicht DBF <-> SQL Inhalte mit dem Client !
eine DO WHILE !EOF() Schleife erfolgt auf der Client Seite und ist typisch Xbase (alle Versionen)

was ich nun meine wäre das arbeiten mit 2 SQL Table "direkt" auf dem SQL Server.
wie nun ein SELECT dazu ausseht hat dir ja Georg gezeigt. Das ganze könnte man nun in einer SQL Function ablegen und mit

Code: Alles auswählen

SELECT machmal()
ausführen.
Fischkopp hat geschrieben:So mach ich das schon seit 10 Jahren, aber nicht direkt ( d.h. über PHPMyAdmin mit csv-Dateien).
Ich werde mal probieren, ob ich per putty auch so arbeiten kann, d.h. `load data` da ausführbar ist.......
du kannst ja auch mysqlimport benutzten was die selbe Syntax hat wie LOAD DATA
überhaupt würde ich primär die MySQL Tools benutzen und die als Referenz benutzen wenn man CSV Dateien erstellt.
( PHPMyAdmin benutzt ' für ENCLOSED was bei den Amis kein Problem ist aber was passiert wenn wir ein Apostroph haben ? )

p.s. mit der Option LOCAL ist folgendes gemeint.
The LOCAL keyword affects expected location of the file and error handling, as described later. LOCAL works only if your server and your client both have been configured to permit it. For example, if mysqld was started with --local-infile=0, LOCAL does not work. See Section 6.1.6, “Security Issues with LOAD DATA LOCAL”.

• If LOCAL is specified, the file is read by the client program on the client host and sent to the server. The file can be given as a full path name to specify its exact location. If given as a relative path name, the name is interpreted relative to the directory in which the client program was started.

• If LOCAL is not specified, the file must be located on the server host and is read directly by the server. The server uses the following rules to locate the file:
also null Problem wenn ich auf dem SQL Server arbeite ... wo sonst bei solchen SQL Aufgaben für den Administrator.

Re: Update einer SQL-Tabelle

Verfasst: Mi, 15. Okt 2014 6:51
von georg
Hallo, Jimmy -


da liegt m.E. ein Missverständnis vor:
AUGE_OHR hat geschrieben:Der Punkt ist ob man bei SQL dem Server oder dem Client die Arbeit überlasst.
Du kannst im Umgang mit einem SQL-Server keinem Client "die Arbeit überlassen". :banghead:

Re: Update einer SQL-Tabelle

Verfasst: Mi, 15. Okt 2014 7:39
von Herbert
:) , georg
Jimmy meinte wohl, dass der SQL-Server wesentlich schneller ist. Also macht es Sinn, dort vieles entsprechend vorzubereiten und durchzuführen, als dass der Client bei sich werkelt und selektiv von SQL-Server informationen holt.
Und ja, Replace ist ein Standard-Befehl

Re: Update einer SQL-Tabelle

Verfasst: Mi, 15. Okt 2014 8:02
von brandelh
Was wie gemacht werden sollte hängt natürlich von der tatsächlichen Aufgabe (und den SQL-Fähigkeiten) ab !
  1. Preis steigt allgemein um 15% ... das geht mit einem Befehl (ich denke UPDATE preis ... )
  2. Preise steigen je nach Gruppe oder anderen Bedingungen ... ich würde da je Gruppe den Befehl von 1 verwenden.
    Man könnte aber sicher auch eine Updateanweisungsdatei für den Server erstellen und das ganze dort ausführen lassen.
  3. Abgleich von Daten etc. mit vielen Tausend Datensätzen, hier ist es einfach deutlich schneller eine Update/Import Anweisungsdatei zu erstellen,
    als viele Tausend UPDATE / SELECT statements per Xbase++ abzusetzen.
  4. Abgleich von einzelnen Datensätzen, gleichzeitig immer die Möglichkeit einer ONLINE Abfrage der Daten.
    Hier bleibt aus meiner Sicht nur die sofortige transaktionsgeschützte Ausführung

Re: Update einer SQL-Tabelle

Verfasst: Mi, 15. Okt 2014 8:11
von georg
Hallo, Herbert -


es handelt sich um ein gedankliches Problem: im Umgang mit einem SQL-Server führt der Server ALLES aus, der Client gibt nur Aufträge. Statements wie das von Jimmy führen da in die Irre.

Es liegt am Programmierer, wie er die Arbeitspakete verteilt. Das ist - abhängig vom Umfang des Paketes, der Auslastung des Servers oder auch in Abhängigkeit von vorhandenen Richtlinien - eine Entscheidung, die der Programmierer treffen muss.

Es gibt auch die Möglichkeit, z.B. mit prepared statemens zu arbeiten: http://dev.mysql.com/doc/refman/5.6/en/prepare.html Das ist quasi das Gegenstück zu einem Codeblock unter Xbase++.

Re: Update einer SQL-Tabelle

Verfasst: Mi, 15. Okt 2014 8:49
von brandelh
georg hat geschrieben: es handelt sich um ein gedankliches Problem: im Umgang mit einem SQL-Server führt der Server ALLES aus,
der Client gibt nur Aufträge. Statements wie das von Jimmy führen da in die Irre.
Mein erster Kontakt mit einem Programm (in MS Access) das auf einen SQL Server zugriff um Inventardaten für
die Beschäftigten zu speichern war sehr ernüchternd. Ich war Anwender ...
Jeder "Skip" von einem User zum nächsten dauerte etwa 1 Minute !
Das Programm, welches ich Jahre zuvor für eine ähnliche Aufgabe schrieb (DBF NTX über WAN Netze), brauchte lokal im LAN keine Sekunde,
in den Außenstellen wegen der langsamen Leitung 2 bis 3 Sekunden (keine Listen, nur einzelne Sätze mit Auswahllisten die ich in STATIC ARRAYS zwischenspeicherte).

Was war geschehen ?

Das Programm forderte jedesmal alle Daten an ( SELECT * ) und durchsuchte diese lokal in Schleifen.

Der Server hatte mehr Arbeit, weil er alle Daten übertragen musste, der Client musste das alles auch noch durchsuchen.
Bei richtiger Verteilung hätte der SERVER gesucht (WHERE ...) und weniger übertragen, das lokale Anwendungsprogramm hätte nichts druchsuchen müssen.

Man sieht, Arbeit ist ein relativer Begriff ;-)

PS: Das ist aber auch ein Grund warum ich der Aussage (geht alles wie bisher ...) grundsätzlich misstraue !
Man kann zwar auch mit dem 60 Tonner oder dem Sportwagen um die Ecke Brötchen kaufen, aber es gibt sinnvollere Lösungen :badgrin:

Re: Update einer SQL-Tabelle

Verfasst: Do, 16. Okt 2014 1:18
von AUGE_OHR
georg hat geschrieben:es handelt sich um ein gedankliches Problem: im Umgang mit einem SQL-Server führt der Server ALLES aus, der Client gibt nur Aufträge. Statements wie das von Jimmy führen da in die Irre.
sorry wenn ich es falsch ausgedrückt habe. Klar werden alle SQL Anfragen vom SQL Server ausgeführt.

es wurde ja nach Update gefragt wobei die Daten dazu noch aus einer DBF kamen.
Der Zugriff auf die DBF wird dabei vom (intelligenten) Client ausgeführt ...

wenn es 2 SQL Table wären könnte es auch ein "dummer" Client ( ohne Xbase++ Runtime )
,mit den Server Tools, ein SELECT in Arbeit geben.

worauf ich raus will ist das man bei SQL nicht nur seinen Code "anpasst" sondern auch in SQL "denkt".
ich empfinde es ähnlich wie mit OOP wo ich am Anfang immer noch procedural dachte ... bis ich anfing selbst in Class Code zu schreiben.

Re: Update einer SQL-Tabelle

Verfasst: Do, 16. Okt 2014 17:40
von Fischkopp
Hallo,
da habe ich ja was angerichet :roll:
geht`s noch um meine Frage, oder mich ?

@Georg: Das Beispiel ist gut und hilfreich =D>
ob`s sich lohnt, so zu verfahren, ist wohl vor allem von der Menge der Daten abhängig.

@Hubert: Deine Zusammenfassung der verschiedenen Optionen bringt`s auf den Punkt !

@Jimmy
AUGE_OHR hat geschrieben: Du vergleicht DBF <-> SQL Inhalte mit dem Client !
wie, wo ? Mein Beispiel ist ein array !
AUGE_OHR hat geschrieben: es wurde ja nach Update gefragt wobei die Daten dazu noch aus einer DBF kamen.
Da ist nix aus dBase, auch keine Daten, das weißt du doch ! Ich habe nach einem sql-Befehl gefragt für obigen Job, sonst nix!
AUGE_OHR hat geschrieben: wenn es 2 SQL Table wären könnte es auch ein "dummer" Client ( ohne Xbase++ Runtime ) ,mit den Server Tools, ein SELECT in Arbeit geben.
Ja, wie Georg schon beschrieben hat.
AUGE_OHR hat geschrieben: worauf ich raus will ist das man bei SQL nicht nur seinen Code "anpasst" sondern auch in SQL "denkt".
Ich denke, du denkst, ich denke nicht richtig :lol:
AUGE_OHR hat geschrieben:ich empfinde es ähnlich wie mit OOP wo ich am Anfang immer noch procedural dachte ... bis ich anfing selbst in Class Code zu schreiben.
Du empfindest was, was mit der Frage oben nix zu tun hat! Wie diese Schleife eingebunden wird, war nicht die Frage!
Laß uns doch bitte einfach bei der Sache bleiben, Allgemeinplätze nützen mir nix und ich denke, ich habe schon einiges gelernt, auch von dir :wink:

Also, erst mal