Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi SL Update mit StoredProc (https://www.delphipraxis.net/186215-sl-update-mit-storedproc.html)

Walter Landwehr 14. Aug 2015 10:12

Datenbank: Firebird • Version: 2.5.4 • Zugriff über: IBO

SL Update mit StoredProc
 
Hallo,

geht so was:


Delphi-Quellcode:
update tbl_gebuehren set sortierung = (select result from SP_Sortstring('Ziffer'))
Der Befehl wird ausgeführt aber die Spalte Sortierung ist null.

mkinzler 14. Aug 2015 10:20

AW: SL Uodate mit StoreOroc
 
Liefert die SP auch ein Feld mit der Bezeichnung "result" zurück?
SUSPEND vergessen?

nahpets 14. Aug 2015 11:40

AW: SL Uodate mit StoreOroc
 
Hallo,

habe von FireBird keine Ahnung, bei den mir bekannten Datenbanken würde ich es in der Form machen:
Code:
update tbl_gebuehren set sortierung = SP_Sortstring(Ziffer);
'Ziffer' dürfte in Deinem Beispiel bedeuten, dass die SP_Sortstring aus der Zeichenfolge 'Ziffer' die Sortierung erstellt, also bei allen Datensätzen zum gleichen Ergebnis kommt. Du möchtest aber sicherlich die Sortierung aus dem Inhalt der Spalte Ziffer gebildet bekommen.

p80286 14. Aug 2015 12:01

AW: SL Uodate mit StoreOroc
 
Ja das kann funktionieren, aber deine SP scheint mir ein wenig unangepasst zu sein.
Normal wäre mindestens ein (individueller) Eingabewert, wenn 'Ziffer' genutzt wird um Zufallszahlen zu generieren sollte es reichen. Wird denn überhaupt ein Wert zurück gegeben?

Aber warum so, die SP kann den Update doch selbst durchführen!?

Gruß
K-H

nahpets 14. Aug 2015 12:28

AW: SL Uodate mit StoreOroc
 
Zitat:

Zitat von p80286 (Beitrag 1312133)
Ja das kann funktionieren, aber deine SP scheint mir ein wenig unangepasst zu sein.
Normal wäre mindestens ein (individueller) Eingabewert, wenn 'Ziffer' genutzt wird um Zufallszahlen zu generieren sollte es reichen. Wird denn überhaupt ein Wert zurück gegeben?

Aber warum so, die SP kann den Update doch selbst durchführen!?

Gruß
K-H

Ein Wert wird hier zurückgegeben.

Wenn die SP das Update selbst ausführt, geht es aber nur nach dem Motto: "Alles oder nichts", also für die gesamte Tabelle. Dies ist bei der erstmaligen Befüllung der Spalte Sortierung sicherlich sinnvoll. Bei allen später hinzukommenden oder geänderten Datensätzen aber nicht, da sollte man die SP lieber in einen entsprechenden Datenbanktrigger legen, der nur bei Änderungen der Spalte Ziffer für eine Neubefüllung der Spalte Sortierung, des konkret betroffenen Datensatzes, sorgt.

p80286 14. Aug 2015 12:35

AW: SL Update mit StoredProc
 
Wenn ich mich nicht verlesen habe, dann liefert die SP von DataSpider für 'Ziffer' NULL. Für '1Ziffer' sieht das schon ganz anders aus.

Gruß
K-H

dataspider 14. Aug 2015 12:36

AW: SL Update mit StoredProc
 
Hi,

die SP berücksichtigt nicht, dass es auch Werte ohne Zahl gibt.

Du musst das Ende der SP noch mal ändern:

Code:
  ...
  if (coalesce(:temp, '') <> '') then
  begin
    -- Zahl vor Punkt auffüllen
    pos = position('.', :temp);
    if (:pos = 0) then
      result = lpad(:temp, 10, '0')||'.'||lpad('0', 10, '0');
    else
      result = lpad(substring(:temp from 1 for :pos -1), 10, '0')||'.'||
               lpad(substring(:temp from :pos + 1 for :laenge), 10, '0');
    result = :result||coalesce(:rest, '');
  end
  else
    Result = :rest;
  suspend;
die 2 Zeilen vor dem supend hinzufügen


Frank

Walter Landwehr 14. Aug 2015 12:44

AW: SL Update mit StoredProc
 
Hallo,

hier mal zum besseren Verständnis dir SP:

Delphi-Quellcode:
begin
   result = null;
   laenge = char_length(:wert);
   if (:laenge > 0) then
   begin
     pos = 1;
     while (:pos <= :laenge) do
     begin
       zeichen = substring(:wert from :pos for 1);
       if (:zeichen in ('0','1','2','3','4','5','6','7','8','9', '.')) then
         temp = coalesce(:temp, '')||:zeichen;
       else
       begin
         -- Rest hinten
         rest = substring(:wert from :pos for 10);
         break;
       end
       pos = :pos + 1;
     end
   end
   if (coalesce(:temp, '') <> '') then
   begin
     -- Zahl vor Punkt auffüllen
     pos = position('.', :temp);
     if (:pos = 0) then
       result = lpad(:temp, 10, '0')||'.'||lpad('0', 10, '0');
     else
       result = lpad(substring(:temp from 1 for :pos -1), 10, '0')||'.'||
                lpad(substring(:temp from :pos + 1 for :laenge), 10, '0');
     result = :result||coalesce(:rest, '');
   end
   suspend;
 end
Ich möchte einmalig alle Datensätze das Feld Sortierung füllen.

Später wir beim Ändern oder Neuanlegen eines Datensatzes ein Trigger benutzt.

p80286 14. Aug 2015 12:50

AW: SL Update mit StoredProc
 
Nicht daß es untergeht:

Zitat:

Zitat von dataspider (Beitrag 1312137)
Hi,

die SP berücksichtigt nicht, dass es auch Werte ohne Zahl gibt.

Du musst das Ende der SP noch mal ändern:

Code:
  ...
  if (coalesce(:temp, '') <> '') then
  begin
    -- Zahl vor Punkt auffüllen
    pos = position('.', :temp);
    if (:pos = 0) then
      result = lpad(:temp, 10, '0')||'.'||lpad('0', 10, '0');
    else
      result = lpad(substring(:temp from 1 for :pos -1), 10, '0')||'.'||
               lpad(substring(:temp from :pos + 1 for :laenge), 10, '0');
    result = :result||coalesce(:rest, '');
  end
  else
    Result = :rest;
  suspend;
die 2 Zeilen vor dem supend hinzufügen


Frank


nahpets 14. Aug 2015 12:52

AW: SL Update mit StoredProc
 
Zitat:

Zitat von p80286 (Beitrag 1312136)
Wenn ich mich nicht verlesen habe, dann liefert die SP von DataSpider für 'Ziffer' NULL. Für '1Ziffer' sieht das schon ganz anders aus.

Gruß
K-H

Das mag ja durchaus so sein, aber mir erscheint ein Aufruf in der Form
Code:
update tbl_gebuehren set sortierung = (select result from SP_Sortstring('Ziffer'))
wenig sinnvoll, da hier für alle Datensätze der Tabelle die Sortierung anhand der konstanten Zeichenfolge 'Ziffer' ermittelt wird und nicht anhand des Inhaltes der Spalte Ziffer. Bei '1Ziffer' mag also durchaus was anderes herauskommen, als bei 'Ziffer', aber es wird für alle Datensätze der Tabelle der gleiche Wert sein, Null wird also für alle Datensätze durch einen anderen, aber immer gleichen Wert, ersetzt.

Oder ist die Funktionalität von Firebird so anders, dass bei SP_Sortstring('Ziffer') hier tatsächlich der Inhalt der Spalte Ziffer genutzt wird?
Dies würde mich doch sehr wundern.

Walter Landwehr 14. Aug 2015 12:53

AW: SL Update mit StoredProc
 
Hi Frank,

habe die Zeilen eingefügt.

nach Ausführung des SQL Befehls steht in Feld Sortierung aller Datensätze 'Ziffer'. ???

Walter Landwehr 14. Aug 2015 12:57

AW: SL Update mit StoredProc
 
OK K-H. Wie kann ich denn den Wert der Spalte Ziffer übergeben?

nahpets 14. Aug 2015 13:00

AW: SL Update mit StoredProc
 
Zitat:

Zitat von Walter Landwehr (Beitrag 1312141)
Hi Frank,

habe die Zeilen eingefügt.

nach Ausführung des SQL Befehls steht in Feld Sortierung aller Datensätze 'Ziffer'. ???

Das ist auch nicht anders zu erwarten, solange Du die konstante Zeichenfolge 'Zffer' an die Prozedur übergibst.
Zitat:

OK K-H. Wie kann ich denn den Wert der Spalte Ziffer übergeben?
Code:
update tbl_gebuehren set sortierung = (select result from SP_Sortstring('Ziffer'))
Nimm doch bitte mal die Kontraproduktiven ' vor und hinter Ziffer heraus, damit die Datenbank die Möglichkeit bekommt, den Inhalt der Spalte Ziffer zu verwenden.

Also so:
Code:
update tbl_gebuehren set sortierung = (select result from SP_Sortstring(Ziffer))

Walter Landwehr 14. Aug 2015 13:21

AW: SL Update mit StoredProc
 
OK,

das funktioniert soweit. Danke.

Nun muss ich noch rausfinden bei welchen Datensatz dieser Fehler kommt.

Arithmetic overflow or division by zero has occurred.
arithmetic exception, numeric overflow, or string truncation.
string right truncation.
At procedure 'SP_SORTSTRING' line: 46, col: 2.

dataspider 15. Aug 2015 08:32

AW: SL Update mit StoredProc
 
Zitat:

Zitat von Walter Landwehr (Beitrag 1312144)
OK,

das funktioniert soweit. Danke.

Nun muss ich noch rausfinden bei welchen Datensatz dieser Fehler kommt.

Arithmetic overflow or division by zero has occurred.
arithmetic exception, numeric overflow, or string truncation.
string right truncation.
At procedure 'SP_SORTSTRING' line: 46, col: 2.

Walter,

deshalb wies ich dich bereits darauf hin, dass du die Länge der Varchar' s überprüfen sollst.
Setz doch mal alle VARCHAR auf 100:

Code:
create or alter procedure sp_sortstring (
    wert varchar(100))
returns (
    result varchar(100))
as
declare variable laenge smallint;
declare variable pos smallint;
declare variable zeichen char(1);
declare variable temp varchar(100);
declare variable rest varchar(100);
...
dann wird der Fehler sicher weg sein.


Frank

hoika 15. Aug 2015 08:33

AW: SL Update mit StoredProc
 
Hallo,
Welche Zeile ist das (bin mit dem iPad hier).

Eine genaue Beschreibung wird es erst mit FB 3.0 geben.
Jetzt hilft hier nur, Ausgaben in eine Log-Tabelle zu schreiben.
Dort steht dann der letzte erfolgreiche gelesene String drin,
der nächste ist das Problemkind.

Woher kennt mein Vorredner die ganze SP???


Heiko

TBx 15. Aug 2015 08:53

AW: SL Update mit StoredProc
 
Er hat sie geschrieben :-)

dataspider 15. Aug 2015 10:28

AW: SL Update mit StoredProc
 
Zitat:

Zitat von hoika (Beitrag 1312168)
Hallo,
Welche Zeile ist das (bin mit dem iPad hier).

Eine genaue Beschreibung wird es erst mit FB 3.0 geben.
Jetzt hilft hier nur, Ausgaben in eine Log-Tabelle zu schreiben.
Dort steht dann der letzte erfolgreiche gelesene String drin,
der nächste ist das Problemkind.

Woher kennt mein Vorredner die ganze SP???


Heiko

Hier noch mal die komplette SP mit längeren VARCHAR Feldern:

Code:
create or alter procedure sp_sortstring (
    wert varchar(100))
returns (
    result varchar(100))
as
declare variable laenge smallint;
declare variable pos smallint;
declare variable zeichen char(1);
declare variable temp varchar(100);
declare variable rest varchar(100);
begin
  result = null;
  laenge = char_length(:wert);
  if (:laenge > 0) then
  begin
    pos = 1;
    while (:pos <= :laenge) do
    begin
      zeichen = substring(:wert from :pos for 1);
      if (:zeichen in ('0','1','2','3','4','5','6','7','8','9', '.')) then
        temp = coalesce(:temp, '')||:zeichen;
      else
      begin
        -- Rest hinten
        rest = substring(:wert from :pos for 100);
        break;
      end
      pos = :pos + 1;
    end
  end
  if (coalesce(:temp, '') <> '') then
  begin
    -- Zahl vor Punkt auffüllen
    pos = position('.', :temp);
    if (:pos = 0) then
      result = lpad(:temp, 10, '0')||'.'||lpad('0', 10, '0');
    else
      result = lpad(substring(:temp from 1 for :pos -1), 10, '0')||'.'||
               lpad(substring(:temp from :pos + 1 for :laenge), 10, '0');
    result = :result||coalesce(:rest, '');
  end
  else
    Result = :rest;
  suspend;
end
Ich habe auch in der Zeile die Zeile
Code:
  rest = substring(:wert from :pos for 100);
von 10 auf 100 geändert.

Walter,
du solltest dennoch die SP überprüfen.
Ich fülle jetzt die numerischen Teile bis 10 Stellen auf.
aus 14.5 mache ich 0000000014.0000000005

Auch das funktioniert evtl. nur korrekt, wenn deine numerischen Teile nie länger als 10 sind.
(hab jetzt nicht im Kopf, ob lpad dann abschneidet, den Wert so lässt oder eine Exception wirft.

Wenn du z.B. einen Wert 123456789012.3a hättest - hättest du u.U. ein neues Problem.

Ich kann nur eine Vorlage liefern, nicht die fehlerfreie Lösung.

Frank

Walter Landwehr 16. Aug 2015 16:56

AW: SL Update mit StoredProc
 
Danke Frank, hatte den Datensatz der den Fehler verursacht hat gefunden und Korrigiert. Lag an solchen Ziffern 50G (9.3a).

Funktioniert alles bestens.

Danke nochmals für Deine Mühen.

dataspider 17. Aug 2015 09:36

AW: SL Update mit StoredProc
 
Zitat:

Zitat von Walter Landwehr (Beitrag 1312354)
Danke Frank, hatte den Datensatz der den Fehler verursacht hat gefunden und Korrigiert. Lag an solchen Ziffern 50G (9.3a).

Do solltest dennoch die Variablen vergrößern.
Dein Beispiel liefert "0000000050.0000000000G (9.3a)."

Das sind 30, die Länge von Result. Das ist arg grenzwertig.
Setz die Varchars hoch, wenn du es noch nicht gemacht hast.

Frank


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

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