Seite 1 von 2

PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 3:34
von AUGE_OHR
hi,

nach dem "Edit" bin ich nun beim "Save" angekommen.

Code: Alles auswählen

local cSQL :=   "UPDATE " + ::cTable + " SET "
danach kommen dann die "Felder" und Zuweisungen. zum Schluss sende ich dann der String mit

Code: Alles auswählen

IF ::oPG:exec(cSQL)
    oRes := ::oPG:result
aber die Anweisung*** stimmt so noch nicht :(
***wurde per Abfragen zusammengesetzt

hm ... ich gelange aus einem Browse, per o:itemselect, in die Edit Maske und "lade" ja die richtigen Daten.

Frage : stehe ich damit auf dem "Record" ?

ich ging davon aus das ich das "UPDATE ..." auf "dem" Datensatz mache ... oder muss ich ihn noch vorher "Positionieren" ?

ich habe ja noch das "alte" ::oPG:result Object vom Intro des "Edit" ... kann ich da was von verwenden ?

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 4:25
von AUGE_OHR
"UPDATE "+cTable+" SET "+... Felder = Value ...+" WHERE id = "+cID
das WHERE fehlte ...

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 7:24
von UliTs
Ich finde, besonders lesbar bleiben die SQL-Statements, wenn man die folgende Syntax verwendet:

Code: Alles auswählen

TEXT INTO cSQL WRAP chr(13)+chr(10) TRIMMED
  UPDATE  [cTable] SET
          [cFeldname1] = [xFeldwert1]
  WHERE   id = [nId]
ENDTEXT
cSQL := StrTran( cSQL,"[cTable]","Adressen" )
cSQL := StrTran( cSQL,"[cFeldname1]","Vorname" )
cSQL := StrTran( cSQL,"[xFeldwert1]","Jimmy" )
...
cSQL := StrTran( cSQL,"[nId]","1234" )
Vor allem bei großen SQL-Statements über viele Zeilen ist dies sehr übersichtlich, finde ich :-) .

Uli

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 7:58
von Jan
Genau. Gerade bei längen SQL-Anweisungen kann man schnell den Überblick verlieren. Wenn z. B. mehrere JOINs verwendet werden, dazu noch WHERE, diverse dazugehörige SELECT, usw. Da kommen manchmal wahre Ungetüme von Anweisungen zusammen, die kein Mensch mehr ordnetlich überblicken kann.

Deswegen gibt es entsprechende Hilfsprogramme (auch online), die das alles in ein vernünftig lesbares Format bringen. Wobei man das natürlich auch selber machen kann, wenn man konsequent von Anfang an eine solche Übersichtlichkeit erzwingt. Das ist wie mit normalem Code auf, den schreibt man ja auch so, das er übersichtlich ist.

Jan

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 10:55
von brandelh

Code: Alles auswählen

 UPDATE  xxx SET Feld = xWert 
entweder man prüft xWert wirklich ausführlich oder man hat ein Problem (gilt natürlich auch für SELECT etc.) ...
:arrow: http://de.wikipedia.org/wiki/SQL-Injection

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 11:28
von georg
Hallo,


auch auf die Gefahr, mich mal wieder unbeliebt zu machen ...

Jimmys Problem, wie ich es verstanden habe, bezieht sich auf den Fokus für den Update:
Frage : stehe ich damit auf dem "Record" ?
Wir sprechen über SQL, nicht über DBF. Mein SELECT * FROM table erzeugt ein Result Set, das normalerweise nur eine Kopie der echten Daten darstellt. Um eine Veränderung in der Tabelle durchzuführen, muss ich ein gezieltes Update durchführen, da ich keinen "Datensatz" im "Zugriff" habe.

Ein

Code: Alles auswählen

UPDATE  xxx SET Feld = xWert 
ist extrem gefährlich, da ALLE Sätze der Tabelle xxx diese Veränderung erfahren würden.

Es gibt verschiedene Ansätze, das Ziel einzugrenzen.

a) wenn ich einen primary key habe, dann kann ich per

Code: Alles auswählen

WHERE keyfield = value
den Fokus einschränken und treffe genau den Satz, den ich ändern will;

b) wenn ich sicherstellen kann, dass es ein Feld gibt, das den Satz eindeutig identifiziert, kann ich auch dieses Feld verwenden;

c) als Alternative bei Tabellen ohne BLOB und Konsorten kann man natürlich auch - unter Zugriff auf die alten Werte - folgendes Konstrukt verwenden (wie es z.B. Hector bei seiner MySQL Klasse macht):

Code: Alles auswählen

WHERE feld1 = wert-feld1 AND feld2 = wert-feld2 AND ... AND feldn = wert-feldn
Ich halte dies nicht für die beste Lösung, aber es ermöglicht, einen Datensatz (hoffentlich) eindeutig zu identifizieren.

d) je nach SQL Implementierung gibt es (interne) Felder, die einen Satz eindeutig identifizieren. Bisher bin ich lediglich bei SQLite auf ein solches Feld gestossen, dass als "rowid", "oid", oder "_rowid_" angesprochen werden kann und quasi ein primary key auto_increment darstellt.


Gruss,

Georg

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 11:34
von brandelh
Ich verwende bei meinen MySQL DBs ein Feld "recno" als primary key ;-)

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 13:46
von UliTs
brandelh hat geschrieben:

Code: Alles auswählen

 UPDATE  xxx SET Feld = xWert 
entweder man prüft xWert wirklich ausführlich oder man hat ein Problem (gilt natürlich auch für SELECT etc.) ...
:arrow: http://de.wikipedia.org/wiki/SQL-Injection
Hallo Hubert,
das würde aber nur dann greifen, wenn "xWert" beispielsweise durch eine freie Eingabe des Benutzers möglich ist!
Hat -finde ich- nichts mit Jimmys Frage zu tun...

Uli

P.S. Georg, toll wie Du Dein Wissen über SQL durch ausführliche Antworten weitergibst :-) . :!:

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 13:48
von brandelh
UliTs hat geschrieben:Hallo Hubert,
das würde aber nur dann greifen, wenn "xWert" beispielsweise durch eine freie Eingabe des Benutzers möglich ist!
Hat -finde ich- nichts mit Jimmys Frage zu tun...
ist das nicht fast immer der Fall ?

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 13:59
von UliTs
Warum hast Du dann Deinen Beitrag in diesem Zusammenhang veröffentlicht?

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 14:04
von brandelh
Ich verstehe deine Frage nicht ...

im ersten Posting schreibt Jimmy, dass er nach dem "Edit" beim "Save" angekommen ist.
"Edit" = freie Eingabe ...
dann bringt er Zeilen mit UPDATE ... feld = cVariable ... offensichtlich also die "Edit" Eingabe die gespeichert werden soll.

WANN also sollte der Hinweis (besser Warnung) auf die Gefahr eines SQL Injektion passender sein ?

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Do, 28. Jun 2012 14:32
von UliTs
Ok, Du hast mich überzeugt :-) .

Uli

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Fr, 29. Jun 2012 1:49
von AUGE_OHR
hi,

danke für deine Ausführliche Antworten.
georg hat geschrieben:Ein

Code: Alles auswählen

UPDATE  xxx SET Feld = xWert 
ist extrem gefährlich, da ALLE Sätze der Tabelle xxx diese Veränderung erfahren würden.
genau das ist mir als Newbie passiert ;)

Frage : aber das "alle" bezieht sich dann nur auf die "SELECT ..." welche ich in oResult habe ?
georg hat geschrieben:a) wenn ich einen primary key habe, dann kann ich per

Code: Alles auswählen

WHERE keyfield = value
den Fokus einschränken und treffe genau den Satz, den ich ändern will;
YUP das hab ich nun mit "WHERE id = cID" z.b. Kdnr, Artnr etc. also das was man so im Indexkey() hatte.

der Ansatz von Hector MySQL ist Klasse =D> und ich "lerne" viel von seinem Code.

soweit bin ich längst noch nicht mit PostgreSQL wobei ich nun zusammen mit Edgar Borger die PG Schnittstelle von Phil ( jetzt mit ot4xb ) für die v8.3/8.4 benutzten möchte.
der Code ist aber noch nicht so weit "dokumentiert" sodass nur Demos existieren an denen wie noch arbeiten.

p.s. wer Lust hat ist gerne "eingeladen", bitte PN

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Fr, 29. Jun 2012 5:21
von georg
Hallo, Jimmy -

Frage : aber das "alle" bezieht sich dann nur auf die "SELECT ..." welche ich in oResult habe ?
Nein, da beide Operationen von einander unabhängig sind.

Beispiel:

Code: Alles auswählen

SELECT * FROM table WHERE EingangsDatum = '2012-06-29'
...
UPDATE table SET geliefert = '1'
In diesem Beispiel würde in allen Sätze der Tabelle das Feld geliefert auf '1' gesetzt. Die vorherige Einschränkung beim SELECT galt nur dort. Du musst also, wenn Du nur die Sätze aus dem Result Set verändern willst, auch die gleiche Bedingung verwenden:

Code: Alles auswählen

UPDATE table SET geliefert = '1' WHERE EingangsDatum = '2012-06-29'

Gruss,

Georg

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Sa, 30. Jun 2012 2:27
von AUGE_OHR
georg hat geschrieben:Nein, da beide Operationen von einander unabhängig sind.
danke für dein Beispiel.
gut zu wissen das ich einen "Scope" damit wohl nicht "so" nach PG übersetzten darf.

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Sa, 30. Jun 2012 5:08
von AUGE_OHR
hi,

das "UDPATE " funktioniert wohl, aber ich muss noch einen "Denkfehler" haben.

aus einem Browse gehe ich in das Edit ändere was und schicke das per "UPDATE " ab.
nun kommt ein oBrowse:refreshcurrent() und ich kann im Debugger sehen wie er im Skipper die Daten,
per Datalink, "neu" einliest ... aber die Daten sich die "alten" ???

erst wenn ich das Browse "zumache" und wieder Table / Fields wähle zeigt er mir die Änderungen an.

ich "denke" ich mache wieder den oResult "Denkfehler" ...
mein o:datalink, für den Browse Codeblock, ist ja eine Method in der oResult Class.

Frage : wenn ich eine "UPDATE " sende muss ich dann auch die oResult Abfrage erneuern ?

hm ... ich sehe gerade in Hectors MySQL Sample

Code: Alles auswählen

METHOD XbTable:RefreshAll()
local lresp := .t.
   mysql_free_result(::pResult)

   if (::pResult := ::EXECUTESQL(::cSql)) > 0
       ::nRows :=  mysql_num_rows(::pResult)
       ::nCurRow := ::nRows
       ::GetRowData(::nCurRow)
   else
       lresp := .f.
   endif

return lresp
ok ... kapiert ... also ein "normales" o:refreshCurrent() kann das wohl nicht ;)

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Di, 03. Jul 2012 6:50
von AUGE_OHR
hi,

es funktioniert ... aber ich finde es nicht optimal ...

ich bräuchte ja nur ein "refresh" von dem geänderten "einem" Datensatz, muss aber "alle" wieder neu per SQL Query "abfragen"...

natürlich hat das auch mit meinem oBrowse:datablock() zu tun was mit den oResult Object arbeitet.
wenn ich das nun doch auf Array umstelle müsste ich ja "nur" für das Element ( "__record" ) neu einlesen ...

soviel zum "UDPATE ..." von einem einzelnen Datensatz was ja nun klappt.
jetzt das ganze "automatisch" mehrmals ... -> crash ... hm ... mit SLEEP(100) -> langsam aber es läuft !
hm ... fast so als wenn ich mit der pgDBE arbeite ...

Frage : gibt es beim "UPDATE ..." zeitlich was zu beachten ?

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Mi, 11. Jul 2012 5:06
von AUGE_OHR
was mit einer Table geht muss ja nicht mit mehreren gehen :(
11:54 CEST ERROR: column "a" of relation "artikel" does not exist at character 25
2012-07-11 04:11:54 CEST STATEMENT: UPDATE artikel AS a SET a.verpackung='1 piece' WHERE a.__record=3118
was ich vorher gemacht habe ergibt sich aus dem Logbuch
Send Query :
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'
6 Tables:
alaska-software.isam.tables
alaska-software.isam.orders
alaska-software.system.connections
artikel
customer
parts

select Table : artikel AS a
Send Query :
SELECT * FROM artikel AS a LIMIT 1
Answer Result :

artnr C 5
// gekürzt
lastplatz C 4

38 Fields :

used Fields for Column :

a.artnr
// gekürzt
a.__deleted
a.__record
a.__rowversion
a.__keyversion
a.__lock_owner

now browse

SELECT a.artnr,
// gekürzt
,a.__deleted,a.__record,a.__rowversion,a.__keyversion,a.__lock_owner FROM artikel AS a
über das Browse bin ich dann ich den Edit Dialog aber beim "save" bekomme ich den Log Eintrag :(

gebt mir doch bitte einen weiteren Tips warum die Syntax hier nicht funktioniert ... was mache ich falsch ?

Code: Alles auswählen

1234567890123456789012345
UPDATE artikel AS a SET a.verpackung='1 piece' WHERE a.__record=3118

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Mi, 11. Jul 2012 6:36
von georg
Hallo, Jimmy -


je nach SQL Dialekt lautet die Fehlermeldung "error at 'set'", während PostgreSQL Dich mit der Nase draufstösst: ab dem 25. Zeichen Deiner Anweisung mag es selbige nicht mehr. Wenn ich mich nicht verzählt habe, ist dass a.verpackung.

Die Verwendung eines Alias macht nur Sinn, wenn mehrere Tabellen verwendet werden, die gleichnamige Feldnamen verwenden. Es kann sein, dass PostgreSQL Deinen Alias ablehnt, weil der keinen Sinn macht. Versuche doch mal

Code: Alles auswählen

UPDATE artikel SET verpackung='1 piece' WHERE __record=3118
Die andere Alternative ist, dass "verpackung" falsch geschrieben wurde.


Gruss,

Georg

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Mi, 11. Jul 2012 7:22
von AUGE_OHR
georg hat geschrieben:Es kann sein, dass PostgreSQL Deinen Alias ablehnt, weil der keinen Sinn macht.
:shock: Tja und damit könntest du Recht haben. klar geht es ohne das "a." ( wie vorher )

Code: Alles auswählen

UPDATE customer AS a SET lastname='Miller',notes='Euro' WHERE a.__record=1;
beim WHERE nimmt er nun wieder den "ALIAS" ...

btw : muss man an das Ende ein ";" setzten ?

ok also werde ich das mit einplanen und nicht alle Fields "pro-forma" ein "ALIAS" verpassen sondern wirklich nur bei den "doppelten".
georg hat geschrieben:Die andere Alternative ist, dass "verpackung" falsch geschrieben wurde.
das "sollte" die Logibc von PGU.EXE verhindern ;)
bei PGu.EXE wird alles "ausgelesen" und praktisch nichts "manuelle" eingegeben.

noch eine Frage : mit

Code: Alles auswählen

WHERE a.__record=1
würde sich das ja auf eine, wenn vorhanden, "Vater" Tabelle beziehen.
da ich nun "Vater" und "Kind" beim "save" habe ...

Code: Alles auswählen

WHERE a.__record=1234 AND b.__record=9876
wäre das die Syntax wenn ich a.blabla und b.blabla geändert hätte ?
... oder kann/sollte ich das auch in 2 Befehle "aufteilen" ?

Code: Alles auswählen

cSql := "UPDATE artikel AS a SET verpackung='Test' WHERE a.__record=1040;"
::Exec(cSql)
cSql := "UPDATE abgang AS b SET bezeichnung='Test' WHERE b.__record=346;"
::Exec(cSql)

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Mi, 11. Jul 2012 7:48
von AUGE_OHR
http://www.postgresql.org/docs/8.0/stat ... pdate.html
fromlist
A list of table expressions, allowing columns from other tables to appear in the WHERE condition and the update expressions.
This is similar to the list of tables that can be specified in the FROM Clause of a SELECT statement.

Note that the target table must not appear in the fromlist, unless you intend a self-join (in which case it must appear with an alias in the fromlist).

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Mi, 11. Jul 2012 8:47
von brandelh
Hi,

bei der Zeile

Code: Alles auswählen

UPDATE artikel SET verpackung='1 piece' WHERE __record=3118
muss man bedenken, dass Xbase++ die Verpackung nur auf der Länge vom Vergleichsstring prüft, also auch '1 piece xyz' wahr wäre. Bei SQL nicht !

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Mi, 11. Jul 2012 8:49
von Martin Altmann
Nun,
SET ist eine Zuweisung - kein Vergleich.

Viele Grüße,
Martin

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Mi, 11. Jul 2012 8:52
von brandelh
Offensichtlich bin ich noch nicht ganz wach ;-)

Re: PostgreSQL "UPDATE " [erledig]

Verfasst: Mi, 11. Jul 2012 9:39
von georg
Hallo, Jimmy -


viele Fragen, hoffentlich vergesse ich keine ...

Das ";" am Ende der Anweisung wird normalerweise nur im Interpreter des jeweiligen Servers verwendet, damit dieser erkennt, wann das Ende der Anweisung erreicht ist (man kann ja anstelle des Wordwrap am Ende der Zeile auch einfach ENTER drücken).

Eine WHERE Clause, die auch andere Dateien einschliesst, macht nur dann Sinn, wenn Dein Update nur dann erfolgen soll, wenn der JOIN zu der anderen/den anderen Tabellen erfolgreich ist.

Um Dein Beispiel aufzugreifen:

Code: Alles auswählen

ÄNDERE tabelle1, tabelle2 SETZE VerpackungsEinheit = 'One Piece" WENN tabelle1.Artikelnummer = 334 UND tabelle1.Artikelnummer = tabelle2.Artikelnummer
SQL ist in mancher Hinsicht ein "Sprachbaukasten", d.h. bestimmte Elemente werden miteinander kombiniert, wobei die Sprachdefinition nicht prüft, ob das Konstrukt Sinn macht.

Das UPDATE Statement erlaubt nur eine Tabelle, so dass Du Änderungen an zwei Tabellen in zwei Anweisungen packen musst.


Gruss,

Georg