Autor Beitrag
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Di 19.08.03 19:44 
Hi,

UGrohne und auch Lemmy haben mir gesagt, ich solle möglichst viele Stored Procedures benutzen. Mir geht es um ein Eingabeformular, wobei 5 Tables aktualisiert werden. Aber da werden doch gar keine Daten abgerufen, sondern eingefügt ? Bzw. wird ein Teil gelesen, das wichtigste ist aber das wegschreiben. Wie soll ich das am besten machen ? Das ganze soll auf einer Form passieren.

_________________
Gruß
Hansa
UGrohne
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Di 19.08.03 22:50 
Du erstellst einfach eine Stored Procedure à la:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
CREATE PROCEDURE update
(
 feld1 INTEGER,
 feld2 VARCHAR(20),
 ....
)
AS
BEGIN
 id1=gen_id(gen1,1);
 INSERT INTO tabelle1 VALUES(feld1,....);
 ....
 EXIT;
END

Diese rufst Du dann einfach über
ausblenden Quelltext
1:
 EXECUTE PROCEDURE update(2,'feldwert2',.....);					

auf und das wars. Du kannst da soviel reinpacken, wie Du willst.
Du kannst auch mehrere Procedures nutzen und diese sich gegenseitig aufrufen lassen, auch kein Problem.

Die obige ist eine Executable Procedure, im Gegensatz zu Select-Prozeduren, die Daten zurückgeben. Da kommt vor dem AS noch der RETURNS-Block.

Auf der Form würde ich Dir vorschlagen, Bereiche zu definieren, die Tabellenweise gegliedert sind, z.B. (von meinem aktuellen projekt) eine Firmenadresse ist ein Block und der andere sind die Ansprechpartner. Diese solltest Du getrennt aktualisieren, damit Du, wenn sich beim einen nichts ändert, diesen Block nicht auch noch unnötig updatest.

Noch Fragen? Fragen!
hansa Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mi 20.08.03 10:28 
Habe jetzt mal eine stored procedure gebaut: Alle Rechnungsbeträge eines Jahres werden mit Hilfe einer "Select-Procedure" addiert etc.:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
BEGIN
 SELECT SUM(UMSATZMWST2), AVG (UMSATZMWST2), MAX (UMSATZMWST2)
  FROM RECKOPF8 WHERE EXTRACT(YEAR FROM RECHNDATUM) = :RECHNJAHR
   INTO :tot_budget, :avg_budget, : max_budget;
 SUSPEND;
END


Habe mich natürlich an entsprechenden Beispielen orientiert, funktionieren tut es aber mit meinen Originaldaten. *stolz* Jetzt stellt sich aber eine kurze Zwischenfrage : Ich muß eine leere DB ausliefern. Ist die Procedure da drin ?

Und die Hauptfrage @UGrohne: Was ist mit dem Generator in Deinem Beispiel. Benutzt Du keinen BI-Trigger ? Und gleich die nächste: Wie unterscheide ich am besten, ob ein Datensatz mit Insert neu eingefügt werden muß, oder ein vorhandener geupdatet werden soll :?: Das müßte die entsprechende SP wohl wissen.

_________________
Gruß
Hansa
Lemmy
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 792
Erhaltene Danke: 49

Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
BeitragVerfasst: Mi 20.08.03 10:41 
Hi,

ich bin zwar nicht UGrohne aber antworte trotzdem...


hansa hat folgendes geschrieben:
Ich muß eine leere DB ausliefern. Ist die Procedure da drin ?


Nur wenn Du sie mit Create Procedure erzeugt hast *gg*

hansa hat folgendes geschrieben:

Und die Hauptfrage @UGrohne: Was ist mit dem Generator in Deinem Beispiel. Benutzt Du keinen BI-Trigger ?


Ich benutze auch keine Trigger, sind mir nicht gut genug. Wenn ich in meiner Client-Anwendung die ID des eingefügten Datensatzes kennen muss, damit ich ihn nach dem einfügen gleich wieder in der Maske anzeigen lassen kann, dann bringt mir der Trigger rein gar nichts!! In einer SP kann ich die ID des eingefügten Datensatzes zurückgeben, oder ich verwende einfach die Generator-Eigenschaft der DataSet.

hansa hat folgendes geschrieben:
Und gleich die nächste: Wie unterscheide ich am besten, ob ein Datensatz mit Insert neu eingefügt werden muß, oder ein vorhandener geupdatet werden soll :?: Das müßte die entsprechende SP wohl wissen.


Lass den Datensatz von der SP doch einfach suchen..... Bei Deinem Bsp.: Willst Du die berechneten Werte in einer Tabelle GesamtRechnung abspeichern, dann lass einfach nach dem Jahr suchen:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
DECLARE VARIABLE Anzahl INTEGER;
BEGIN
  SELECT Count(*) From GesamtRechnung where  EXTRACT(YEAR FROM RECHNDATUM) = :RECHNJAHR INTO :Anzahl;
  IF (:Anzahl=0) then
  BEGIN
    INSERT INTO....
  END
  ELSE
  BEGIN
    UPDATE GesamtRechnung.....
  END;


So sollte es ungefähr hinhauen....

GRüße
Lemmy
hansa Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mi 20.08.03 11:26 
Wie, Lemmy ? Nix Urlaub :?: :mrgreen: Wie ich sehe, muß ich mich wieder etwas mehr mit SQL beschäftigen. Habe mir deshalb gestern mal ein Buch darüber gekauft. 8) Das mit :Anzahl kommt mir etwas kompliziert vor. *grübel* Aber mir fällt auch nichts besseres ein. Das Beispiel ist auch nicht so gut gewählt. Was ist in folgendem Fall zu tun: neuer Artikel, Lagerbestand deshalb auch nicht vorhanden. Jetzt könnte ich ja 2 Dinge tun: 1. leeren Datensatz Lagerbestand usw. anlegen, sofern ein neuer Artikel angelegt wird, dann wäre die Unterscheidung Insert/Update überflüssig 2. Für solche Fälle eine stored procedure, so ähnlich wie Lemmy das gemacht hat. Dann bräuchte ich für jede Tabelle wahrscheinlich alleine dafür eine SP.

Dies wiederum würde erklären, warum andere so viele SP brauchen. Das hat mich sowieso schon gewundert. Stop, es gibt noch eine Variante: In Delphi kann ich doch Dataset.IsEmpty
überprüfen. Also in diesem Fall jetzt SELECT * FROM LAGERBESTAND WHERE ID_ART = ???
Ist die Datenmenge leer dann eben ein insert. Wobei wir da wieder bei der Grundsatzfrage wären, ob die DB die Arbeit macht oder mein Programm. Aber, wie man sieht, da muß noch etwas Licht ins Dunkel. 8)

@Lemmy: das mit dem Trigger verstehe ich auch nicht richtig, was Du da meinst. Mit einem BI-Trigger erhalte ich doch sofort eine ID?

_________________
Gruß
Hansa
Lemmy
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 792
Erhaltene Danke: 49

Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
BeitragVerfasst: Mi 20.08.03 12:00 
hansa hat folgendes geschrieben:
Wie, Lemmy ? Nix Urlaub :?: :mrgreen:


Was, Hansa?? Was ist Urlaub??? :mrgreen:

hansa hat folgendes geschrieben:

Was ist in folgendem Fall zu tun: neuer Artikel, Lagerbestand deshalb auch nicht vorhanden. Jetzt könnte ich ja 2 Dinge tun: 1. leeren Datensatz Lagerbestand usw. anlegen, sofern ein neuer Artikel angelegt wird, dann wäre die Unterscheidung Insert/Update überflüssig 2. Für solche Fälle eine stored procedure, so ähnlich wie Lemmy das gemacht hat. Dann bräuchte ich für jede Tabelle wahrscheinlich alleine dafür eine SP.


Ohne Deine DB-Struktur zu kennen kann ich da gerade recht wenig dazu beitragen....

hansa hat folgendes geschrieben:

Dies wiederum würde erklären, warum andere so viele SP brauchen. Das hat mich sowieso schon gewundert. Stop, es gibt noch eine Variante: In Delphi kann ich doch Dataset.IsEmpty
überprüfen. Also in diesem Fall jetzt SELECT * FROM LAGERBESTAND WHERE ID_ART = ???
Ist die Datenmenge leer dann eben ein insert. Wobei wir da wieder bei der Grundsatzfrage wären, ob die DB die Arbeit macht oder mein Programm. Aber, wie man sieht, da muß noch etwas Licht ins Dunkel. 8)


Klar, Du könntest auch den Anwendern Schieferplatten, nen Hammer und nen Meisel in die Hand drücken, dann werden die nie Probleme mit Windows haben....

Im Ernst: Wenn Du ne halbwegs schnelle und wartbare Applikation haben willst, sind StoredProcedures unverzichtbar. Auch ich habe am Anfang ohne die SP gearbeitet, aber mich nach und nach ihnen genähert und immer mehr gemacht. Versuche doch erst mal Dein Problem in der Client-Applikation zu lösen. WEnn Du das geschafft hast, kannst Du über ne Implementierung als SP nachdenken. SP's ganz theoretisch durchzudenken macht IMHO wenig Sinn.


hansa hat folgendes geschrieben:

@Lemmy: das mit dem Trigger verstehe ich auch nicht richtig, was Du da meinst. Mit einem BI-Trigger erhalte ich doch sofort eine ID?


Wie verwendest DU den Trigger?? Doch so, dass Du nen Insert-Trigger erzeugst, der den Wert der ID abfragt, ist der NULL wird eine neue ID mit dem Generator erzeugt und zugewiesen. In diesem Zustand weiß aber die Client-Applikation nichts von dem Wert der ID! Wenn Du also die gerade eingefügten Datensatz nach dem Einfügen gleich anzeigen lassen willst, musst Du den irgendwie in der Datenbank wiederfinden. Genau da liegt das Problem! Wie willst Du den Datensatz eindeutig identifizieren???

Ich dagegen verwende in diesem Fall keinen Trigger sondern eine Insert-SP bzw. die Eigenschaft Generator der IBDataSet. Damit erhalte ich immer die ID des eingefügten DS zurück und kann diesen eindeutig identifizieren....

Grüße
Lemmy
hansa Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mi 20.08.03 12:13 
Lemmy, meinst Du etwa, ich soll meine ganzen Trigger wegschmeißen ? :cry: Habe im Moment 27 ? Tables und für jede einen Trigger. Was macht denn eine Insert-SP anders, als ein Trigger :?: Soll ich das wieder umbauen ?

_________________
Gruß
Hansa
UGrohne
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mi 20.08.03 12:47 
Mit der SP hast Du viel mehr Kontrollmöglichkeiten. Der Trigger von Dir wird ja nur aktiv, wenn Du einen Datensatz einfügst, dann generiert er eine neue ID und weist diese zu. Aber wenn Du diese ID in Deinem Prog brauchst, musst Du den Datensatz mit einer neuen Abfrage erst wieder suchen. Mit der SP kannst Du die ID wie der Trigger erzeugen und diese dann zurückgeben, das war der erste Grund für mich eine INSERT-SP zu schreiben.
Lemmy
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 792
Erhaltene Danke: 49

Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
BeitragVerfasst: Mi 20.08.03 12:53 
Hi Hansa,

ganz einfach: Die Insert-SP gibt die ID zurück, d.h. ich weiß im Client den Wert der ID. Das funktioniert im Trigger nicht...
Wenn Du diese Möglichkeit (Anzeige des gerade eingegebenen DS) nicht brauchst, dann musst Du auch nicht zwangsläufig was umstellen.... Kommt halt immer darauf an...

Grüße
Lemmy
hansa Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mi 20.08.03 13:24 
Ihr wißt doch, daß ich dumm bin. :nixweiss: Also müßt ihr mir das erklären. :lol: Das gilt doch wohl nur für neue Datensätze ? Meint Ihr, ich solle im Fall der Fälle die ID als Output-Parameter irgendwie übergeben oder wie ? Und was passiert in einem Netztwerk, wenn ich das ganze mit dem Trigger mache ? Dann merkt doch nur das Programm nichts davon, oder die anderen WS auch nicht :?:

_________________
Gruß
Hansa
Lemmy
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 792
Erhaltene Danke: 49

Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
BeitragVerfasst: Mi 20.08.03 14:16 
Nein Hansa, du bist nicht dumm....
Klar gilt das nur für neue Datensätze, Dein Trigger doch auch und ja, die neue ID wird bei einer Insert-Sp als Output Parameter zurückgegeben. Es spielt dabei keine Rolle, ob es sich um ne EinzelplatzAppl oder NetzwerkAppl handelt.
hansa Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mi 20.08.03 17:22 
Moment. Feuere ich den Triger ab, ist dann der Datensatz nicht in der DB drin ? Ist es nicht eher so, daß ich den an der Workstation, wo das passiert nicht mitkriege, die anderen aber schon :?:

_________________
Gruß
Hansa
Lemmy
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 792
Erhaltene Danke: 49

Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
BeitragVerfasst: Do 21.08.03 07:32 
Guten Morgen Hansa,

es geht hier rein um die ID. Wenn Dein Insert-Trigger feuert ist der Datensatz in der DB drin, wie soll denn der Trigger sonst feuern??? Das Prob ist dass der Trigger die ID nicht zurückgeben kann, eine SP schon. Es kommt aber immer darauf an, was Du machst. Wenn es nicht wichtig ist, die ID im Clientprogramm zu kennen, brauchst Du dir darüber auch keine Gedanken machen....

GRüße
Lemmy

P.S.: Die PN schaue ich mir später genauer an...