![]() |
Stored pocedure
hallo experten,
ich stehe mal wieder auf den schlauch, und lange ist es her ds ich etwas mit stored procedure gemacht habe, DB: ib Zugriff : IBSQL
SQL-Code:
folgende Datenaufbau
CREATE PROCEDURE HELPME (id Integer)
AS DECLARE VARIABLE LETZTEAENDERUNG TIMESTAMP; BEGIN SELECT LETZTEAENDERUNG FROM ART8 WHERE id = :id; IF LETZTEAENDERUNG <> 'NOW' THEN LETZTEAENDERUNG =: 'NOW' ELSE EXIT END ID : integer name : varchar Letzteaenderung :Timestamp schon beim execute Query kommt die Fehlermeldung Zitat:
raik edit : dicke Finger und kleine Tasten :mrgreen: |
Re: Stored pocedure
Hi Kiar!
In Ermangelung eines Interbase Servers (ich hab hier nur nen Oracle zum Spielen!) rate ich einfach mal, aber wenn das mit den Stored Procedures so geht wie in Oracle, dann hast Du schlicht und einfach zwei Semikoli vergessen (siehe unten). Hoffe das behebt das Problem. Viele Grüsse Frank
SQL-Code:
CREATE PROCEDURE HELPME (id Integer)
AS DECLARE VARIABLE LETZTEAENDERUNG TIMESTAMP; BEGIN SELECT LETZTEAENDERUNG FROM ART8 WHERE id = :id; IF LETZTEAENDERUNG <> 'NOW' THEN LETZTEAENDERUNG =: 'NOW'; <<<<<<< HIER ELSE EXIT; <<<<<< HIER AUCH END |
Re: Stored pocedure
Code:
[edit=MrSpock]Code Tags eingefügt. Mfg, MrSpock[/edit]
CREATE PROCEDURE HELPME (id Integer)
AS DECLARE VARIABLE LETZTEAENDERUNG TIMESTAMP; BEGIN SELECT LETZTEAENDERUNG FROM ART8 WHERE id = :id; IF LETZTEAENDERUNG <> 'NOW' THEN LETZTEAENDERUNG =: 'NOW'; <<<<<<< HIER //sollte so aussehen LETZTEAENDERUNG [b]:=[/b] 'NOW'; ELSE EXIT; END |
Re: Stored pocedure
hallo frank,
ich glaube der Interbase server tickt anders, jedenfalls, haben deine einwände 'zu mindestens bei meiner procedure' :mrgreen: nicht zum erfolg geführt. danke raik |
Re: Stored pocedure
Also ich meine wenn dein Zuweisungsoperator genau so im Quelltext steht kommt es unweigerlich zu einer Fehlermeldung!
|
Re: Stored pocedure
Hi Klabim :hi:
Herzlich willkommen in der DP :dp: Bitte formatiere fürs nächste mal deinen Code, für den ObjectPascal Teil gibt es oben den Butten "Delphi-Code", falls du SQL Statements posten willst nimm den "SQL" Button zuhilfe, damit kann man den Quellcode hier im Forum nämlich hervorragend formatieren. Viel Spass noch im Forum :zwinker: mfg phlux :hi: |
Re: Stored pocedure
hallo klabim :mrgreen:
das ist es auch nicht, ich habe jetzt die procedure
SQL-Code:
eingekreist und jetzt moniert er das set Term ^ ... ^
SQL-Code:
raik
SELECT LETZTEAENDERUNG FROM ART8 WHERE id = :id;<---- das letzte zeichen
|
Re: Stored pocedure
Hallo,
probier es doch mal so
SQL-Code:
Gruß
CREATE PROCEDURE HELPME (id Integer)
AS DECLARE VARIABLE LETZTEAENDERUNG TIMESTAMP; BEGIN SELECT LETZTEAENDERUNG FROM ART8 WHERE id = :id; IF LETZTEAENDERUNG <> 'NOW' THEN LETZTEAENDERUNG = 'NOW'; -- Ohne : ELSE EXIT; END Ken |
Re: Stored pocedure
Deine Procedure macht so gar nix. Du hast weder einen Ausgabeparameter definiert noch verändert Deine Prozedur irgendwelche Daten. Ich nehme mal an das Du die Variable LETZTEAENDERUNG zurückgeliefert haben möchtest. In diesem Fall sollte die Procedure etwa so aussehen:
SQL-Code:
Gruß,
SET TERM !!;
CREATE PROCEDURE HELPME ( P_ID INTEGER ) RETURNS ( LETZTEAENDERUNG TIMESTAMP ) AS BEGIN SELECT LETZTEAENDERUNG FROM ART8 WHERE ID = :P_ID INTO :LETZTEAENDERUNG; IF LETZTEAENDERUNG <> 'NOW' THEN LETZTEAENDERUNG = 'NOW'; SUSPEND; END !! Marcel |
Re: Stored pocedure
viel zu kompliziert :
SQL-Code:
Was mich nur wundert : derselbe Code in einem Trigger geht bei mir von Delphi aus nicht. :shock:
SET TERM ^;
CREATE PROCEDURE HELPME RETURNS (LETZTEAENDERUNG TIMESTAMP) AS begin LETZTEAENDERUNG = 'NOW'; suspend; end ^ |
Re: Stored pocedure
Zitat:
Gruß, Marcel |
Re: Stored pocedure
allerdings will es mir nicht gelingen, eine ID als Input-Parameter mitzugeben.
SQL-Code:
Da stimmt irgendwas mit der Syntax nicht. 8) Er beschwert sich über das Select.
ALTER PROCEDURE HELPME (
ID INTEGER) AS DECLARE VARIABLE L TIMESTAMP; SELECT LETZTEAENDERUNG FROM ART8 WHERE ID = :ID INTO :L; IF L <> 'NOW' THEN LETZTEAENDERUNG = 'NOW'; SUSPEND; [EDIT] so gehts :
SQL-Code:
Jetzt ist nur noch die Frage, wie man solch eine Prozedur Feld/Tabellen- unabhängig machen kann.
ALTER PROCEDURE HELPME (
ID INTEGER) RETURNS ( LETZTEAENDERUNG TIMESTAMP) AS DECLARE VARIABLE L TIMESTAMP; BEGIN SELECT LETZTEAENDERUNG FROM ART8 WHERE ID = :ID INTO :L; IF (L <> 'NOW') THEN LETZTEAENDERUNG = 'NOW'; SUSPEND; END; |
Re: Stored pocedure
hallo hansa,
vielleicht kann man, der procedure den Namen der tabelle mitgeben
SQL-Code:
und dann in der procedure einfach TbName aufrufenALTER PROCEDURE HELPME ( ID INTEGER, TABName Varchar(20)) AS
SQL-Code:
raik
SELECT LETZTEAENDERUNG FROM TABNAme WHERE
|
Re: Stored pocedure
hast du jetzt nen Interbase server? ... ich hab jetzt vielleicht was überlesen(nur auf topicanfang geschaut) allerdings ist das ne pottenzielle "Fehlerquelle" :mrgreen:
|
Re: Stored pocedure
und woher kommt TabName ? :mrgreen:
|
Re: Stored pocedure
Zitat:
SQL-Code:
Gruß,
CREATE PROCEDURE HELPME (
P_ID INTEGER, P_TABELLE VARCHAR(31), P_FELD VARCHAR(31) ) RETURNS ( LETZTEAENDERUNG TIMESTAMP ) AS DECLARE VARIABLE SQL VARCHAR(255); BEGIN SQL = 'select ' || P_FELD || ' from ' || P_TABELLE || ' where ID = ' || CAST(P_ID AS VARCHAR(15)); EXECUTE STATEMENT :SQL INTO :LETZTEAENDERUNG; IF (LETZTEAENDERUNG <> 'NOW') THEN LETZTEAENDERUNG = 'NOW'; SUSPEND; END; Marcel |
Re: Stored pocedure
Vorsichtshalber Firebird, aber eher dann 1.0.296 ? Wer weiß ? Zumindest will ich nicht etwas verwenden, das mit Borland-Interbase mit Sicherheit nicht mehr läuft. 8)
|
Re: Stored pocedure
Würde es nicht auch so (oder so ähnlich :P ) funktionieren?
Rüchkgabewert -> Function, oder ist der IB Dialekt so verschieden von PL/SQL?
SQL-Code:
CREATE OR REPLACE FUNCTION HelpMe(p_ID Integer
,p_Owner Varchar2 := Null -- optional parameter ,p_Tabelle Varchar2 ,p_Feld Varchar2) RETURN Timestamp IS LetzteAenderung Timestamp; TableIdent Varchar2(65); Begin If p_Owner Is not Null Then TableIdent := P_Owner || '.' || p_Tabelle; Else TableIdent := p_Tabelle; End If; EXECUTE IMMEDIATE 'SELECT ' || P_FELD || chr(10) || 'FROM ' || TableIdent || chr(10) || 'WHERE ID = :i_ID' INTO LetzteAenderung USING P_ID; RETURN LetzteAenderung; EXCEPTION When No_Data_Found Then -- Wenn nix da ist, braucht man auch keinen Fehler ;) RETURN Null; End; |
Re: Stored pocedure
hallo robert,
firebird 1.0 kennt kein EXECUTE Statement, marcel ist ja auch von firebird 1.5 ausgegangen |
Re: Stored pocedure
Zitat:
|
Re: Stored pocedure
Im Normalfall will man mit dem Wert arbeiten, wird nix gefunden, kannst du das Ergebnis gegen NULL prüfen.
Außerdem war Raiks Code genausowenig für den Produktiveinsatz gedacht, wie es meiner war. ;) |
Re: Stored pocedure
Zitat:
Ich habe ihm gesagt, er solle einen Trigger verwenden, der geht aber bei mir seltsamerweise auch nicht richtig. [BEGINN OT] Du setzt doch Ora wohl nicht im Kindergarten ein, oder ? [ENDE OT] :P |
Re: Stored pocedure
Ich dachte es sei mehr eine generelle Frage gewesen. :roll:
|
Re: Stored pocedure
was kiar vor hat ist folgendes : zu jedem Datensatz soll das Datum des erstmaligen Erstellens festgehalten werden und das Datum, wenn irgendeiner was ändert. Noch besser wäre es, so habe ich vorgeschlagen, auch noch die ändernde/anlegende Workstation mit zu speichern (für jeden Datensatz).
Das ist wohl schon (meiner Meinung nach) in einem BI/BU Trigger aufgehoben. Kiar meint aber eine Stored Procedure sei dafür besser. |
Re: Stored pocedure
Das klingt für mich nach Qualitätssicherung und ISO 9001 :arrow: Audit trial.
Jede Tabelle bekommt ein Feld EditUser und EditDateTime, die werden BU/BI gesetzt. Billige Lösung: Ein BU / BD Trigger, der eine Kopie des Datensatzes vor der Änderung in den Audit trial schreibt (bei der billigen Lösung wäre es eine Tabelle mit gleicher Struktur) In der "richtigen" Tabelle steht also der aktuelle Datensatz mit dem User, der ihn geändert/erzeugt hat, im Audit trial stehen alle Änderungen davor. Die aufwendigere Lösung wäre EIN Audit für alle Tabellen (, die ein Audit brauchen) pro Tabelle / Feld. Das wäre dann eine Tabelle, in der der Tabellenname (hier kann auch ein FK zur TabellenID in deinem Data Dictonary, falls vorhanden ;), rein), PK, FeldName (kann ebenfalls auf eine DataDict-Tabelle zeigen), alter Wert, vorheriger EditUser und EditDateTime hinterlegt werden. Wenn du die Tabelle nach Tabellenname partitionierst dürften die Abfragen darauf nicht langsam werden (die wird ewig lang werden!) |
Re: Stored pocedure
hallo robert,
genau auf deine letzte lösung sollte es herauslaufen. schön wie du das dargestellt hast :thuimb: raik |
Re: Stored pocedure
so ungefähr solls wohl sein. Aber das mit dem "Audit Trail" ist zuviel des guten, es geht erstmal darum, daß die Trigger/Procedures sauber laufen.
Da es um IB/FB geht, steht zudem ein BDR (Back Difference Record) zur Verfügung (leider sonst nirgends :wink:) , der die noch nicht committeten Operationen speichert. Wie der aber ausgewertet werden kann, weiß niemand. :mrgreen: Im Moment geht es lediglich darum, das Datum eines Inserts und das des letzten Updates festzuhalten. Am besten natürlich noch ein Delete. Und eben, wer das war. :gruebel: Für eine Art Logbuch bräuchte man im Prinzip nur eine Extra Tabelle, ungefähr so wie Robert gesagt hat : 4 Felder, Operationstyp (insert, update delete), Operations-Datum, User und irgendeinen zusammengebastelten string, um den DS im nachhinein zu indentifizieren. Im Moment besteht das Problem allerdings darin, daß bei mir der Trigger nicht richtig läuft und bei kiar die SP auch nicht. 8) Also : Anforderung ist, das Feld ANGELEGT bei einem INSERT mit dem aktuellen Timestamp zu belegen. Und bei jedem Update [EDIT] das Feld LETZTEAENDERUNG [ENDE EDIT], wobei vorerst das ältere Datum ruhig überschrieben werden kann unter dem Motto : "der letzte hat gewonnen" :lol: |
Re: Stored pocedure
Hallo,
Zitat:
Zitat:
Ich habe mit Oracle mal eine sehr schöne Audit-Trail Lösung im Rahmen meines Praktikums implemtiert. Für diesen Fall würde ich aber vorschlagen, in jede relevante Tabelle die folgenden vier felder einzufügen
SQL-Code:
und dann bei jedem entsprechenden Statement die felder created_by und modified_by/Modified_Date (<=CURRENT_TIME verwenden) zu übergeben. So eine Lösung habe ich für jede meiner Tabellen und die Anwender sinds zufrieden. :)
Created_date Timestamp Not Null,
Created_By Integer Not Null, -- oder auch String Modified_Date TimeStamp Not Null, Modified_by Integer Not Null Dann braucht man nur einen trigger pro tabelle, der das created_date auf die Systime des Servers setzt und gut ist. Keine extra procedure und sonstigen kram und auch keine extra tabelle - Zumindest nicht für ein rudimentäres "Trailing". Ein Audit Trail benötigt auf jeden Fall eine Extra-Tabelle und da ist es erst mit den generischen Trigger ab FB 1.5 wirklich schön zu implementieren. Wenn es noch mit nem Delete sein soll, ist es natürlich die sache.... Aber ohne geht das so ganz gut. ;) [edit] Zitat:
Habe jetzt gerade gelesen, daß kiar einen Audittrail haben will, und da ist es wie gesagt richtig schön erst mit FB 1.5 aber mit den anderen FBs/IBs natürlich auch kein Problem... [/edit] Gruß Ken |
Re: Stored pocedure
hallo ken,
hansa und ich philosophieren an dem gleichen thema, ich bin mit IB 6.0 und hansa mit FB 1.0 an die sache gegangen. im endeffect suchten wir eine allgemeingültige Variante. ich muss wohl auf FB 1.5 oder das thema knicken. raik |
Re: Stored pocedure
@CenBells
Dein Vorschlag wäre im endeffekt das, was ich als "billige Lösung" vorgeschlagen habe, nur das die Felder
SQL-Code:
sinnlos sind.
Created_date Timestamp Not Null,
Created_By Integer Not Null, -- oder auch String In der aktiven Tabelle steht der User & das Datum der letzten Änderung, im Audit wäre der Eintrag mit der kleinsten Audit ID zu dieser PK der Eintrag mit dem "Erzeuger". Dabei fällt mir auf: Auch das Audit bräuchte natürlich einen PK. |
Re: Stored pocedure
Hi Hansa,
Zitat:
tut nicht.... Es gibt aber in FB 1.5 (vielleicht auch IB 7.x?) die Möglichkeit innerhalb einer SP ein beliebiges Statement auszuführen (was allerdings den Sinn einer SP wieder in Frage stellt und zudem ein gewisses Sicherheitsrisiko in sich birgt!). Grüße Lemmy |
Re: Stored pocedure
Hi Lemmy,
gut, daß du auch was dazu sagst. Aber die Idee mit der SP kam von Kiar nicht von mir. :mrgreen: Was ist mit der Trigger-Lösung ? |
Re: Stored pocedure
Zitat:
Den "schönen, großen" Audit würde ich aber bevorzugen und dann natürlich mit neuer tabelle. @kiar: musst nicht zwingend auf FB1.5 wechseln. Es geht auch mit IB dann nur nicht so schön (generische Trigger...) [edit] ein o durch ein ö ersetzt Gruß Ken |
Re: Stored pocedure
@Ken: also doch Trigger ? Nur was meinst Du mit "generischen" Triggern ??
|
Re: Stored pocedure
HAllo Hansa,
klar geht das mit Triggern. Mit Generisch meine ich die Erweiterung der Syntax des FB, daß du jetzt einen Trigger für alle Vorgänge schreiben kannst und dann im Trigger fragst, ob man nun gerade ein insert, update oder delete durchführt. Dafür gibt es seit FB 1.5 die möglichkeit per if abfrage den modus festzustellen
SQL-Code:
Wie genau die Syntax für den Trigger header aussieht musst du in den Release notes mal nachlesen. Wahrscheinlich sowas wie
IF (updating) THEN BEGIN
... END ELSE IF (inserting) THEN...
SQL-Code:
Das mach die Arbeit halt ein bisserl schöner. Ein Trigger anstelle für drei. ;)
CREATE TRIGGER ...
ACTIVE BEFORE INSERT OR UPDATE ... Gruß Ken |
Re: Stored pocedure
ich versteht zwar nicht den sinn folgender zeile
IF (L <> 'NOW') THEN LETZTEAENDERUNG = 'NOW'; aber es geht ja hier um ein variables sql statement. Bei Firebird gibt es hierzu das maechtige feature 'execute statement', damit kann man sowas realisieren. Unter Interbase gibt es das meines wissens nicht (korrigiert mich wenn dem nicht so ist) Hier die Prozedure:
Code:
die systemvariablen now und today sind veraltet, man benutzt künftig besser current_timestamp bzw. current_date
CREATE PROCEDURE HELPME (
TABNAME VARCHAR(32), FIELDNAME VARCHAR(32), ID INTEGER) RETURNS ( LETZTEAENDERUNG TIMESTAMP) AS DECLARE VARIABLE SQL VARCHAR(512); DECLARE VARIABLE L TIMESTAMP; BEGIN EXECUTE STATEMENT 'SELECT ' || FIELDNAME || ' FROM ' || TABNAME || ' WHERE ID = ' || :ID INTO :L; IF (L <> current_timestamp) THEN LETZTEAENDERUNG = current_timestamp; SUSPEND; END [SORRY WAR ZU SCHNELL UND HABE DEN THREAD NICHT BIS ANS ENDE GELESEN; WAR JA ALLES SCHON BEKANNT BIS AUF DIE SACCHE MIT CURRENT_TIMESTAMP] |
Re: Stored pocedure
hallo dephideveloper,
execute Statement geht unter Firebird 1.0 auch nicht, marcel hatte sich darüber schon ausgelassen raik |
Re: Stored pocedure
Hallo all,
mit der Stored procedure wurde erstmal geknickt. interesse meinerseits ist aber da . werde mich mal mit audit trail befassen. habe auch schon einen guten ansatz erhalten. dank dem Spender :mrgreen: es wurde mit BI und AU Triggern realisiert und scheint zu laufen. danke raik |
Re: Stored pocedure
Warum AU?
Dann hast du doch keinen Zugriff mehr auf den ":New Record". Im Endeffekt wäre es bei der von dir gewählten Lösung nix weiter als das:
SQL-Code:
CREATE Table Robert_G.SENT_QUERIES_Audit
(PK_SENT_QUERIES_Aud Integer -- Zusätzliche PK_Spalte ,PROJECT_NO NUMBER(22) ,SUBJECT_ID NUMBER(22) ,SUBJID VARCHAR2(80) ,ERROR_ID NUMBER(22) ,SENT_TO_MONITOR VARCHAR2(60) ,SENT_DATE VARCHAR2(200) ,BACK VARCHAR2(500) ,BACK_DATE VARCHAR2(20))
SQL-Code:
-- Prim Key auf diese Spalte
ALTER Table Robert_G.SENT_QUERIES_audit ADD Primary Key(PK_SENT_QUERIES_Aud) Using Index
SQL-Code:
-- Sequence für den Audit PK
CREATE Sequence Robert_G.SENT_QUERIES_Aud_Seq
SQL-Code:
-- Sequence für den Audit PK
CREATE Trigger Robert_G.SENT_QUERIES_Aud_PK_Trig Before INSERT ON Robert_G.SENT_QUERIES_Audit FOR EACH ROW DECLARE NewID Integer; BEGIN SELECT Robert_G.SENT_QUERIES_Aud_Seq.NextVal INTO NewID FROM Dual; :New.PK_SENT_QUERIES_Aud := NewID; END;
SQL-Code:
Falls du den Code zu IB übersetzen konntest, dürfte er dir das für alle Tabellen des angegeben Users machen. (Audit tabelle & Co erzeugen)
CREATE Trigger Robert_G.SENT_QUERIES_Aud_Trig
Before INSERT Or Update ON Robert_G.SENT_QUERIES FOR EACH ROW BEGIN -- Die 2 Zeilen klappen nur mit einem BU Trigger :New.EditDate := SysDate; :New.EditUser := User; If UPDATING Then INSERT INTO Robert_G.SENT_QUERIES_Audit VALUES ( null ,:Old.PROJECT_NO ,:Old.SUBJECT_ID ,:Old.SUBJID ,:Old.ERROR_ID ,:Old.SENT_TO_MONITOR ,:Old.SENT_DATE ,:Old.BACK ,:Old.BACK_DATE); End If; END; Das da oben wurde aus einer Tabellenleiche von vorgestern, die noch in meinem User lag, erzeugt. |
Re: Stored pocedure
Doch doch, Robert. Die Trigger gehen schon so, wie Kiar gesagt hat. :shock: Und das ganze auch noch in einem Audit aufzuzeichnen ist kein Problem mehr.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:39 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