Bestands-Daten für die Verwendung in einem Unique-Index anpassen.

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Hallo zusammen,

Ich habe eine Tabelle mit einer Spalte, auf die künftig ein Unique-Index angewendet werden soll.

Bei einigen Kunden sind die Bestands-Daten dafür aber nicht geeignet, weil es vereinzelt Dubletten in den Daten-Sätzen gibt.

Um diese Bestands-Daten für einen Unique-Index tauglich zu machen, hänge ich bei den Dubletten einfach die ID des Datensatzes dran. Das funktioniert auch prima.

Code: Alles auswählen

$Select = "SELECT 
                  ID,
                  MusterSpalte
          FROM
                  MusterTabelle
          WHERE
                  ID > 0
          ORDER BY
                  MusterSpalte ASC;";

$Pointer        = 11;
$Db['Syntax']   = "PDO";
$Db['DataBase'] = "Labor.FDB";

require("DB.php");

$Vorher = "";
while ($Record = DB_FetchAssoc_Upper($Pointer, $Db['Syntax'])) {

       if ($Record["MusterSpalte"] == $Vorher){

           $Update = "UPDATE 
                            MusterTabelle
                      SET
                            MusterSpalte = '".$Record["MusterSpalte"]." ".$Record["ID"]."'
                      WHERE
                            ID = '".$Record["ID"]."';";

           require("DB.php");

       }
       $Vorher = $Record["MusterSpalte"];
}
Allerdings braucht das bei vielen Daten-Sätzen narürlich sehr lange,
weil es über das Client-Script mit entsprechendem Traffic zum Browser läuft.

Kann man diese Aufgabe auch rein über FireBird-Statements lösen und somit
server-seitig viel schneller erledigt wird ?

Mein Freund "Google" hat mir kein geeignetes Beispiel ausgespuckt, vielleicht auch, weil
mir dazu nicht die geeigneten Suchworte eingefallen sind.

Danke und viele Grüße
bfuerchau
Beiträge: 546
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

"Execute Block" wäre da wohl das geeignete.
In dem kannst du ganze Scripte durchalufen lassen.
Somit kannst du da Selects und Updates machen sowie Variablen deklarieren und verwenden.
Nicht zu vergessen, das Ganze in eine Transaktion zu verpacken.

https://firebirdsql.org/refdocs/langref ... block.html

Eine SP zu erstellen um sie dann aufzurufen führt zum gleichen Ergebnis, ist aber etwas kompizierter.
Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Hallo bfuerchau,

danke für den Tipp.

Ich habe mal Folgendes gebastelt:

Code: Alles auswählen

EXECUTE BLOCK 

AS 
    DECLARE VARIABLE ID BI;
    DECLARE VARIABLE ZWECK  XTXT;
    DECLARE VARIABLE LAST_ZWECK XTXT = '';

BEGIN
FOR
SELECT 
        RID_BUCHUNGEN, 
        VERWENDUNGSZWECK 
FROM 
        BUCHUNGEN
WHERE
        RID_BUCHUNGEN  > 0
ORDER BY
        VERWENDUNGSZWECK ASC;
INTO    :ID, 
        :ZWECK
DO
IF ( :ZWECK == :LAST_ZWECK ) THEN
BEGIN
UPDATE
      BUCHUNGEN
SET 
      VERWENDUNGSZWECK = :ZWECK || ' R' || :ID
WHERE
      RID_BUCHUNGEN = :ID ;
END
:LAST_ZWECK = :ZWECK;
END
von dem ich glaube, dass es in die richtige Richtung geht.

Das Ding fliegt mir aber um die Ohren, mit der Fehler-Meldung:
SQLSTATE[HY000]: General error: -104 Dynamic SQL Error SQL error code = -104 Token unknown - line 19, column 29 ;
Kannst Du mir sagen, ob das überhaupt in die richtige Richtung geht und
wenn ja. was mein Fehler ist ?

Danke und viele Grüße
bfuerchau
Beiträge: 546
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Die Richtung ist korrekt, allerdings stimmt die Formatierung hier nicht um zu sehen, was in 19/29 denn steht.
Ggf. fehlt nur das eine oder andere Semikolon.
Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Guten Morgen,

ja, da habe ich auch immer so meine Probleme mit bei diesen Meldungen mit Positions-Angaben.

Kann man irgendwo nachlesen, wie FireBird die Lines und Column's zählt, damit ich das so formatieren kann, dass man mit den Angaben der Meldung auch was anfangen kann ?

Danke und viele Grüße
Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Ich habe jetzt einige Google-Stunden hinter mir und die Essens daraus

ist, dass der "EXECUTE BLOCK" aussehen müßte, wie folgt:

Code: Alles auswählen

EXECUTE BLOCK 
AS 
    DECLARE VARIABLE ID BI;
    DECLARE VARIABLE ZWECK XTXT;
    DECLARE VARIABLE LAST_ZWECK XTXT = '';

BEGIN
FOR SELECT 
            RID_BUCHUNGEN, 
            VERWENDUNGSZWECK 
    FROM 
            BUCHUNGEN
    WHERE
            RID_BUCHUNGEN > 0
    ORDER BY
            VERWENDUNGSZWECK ASC
    INTO    :ID, :ZWECK 
DO BEGIN
    IF ( ZWECK = LAST_ZWECK ) THEN
        UPDATE
              BUCHUNGEN
        SET 
              VERWENDUNGSZWECK = :ZWECK || ' R' || :ID
        WHERE
              RID_BUCHUNGEN = :ID ;
    END
    LAST_ZWECK = ZWECK;
END
Aber denkste, ich bekomme immer noch eine Fehler-Meldung:
General error: -104 Dynamic SQL Error SQL error code = -104 Token unknown - line 18, column 13 ?
Line 18 ist die "INTO"-Zeile und Column 13 der ":" vor ID, :ZWECK. Nach allem, was ich gelesen habe, sind die Doppelpunkte aber zwingend erforderlich.

Entferne ich die Doppelpunkte kommt die Fehler-Meldung:
General error: -901 Dynamic SQL Error SQL error code = -901 undefined message number
Womit ich noch weniger anfangen kann. Es ist echt zum verrückt werden.

Ich bin mit meinem Latein am Ende.

Kann mir irgendjemand das Ding so umbauen, dass es funktioniert ?

Herzlichen Dank und viele Grüße
Benutzeravatar
martin.koeditz
Beiträge: 478
Registriert: Sa 31. Mär 2018, 14:35

Moin,

die Doppelpunkte kennzeichnen Variablen. Im Grunde müsste das Ganze dann so aussehen:

Code: Alles auswählen

EXECUTE BLOCK 
AS 
    DECLARE VARIABLE ID BI;
    DECLARE VARIABLE ZWECK XTXT;
    DECLARE VARIABLE LAST_ZWECK XTXT = '';

BEGIN
FOR SELECT 
            RID_BUCHUNGEN, 
            VERWENDUNGSZWECK 
    FROM 
            BUCHUNGEN
    WHERE
            RID_BUCHUNGEN > 0
    ORDER BY
            VERWENDUNGSZWECK ASC
    INTO  :ID, :ZWECK 
DO BEGIN
    IF ( :ZWECK = :LAST_ZWECK ) THEN
        UPDATE
              BUCHUNGEN
        SET 
              VERWENDUNGSZWECK = :ZWECK || ' R' || :ID
        WHERE
              RID_BUCHUNGEN = :ID ;
    END
    :LAST_ZWECK = :ZWECK;
END
Viele Editoren benötigen noch einen passenden Terminator. Dann sieht es so aus:

Code: Alles auswählen

set term ^;

EXECUTE BLOCK 
AS 
    DECLARE VARIABLE ID BI;
    DECLARE VARIABLE ZWECK XTXT;
    DECLARE VARIABLE LAST_ZWECK XTXT = '';

BEGIN
FOR SELECT 
            RID_BUCHUNGEN, 
            VERWENDUNGSZWECK 
    FROM 
            BUCHUNGEN
    WHERE
            RID_BUCHUNGEN > 0
    ORDER BY
            VERWENDUNGSZWECK ASC
    INTO  :ID, :ZWECK 
DO BEGIN
    IF ( :ZWECK = :LAST_ZWECK ) THEN
        UPDATE
              BUCHUNGEN
        SET 
              VERWENDUNGSZWECK = :ZWECK || ' R' || :ID
        WHERE
              RID_BUCHUNGEN = :ID ;
    END
    :LAST_ZWECK = :ZWECK;
END^

set term; ^
Prüfe das bitte mal.

Gruß
Martin
Martin Köditz
it & synergy GmbH
bfuerchau
Beiträge: 546
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Bei .Net mit Commandobjekten ist dies nicht erforderlich.
Ggf. wird man etwas schneller fündig, wenn man alle \n entfernt so dass es nur noch 1 Zeile gibt, dann sollte die Position der Meldung besser passen.
Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Hallo Martin,

danke für die beiden Vorschläge. Leider klappen auch die nicht.

1. Fehler-Grund: >SQLSTATE[HY000]: General error: -104 Dynamic SQL Error SQL error code = -104 Token unknown - line 18, column 11 ?

2. Fehler-Grund: >SQLSTATE[HY000]: General error: -104 Dynamic SQL Error SQL error code = -104 Token unknown - line 2, column 5 term

Bei 1. ist es wieder der Doppel-Punkt und bei 2. meckert er über "term"

Ich verstehe es einfach nicht.
Hamburgo
Beiträge: 125
Registriert: Di 28. Mai 2019, 17:28

Hallo bfuerchau,

auch Deinen Vorschlag habe ich ausprobiert und Martins 1. Vorschlag mal in eine Zeile gepackt.

Code: Alles auswählen

>EXECUTE BLOCK AS DECLARE VARIABLE ID BI; DECLARE VARIABLE ZWECK XTXT; DECLARE VARIABLE LAST_ZWECK XTXT = ''; BEGIN FOR SELECT RID_BUCHUNGEN, VERWENDUNGSZWECK FROM BUCHUNGEN WHERE RID_BUCHUNGEN > 0 ORDER BY VERWENDUNGSZWECK ASC INTO :ID, :ZWECK DO BEGIN IF ( :ZWECK = :LAST_ZWECK ) THEN UPDATE BUCHUNGEN SET VERWENDUNGSZWECK = :ZWECK || ' R' || :ID WHERE RID_BUCHUNGEN = :ID; END :LAST_ZWECK = :ZWECK; END<

(strlen: 404) (strpos ':' 232)

Fehler-Grund: >SQLSTATE[HY000]: General error: -104 Dynamic SQL Error SQL error code = -104 Token unknown - line 1, column 233 ?
Das Ganze ist 404 Zeichen lang und der "strpos" auf Doppel-Punkt gibt 232 zurück. Geht man davon aus, dass strpos bei 0 anfängt zu zählen meckert die Fehler-Meldung mit column 233 wohl weiternin den Doppel-Punkt an.

Es ist zum verrückt werden.
Antworten