Zum Inhalt springen

innerhalb trigger wert aus tabellenspalte in variable schreiben?


pel

Empfohlene Beiträge

Ein DECLARE ist weder in einer Prozedur noch in einer Funktion erlaubt. Das Schlüsselwort existitiert in Tiggern und anonymen PL/SQL Blöcken.

Dim

warum meckert der compiler aber, wenn untenstehends declare von mir entfernt wird? Es ist eine Prozedur sollte doch laut dir kein declare enthalten?

CREATE OR REPLACE PROCEDURE COLLECTIONTEST AS

BEGIN


 declare  

 TYPE MaTab is table of Mitarbeiter%ROWTYPE index by binary_integer;

 MaSatz MaTab;

 Begin


   -- ///////// Spaltenwerte in eine Collections einlesen /////////////

   select * into MaSatz(1) from mitarbeiter where ma_nr = 1;

   dbms_output.put_line('Mitarbeiternummer: '||masatz(1).MA_NR||' Vorname: '||masatz(1).MA_Vorname||' Mitarbeitergehalt: '||masatz(1).MA_Gehalt); 


 End; 

END COLLECTIONTEST;
Beende ich ein Case mit
 end case;
kommt Fehler. nur mit
end;

kein fehler??

In wikipedia steht aber end case; so beenden :confused: irgendwie scheint mir pl/sql noch in den Kinderschuhen zu stecken oder die leute blickens net...

quelle: http://de.wikipedia.org/wiki/PL/SQL#Simple_CASE

beides zu erlauben ist auch quark!

Bearbeitet von pel
Link zu diesem Kommentar
Auf anderen Seiten teilen

irgendwie scheint mir pl/sql noch in den Kinderschuhen zu stecken oder die leute blickens net...

Letzteres. Was ihr in der Schule beigebracht bekommt ist ja sowas von falsch, das es schon nicht mehr feierlich ist

warum meckert der compiler aber, wenn untenstehends declare von mir entfernt wird?

Du kannst in PL/SQL Blöcke inneinander schachteln. Das wird z.B. verwendet um im Falle einer Exception nicht sofort ans ende der Prozedur zu springen:


create procedure t is

begin

 ...

 --Hier beginnt ein eingebetteter Block

 begin 

 ...

 exception

  when ...

 end;

 ...

  --Hier beginnt ein eingebetteter Block

 begin 

 ...

 exception

  when ...

 end; --Hier endet er

...

exception when others then --Alle nicht behandelten Fehler werden hier behandelt

 dbms_output.put_line('Unbekannter Fehler aufgetreten: '||SQLERRM);

 raise;

end;

Damit hast Du zwei separate Blöcke mit einer eigenen Fehlerbehandlung. In Java wär das vergleichbar mit einem try-catch Block. Fügt man aber noch ein declare hinzu (ist ja erlaubt da es nicht zur Prozedur sondern zum eingebetteten Block gehört) wird das ganze eher vergleichbar mit einer Inneren Klasse. In java mag es Konstrukte geben in denen das sinnvoll sein mag, in PL/SQL gehört das in die Kategorie "schwer wartbarer Code" bzw. "denn sie wissen nicht was sie tun". Bei dir wäre also folgendes korrekt:
CREATE OR REPLACE PROCEDURE COLLECTIONTEST AS

 TYPE MaTab is table of Mitarbeiter%ROWTYPE index by binary_integer;

 MaSatz MaTab;

BEGIN


   -- ///////// Spaltenwerte in eine Collections einlesen /////////////

   select * into MaSatz(1) from mitarbeiter where ma_nr = 1;

   dbms_output.put_line('Mitarbeiternummer: '||masatz(1).MA_NR||' Vorname: '||masatz(1).MA_Vorname||' Mitarbeitergehalt: '||masatz(1).MA_Gehalt); 


 End; 

END COLLECTIONTEST;

In wikipedia steht aber end case; so beenden

Lass mal die wikipedia und schau lieber in der Doku nach:

Fundamentals of the PL/SQL Language

Dim

Link zu diesem Kommentar
Auf anderen Seiten teilen

CREATE OR REPLACE PROCEDURE COLLECTIONTEST AS


 TYPE MaTab is table of Mitarbeiter%ROWTYPE index by binary_integer;

 MaSatz MaTab;

 Begin 

   -- ///////// Spaltenwerte in eine Collections einlesen /////////////

   select * into MaSatz(1) from mitarbeiter where ma_nr = 1;

   dbms_output.put_line('Mitarbeiternummer: '||masatz(1).MA_NR||' Vorname: '||masatz(1).MA_Vorname||' Mitarbeitergehalt: '||masatz(1).MA_Gehalt); 


 End; 

END COLLECTIONTEST;
Fehler:
Error(12,1): PLS-00103: Fand das Symbol "END" 

??

Link zu diesem Kommentar
Auf anderen Seiten teilen

kennst du noch ein Programm sollte freeware sein, dass pl/sql code darstellt mit syntax highlighting, da ich meinen Code farbig ausdrucken möchte, um zu lernen :) ach vergiß die frage, ich installier einfach sql developer bei der Freundin daheim...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Musterlösung von Lehrerin:

create or replace PROCEDURE STUE14 AS

BEGIN

  declare 

      cursor c_Bestellung is select * from BestellungenUe14  where Lfr_code not in (select Lfr_code from LieferantenUe14) for update;


      B_Satz BestellungenUe14 %ROWTYPE;


      fehlercode number;

      fehlernachricht varchar2(255);


      lfr_not_found exception;

      falscherLfr_code BestellungenUe14.Lfr_code%TYPE; -- B_Satz.Lfr_code in exception nicht 

  								-- bekannt!

  Begin


      dbms_output.enable;

      if SQL%NOTFOUND then dbms_output.put_line('keine fehlerhaften Tupel in B-Tab.');

      else

        for B_Satz in c_Bestellung

        loop


            insert into FalscheBestellungenUe14 values (B_Satz.Bestellnr, B_Satz.Lfr_code, B_Satz.B_Datum, B_Satz.Betrag);

            delete BestellungenUe14 where current of c_Bestellung;

            falscherLfr_code:= B_Satz.Lfr_code;

            raise lfr_not_found;


        end loop;

      end if;

   commit;


  exception

      when NO_DATA_FOUND then dbms_output.put_line('keine fehlerhaften Tupel in Bestell-Tab.');

      when lfr_not_found then dbms_output.put_line('Lieferant: '||falscherLfr_code||' ex. nicht'); 

      when others        then fehlercode:= SQLCODE;

     fehlernachricht:= SQLERRM;


  end;
DDL code von Lehrerin:
  CREATE TABLE BESTELLUNGENUE14 

   (	"BESTELLNR" NUMBER(10,0), 

	"LFR_CODE" CHAR(3), 

	"B_DATUM" CHAR(8), 

	"BETRAG" NUMBER(7,2)

   ) ;


Insert into BESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (175,'004','19880227',395.51);

Insert into BESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (181,'009','19890306',577.22);

Insert into BESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (190,'014','19850313',659.84);

Insert into BESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (191,'013','19850313',1211.41);

Insert into BESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (200,'004','20040314',72);

Insert into BESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (201,'004','19850326',221.25);

Insert into BESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (202,'014','19850326',530.43);

Insert into BESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (203,'019','19850401',556.6);

Insert into BESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (205,'013','20010225',300);



  CREATE TABLE FALSCHEBESTELLUNGENUE14 

   (	"BESTELLNR" NUMBER(10,0) NOT NULL ENABLE, 

	"LFR_CODE" CHAR(3), 

	"B_DATUM" CHAR(8), 

	"BETRAG" NUMBER(7,2)

   ) ;

  ALTER TABLE FALSCHEBESTELLUNGENUE14 ADD CONSTRAINT "FALSCHEBESTELLUNGENUE18_PK" PRIMARY KEY ("BESTELLNR") ENABLE;


Insert into FALSCHEBESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (174,'003','20010225',117.5);

Insert into FALSCHEBESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (184,'022','19990306',240);

Insert into FALSCHEBESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (186,'020','19850311',414.05);

Insert into FALSCHEBESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (192,'035','20030313',317.52);

Insert into FALSCHEBESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (197,'035','19850314',928.27);

Insert into FALSCHEBESTELLUNGENUE14 (BESTELLNR,LFR_CODE,B_DATUM,BETRAG) values (204,'034','19850401',492.53);



  CREATE TABLE LIEFERANTENUE14 

   (	"LFR_CODE" CHAR(3) NOT NULL ENABLE, 

	"LFR_NAME" VARCHAR2(20), 

	"ADRESSE" VARCHAR2(25), 

	"WOHNORT" VARCHAR2(15)

   ) ;

  ALTER TABLE LIEFERANTENUE14 ADD CONSTRAINT "LIEFERANTENUE18_PK" PRIMARY KEY ("LFR_CODE") ENABLE;


Insert into LIEFERANTENUE14 (LFR_CODE,LFR_NAME,ADRESSE,WOHNORT) values ('004','HOVEN G.H.','SANDWEG 50','LINZ');

Insert into LIEFERANTENUE14 (LFR_CODE,LFR_NAME,ADRESSE,WOHNORT) values ('009','BAUMGARTEN R.','TANKSTRASSE 13','HANNOVER');

Insert into LIEFERANTENUE14 (LFR_CODE,LFR_NAME,ADRESSE,WOHNORT) values ('011','STRAUCH GMBH','BEERENWEG 1','LINZ');

Insert into LIEFERANTENUE14 (LFR_CODE,LFR_NAME,ADRESSE,WOHNORT) values ('013','SPITZMANN','HINTERGARTEN 9','AALEN');

Insert into LIEFERANTENUE14 (LFR_CODE,LFR_NAME,ADRESSE,WOHNORT) values ('014','DEZAIER L.J.','IM GRUND 101','LINZ');

Insert into LIEFERANTENUE14 (LFR_CODE,LFR_NAME,ADRESSE,WOHNORT) values ('019','SCHOENE F.A.','SOMMERSTR. 24','AALEN');
Compiliert OK, doch beim ausführen der Prozedur kommt dieser fehler:
Source does not have a runnable target.

Habe auch gegoogelt doch da steht was von Packages macht aber net wirklich sinn, vielleicht weißt du mehr mit deiner Masse ERahrung an pl/sql!? :uli

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also meine Meinung über eure Lehrerin was PL/SQL angeht wird immer schlechter echt. Man kann eigentlich nur raten es nicht so zu machen wie es hier gezeigt wird.

Da wär ja zum einen wieder der unnötig geschachtelte declare-begin-end block.

Dann diese bedingung hier:

if SQL%NOTFOUND then dbms_output.put_line('keine fehlerhaften Tupel in B-Tab.');
Ja ne ist klar. Welches SQL wurde denn bitte ausgeführt um überhaupt ein aussagekräftiges Ergebnis zu bekommen? Keines. Ist also ein ganz klarer Bug. Dann das Exception Handling. Wird ein fehlerhafter Satz gefunden, gibts einen Eintrag in eine Logtabelle, es wird etwas gelöscht und anschließend wird eine Exception geworfen, welche direkt in den EXCEPTION Block verzweigt. Und dann? Ich hab hier eine offene Transaktion. das Commit wird nämlich nicht ausgeführt. Wir hätten also Bug Nr.2 Ausserdem wärs doch schöner, wenn ich nicht beim ersten Fehler komplett rausspring und dann nochmal starten muss um den nächsten zu finden und so weiter und so fort. Bug Nr. 3 Im Exceptionblock gehts aber natlos weiter. Ein explizieter Cursor wirft keine NO_DATA_FOUND Exception. das wird hier aber erwartet. Bug Nr. 4 Im WHEN OTHERS Block wird die Fehlermeldung einer Variablen eines eines einbebetteten PL/SQL Blocks zugewiesen und das Programm anschließend beendet. Leider ist die innere Variable aber im äußeren Block nicht sichtbar und daher könnte die Fehlermeldung nicht ausgelesen werden (Bug Nr 5) noch ist ein abschließendes RAISE vorhanden, welches die Fehlermeldung weitergibt (Bug Nr.6).
DDL code von Lehrerin:
Ja da geht es munter weiter. Zum einen wird suggeriert, das man "" um die Spaltennamen braucht. Das ist nicht so. Es ist sogar gefährlich. Ist alles groß geschrieben passiert nichts. Legt man jetzt aber z.B. eine solche Tabelle an:
SQL> create table never_do_that("Spalte1" number);


Tabelle wurde erstellt.


SQL> select spalte1 from never_do_that;

select spalte1 from never_do_that

       *

FEHLER in Zeile 1:

ORA-00904: "SPALTE1": ungültiger Bezeichner



SQL> select "Spalte1" from never_do_that;


Es wurden keine Zeilen ausgewählt

es wurde also erreicht, dass der Spaltenname plötzlich Casesensitive angegeben werden muss!! Also bei DDL generell keine "" verwenden. Auch wenn manche Tools das so generieren bzw. Oracle das intern so umwandelt.

"BESTELLNR" NUMBER(10,0) NOT NULL ENABLE,

Das ENABLE ist unnötig, das NOT NULL ist, wenn man den später angelegten zweiten Constraint sieht auch unnötig. Eine PrimaryKey ist immer impliziert indiziert, unique und not null. Hier wurden zwei gleiche Constraints auf die Spalte gelegt - und es wird dementsprechend auch zweimal geprüft.

Zusammengefasst nochmal das wichtigste für dich als Einsteiger:

  • Verwende niemals PL/SQL wenn es es mit SQL geht. Und es geht sehr viel mit reinem SQL
  • Keine Programmlogik innerhalb eines Triggers (auch keine die aus einem Trigger heraus aufgerufen wird)
  • Ein WHEN OTHERS ohne abschließendes RAISE ist zu 99% ein Bug
  • Verwende geschachtelte BEGIN END Blöcke um die Fehlerbehandlung zu verfeinen. Aber verwende kein DECLARE
  • Diesen Link bookmarken: Oracle Database Online Documentation 10g Release 2 (10.2)

Dim

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...