Bitte sehr:
SQL-Code:
/* im ersten SQL-Skript: */
CREATE PROCEDURE Logbuch_Start
( Daten_Nr
INTEGER, Selektion_Nr
INTEGER, Formular_Nr
SMALLINT )
RETURNS ( neu_ID
INTEGER, Neuer_Monat BOOLEAN )
AS
BEGIN
EXIT;
END
/* in einem späteren SQL-Skript: */
ALTER PROCEDURE Logbuch_Start
( Daten_Nr
INTEGER, Selektion_Nr
INTEGER, Formular_Nr
SMALLINT )
RETURNS ( neu_ID
INTEGER, Neuer_Monat BOOLEAN )
AS
DECLARE VARIABLE Computer_Name
VARCHAR(35);
DECLARE VARIABLE Nutzer_Name
VARCHAR(35);
DECLARE VARIABLE Nutzer_Nr
INTEGER;
DECLARE VARIABLE b1 BOOLEAN;
DECLARE VARIABLE t1 TIME;
DECLARE VARIABLE d1 DATE;
DECLARE VARIABLE d2 DATE;
BEGIN
/* alle frueheren Eintraege, die nicht beendet wurden, werden
beim Programmstart mit dem Vermerk 'Programmabsturz?' versehen */
IF ( Formular_Nr
IS NULL )
THEN Formular_Nr = 0;
IF ( Formular_Nr = 0 )
THEN BEGIN
t1 = '
23:59:59';
d1 =
CURRENT_DATE;
UPDATE Logbuch
SET Ende = CAST( Ende
AS DATE ) + :t1,
Bemerkung = '
Programmabsturz?'
WHERE ( ( Start = Ende )
AND ( Ende < :d1 )
AND ( Bemerkung = '
' ) );
END
/* Nutzer-ID wird durch USER aus der Tabelle Nutzer geholt */
Nutzer_Name =
USER;
Nutzer_Nr =
NULL;
EXECUTE PROCEDURE ID_Suchen_Nutzer ( '
',
NULL, :Nutzer_Name )
RETURNING_VALUES :Nutzer_Nr, :Nutzer_Name;
/* sicherheitshalber ersatzweise auf 0 setzen */
IF ( ( Nutzer_Nr
IS NULL )
OR ( Nutzer_Nr < 0 ) )
THEN Nutzer_Nr = 0;
/* Computer-Name von Interbase holen */
Computer_Name =
NULL;
SELECT TMP$USER_HOST
FROM TMP$ATTACHMENTS
WHERE TMP$
USER =
USER
INTO :Computer_Name;
IF ( Computer_Name
IS NULL )
THEN Computer_Name = '
';
/* andere Angaben werden auf Standards gesetzt, sofern erforderlich */
IF ( Daten_Nr
IS NULL )
THEN Daten_Nr = 0;
IF ( Selektion_Nr
IS NULL )
THEN Selektion_Nr = 0;
neu_ID = GEN_ID( Logbuch_id, 1 );
INSERT INTO Logbuch ( ID, Nutzer_ID, Daten_ID, Selektion,
Computer, Formular, Start, Ende, Bemerkung )
Values ( :neu_ID, :Nutzer_Nr, :Daten_Nr, :Selektion_Nr,
:Computer_Name, :Formular_Nr,
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP, '
' );
/* Einstellungen aktualisieren */
Neuer_Monat =
False;
IF ( Formular_Nr = 0 )
THEN BEGIN
EXECUTE PROCEDURE Einstellungen_Computerstart
( Computer_Name, Nutzer_Name, neu_ID );
/* kontrolliere, ob ein neuer Monat begonnen hat und
folglich die monatlichen Anpassungen zu erledigen sind */
SELECT Datum1
FROM Einstellungen
WHERE Bezeichnung = '
Interna-DB'
INTO :d2;
IF ( d2 < d1 )
THEN Neuer_Monat =
True;
END
SUSPEND;
END
Wie früher bereits gesagt: Aus der IBConsole heraus durch
SELECT * FROM Logbuch_Start(0,0,0)
wird genau eine Zeile zurückgegeben.
Hilft diese Angabe? (Ich hoffe, dass es nicht nötig ist, auch die anderen Prozeduren und die Tabellen zu erläutern.) Jürgen
Nachtrag zu @Hansa
Zitat von
Hansa:
Inwiefern ist hier ... sichergestellt, daß die Datenmenge nur aus einem Element besteht ? :shock:
Siehe auch den vollständigen Code; 'Bezeichnung' ist PrimaryKey von Einstellungen.
Nachtrag 2 zu @Hansa
Zitat von
Hansa:
Öfter mal was neues : Erläuterung zu später gestellter Nachfrage wird vor diese gesetzt. Jaja, die Kausalität.
Ich habe den Eindruck, dass die Moderatoren sauer werden, wenn ein neuer Eintrag hinzugefügt wird, statt dass ein vorheriger Eintrag mit Edit geändert wird...
Zitat von
Hansa:
'Bezeichnung' ist PrimaryKey von Einstellungen. - Das ist doch dem primary Key alles egal. Du kriegst (siehe Fehlermeldung) eben definitiv NICHT nur ein Element zurück !
Das kann doch nicht sein (und ist in der IBConsole auch nicht so)! PrimaryKey ist automatisch unique. Wenn ich also
SELECT Datum1 FROM Einstellungen WHERE Bezeichnung = 'Interna-DB'
abfrage, gibt es definitiv nur den eindeutigen (= unique) Datensatz.
Nachtrag zu @Dataspider
Zitat von
dataspider:
Paramteter mismatch kommt von Formular_Nr -> Int32 statt Int16 (im ersten Beitrag richtig).
SELECT TMP$USER_HOST FROM TMP$ATTACHMENTS WHERE TMP$USER = USER INTO :Computer_Name;
Erst mal nur als Frage:
TMP$ATTACHMENTS erzeugt für jede Verbindung einen Datensatz.
Wenn sich der gleiche User 2 mal verbindet, liefert dann dein Select evtll 2 Records?
Frank
Au ja, beides muss ich prüfen: (1) Formular_Nr habe ich vielleicht im C#-Code bei einem Parameter falsch eingetragen. (2) Es ist denkbar, dass zu diesem Zeitpunkt eine Verbindung über IBConsole (zur Kontrolle) und eine durch die Anwendung (mit dem o.g. Problem) besteht; ich muss die Abfrage nach dem Computer_Name verfeinern.
Dann ist dies natürlich nicht in Ordnung. Aber kann es wirklich Auswirkung auf den Suspend-Befehl und die eigentliche Fehlermeldung haben?
Mit diesen Hinweisen komme ich wenigstens weiter. Jürgen
PS. Das ist eines meiner Probleme als Einzelkämpfer: Manchmal erkennt man solche Situationen nicht selbst, sondern muss darauf hingestoßen werden.