Announcement

Collapse
No announcement yet.

für PL/SQL-Profis: Variable über Variable initialisieren

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • für PL/SQL-Profis: Variable über Variable initialisieren

    hallo zusammen,


    folgendes prob:
    create procedure MY_PROCEDURE
    IS
    v_record MY_TABLE%rowtype; -- MY_TABLE hat 84 Spalten

    CURSOR cur_wert
    IS
    select COLUMN_NAME
    from all_tab_COLUMNS
    WHERE TABLE_NAME = 'MY_TABLE'
    AND OWNER = 'SCOTT'
    ORDER BY COLUMN_ID;

    v_return_wert number;
    begin

    for rec in cur_wert
    loop

    v_return wert := fremdes_plsql_package.start(rec.COLUMN_NAME);

    */ und hier kommt jetzt das prob.
    der inhalt von v_return_wert soll nun der richtigen spalte in v_record
    zugeordnet werden.
    unter Oracle-Forms gibt es Functions hierfür. NAME_IN() und COPY()
    also so in der art stelle ich mir das vor:
    /*
    v_record.||rec.COLUMN_NAME := v_return_wert;
    -- diese syntax geht nicht, weis ich auch. will nur verdeutlichen welche
    -- lösung ich anstrebe. will also nicht HART-codieren

    End Loop;

    insert into andere_tabelle .....v_record;

    end;

    hat jemand eine idee?

    danke!

  • #2
    So ganz steig ich da nicht durch. Vom Code mal abgesehen, was möchtest Du denn fachlich machen?

    Dim
    Zitat Tom Kyte:
    I have a simple philosophy when it comes to the Oracle Database: you can treat it as a black box and just stick data into it, or you can understand how it works and exploit it as a powerful computing environment.

    Comment


    • #3
      gut, fange mal vorn an!

      ich habe ein schnittstellen-schema.
      dort liegen diverse IN und OUT-Tabellen.

      die Tabellen-Namen entsprechen immer der Applikation für die sie bestimmt sind.
      die Spalten-Namen entsprechen immer den Parametern die eine Applikation erwartet bzw. zurück liefert.

      ich habe nun eine applikation namens
      Function APPL1(IN_zuberechnender_wert IN VARCHAR2) Return NUMBER.
      diese berechnet diverse werte(bestimmt durch den parameter) und liefert das ergebnis zurück.
      die Return-Values werden dann von mir in der entsprechenden IN-Tabelle in der dazugehörigen Spalte gespeichert.

      Und da liegt genau die Krux!

      ich laufe mit einem loop über die tabellenspalten der Out-Tabelle.
      übergebe den Spaltennamen als Parameter an APPL1.
      und möchte nun den rückgabewert in die korrespondierende IN-Tabellen-Spalte ablegen.

      also habe ich mir eine rowtype-variable erstellt auf basis meiner IN-Tabelle.
      nenn wir sie v_IN_Rec IN_APPL1%Rowtype.

      und nun möchte ich das Returnvalue von APPL1 der korrespondierenden Spalte in der Rowtype-Variablen zuordnen.

      z.B. v_in_rec.spalten_name := return_value.

      da aber die schnittstellen sehr dynamisch sind, und somit es sein kann das auch mal eine spalte zugefügt wird, kann ich keine hart-codierte zuweisung wie im beispiel machen.

      ich muss also v_in_rec.spalten_name zur laufzeit zusammensetzen.


      jetzt verständlicher?

      Comment


      • #4
        Originally posted by jogi_hb View Post
        gut, fange mal vorn an!

        ich habe ein schnittstellen-schema.
        dort liegen diverse IN und OUT-Tabellen.

        die Tabellen-Namen entsprechen immer der Applikation für die sie bestimmt sind.
        die Spalten-Namen entsprechen immer den Parametern die eine Applikation erwartet bzw. zurück liefert.

        ich habe nun eine applikation namens
        Function APPL1(IN_zuberechnender_wert IN VARCHAR2) Return NUMBER.
        diese berechnet diverse werte(bestimmt durch den parameter) und liefert das ergebnis zurück.
        die Return-Values werden dann von mir in der entsprechenden IN-Tabelle in der dazugehörigen Spalte gespeichert.

        Und da liegt genau die Krux!

        ich laufe mit einem loop über die tabellenspalten der Out-Tabelle.
        übergebe den Spaltennamen als Parameter an APPL1.
        und möchte nun den rückgabewert in die korrespondierende IN-Tabellen-Spalte ablegen.

        also habe ich mir eine rowtype-variable erstellt auf basis meiner IN-Tabelle.
        nenn wir sie v_IN_Rec IN_APPL1%Rowtype.

        und nun möchte ich das Returnvalue von APPL1 der korrespondierenden Spalte in der Rowtype-Variablen zuordnen.

        z.B. v_in_rec.spalten_name := return_value.

        da aber die schnittstellen sehr dynamisch sind, und somit es sein kann das auch mal eine spalte zugefügt wird, kann ich keine hart-codierte zuweisung wie im beispiel machen.

        ich muss also v_in_rec.spalten_name zur laufzeit zusammensetzen.


        jetzt verständlicher?
        - Na ja, besser :-). Geht das so Richtung "Dynamisches Datenmodell" ?


        Gruss

        Comment


        • #5
          Geht das so Richtung "Dynamisches Datenmodell" ?
          Hmm dafür ist es zu unflexibel:
          die Tabellen-Namen entsprechen immer der Applikation für die sie bestimmt sind.
          die Spalten-Namen entsprechen immer den Parametern die eine Applikation erwartet bzw. zurück liefert.
          Eigentlich sollte der Wert den Parameternamen enthalten und nicht der Spaltenname. Vor allem nach dieser Aussage des OP.

          Aber zurück zu dem Problem. Was ich mir vorstellen könnte, ist ein dynamisch generierter anonymer PL/SQL Block:
          Code:
          execute immediate 'begin v_record.'||rec.COLUMN_NAME||':=fremdes_plsql_package.start('||rec.COLUMN_NAME||');end;'
          Allerdings bin ich mir momentan nicht ganz sicher, wie es mit der Sichtbarkeit von v_record abläuft. ich vermute, Du musst die variable im Package Body deklarieren und dann mit packagename.Variablenname aufrufen, damit Du sie im anonymen Block ohne weitere deklaration verwenden kannst.

          Dim
          Zitat Tom Kyte:
          I have a simple philosophy when it comes to the Oracle Database: you can treat it as a black box and just stick data into it, or you can understand how it works and exploit it as a powerful computing environment.

          Comment


          • #6
            Wenn ich richtig verstanden habe, besitzt du eine Tabelle MY_TABLE mit 84 Spalten. Das bedeutet, dass dir die Spaltennamen davon bekannt sind.

            Beispiel: MY_TABLE besitzt die Spalten name und ort


            Durch den Cursor cur_wert liefert die Spaltennamen von MY_TABLE.

            Die Anweisung:
            v_return wert := fremdes_plsql_package.start(rec.COLUMN_NAME);
            wird zur Laufzeit mit
            v_return wert := fremdes_plsql_package.start( 'name' );
            und
            v_return wert := fremdes_plsql_package.start( 'ort' );
            aufgerufen (bezogen auf meine beiden Spalten).

            Der Rückgabewert soll in die richtige Komponente von v_record eingetragen werden. Die Anweisung
            v_record.||rec.COLUMN_NAME := v_return_wert
            wird zur Laufzeit wie folgt abgearbeitet:
            v_record.'name' := v_return_wert bzw. v_record.'ort' := v_return_wert

            Das Problem dabei ist, dass COLUMN_NAME einen String zurückliefert, d.h. der String ist in Hochkommata eingefasst. In deinem Record sind die Komponentennamen aber ohne Hochkommata enthalten.

            Hier hilft nur folgendes:
            IF rec.COLUMN_NAME = 'name' THEN v_record.name := v_return_wert END IF;
            IF rec.COLUMN_NAME = 'ort' THEN v_record.ort := v_return_wert END IF;

            Allerdings basiert die Lösung darauf, dass die Namen deiner 84 Spalten ja bekannt sind, die dann beim Vergleichen herangezogen werden.

            kuemmelchen

            Comment


            • #7
              vielen dank für eure antworten.

              dynamisches DM nicht ganz.
              es ist nur so dass eben Anwender die Schnittstellen selbst konfigurieren können.
              jenachdem wie die Appl aussieht. (setzen hier viele fremdprodukte ein).

              dadurch werden die schnittstellen-tabellen hin und wieder durch DDLs umgebaut.

              hierdurch bedingt es eben einer dynamischen programmierung.

              mal habe ich 10 und manchmal 200 parameter die dann hin und her geschaufelt werden.

              statische if's wie bei kuemmelchen würden meine packages invalid werden lassen.

              werde den vorschlag von dimitri mal ausprobieren. EXECUTE IMMEDIATE...

              nochmal gracias

              Comment


              • #8
                statische if's wie bei kuemmelchen würden meine packages invalid werden lassen.
                Das werden sie sowieso, da Du %ROWTYPE verwendest. %ROWTYP ist nicht dynamisch, sondern wird zur Compiletime aufgelöst.

                Das kann man nur umgehen, indem man die Schnittstellen nicht per DDL sondern per DML definiert.

                Dim
                Zitat Tom Kyte:
                I have a simple philosophy when it comes to the Oracle Database: you can treat it as a black box and just stick data into it, or you can understand how it works and exploit it as a powerful computing environment.

                Comment


                • #9
                  nur dass ein invalid package wenn es angesprochen wird implizit compeliert wird.

                  und durch dein EXECUTE IMMEDIATE (welches im übrigen hervoragend klappt) erhalte ich keine fehler!

                  Comment

                  Working...
                  X