Frage

Wie kann ich eine Oracle gespeicherte Prozedur erstellen, die eine variable Anzahl von Parameterwerten akzeptieren eine IN-Klausel zu füttern?

Das ist, was ich zu erreichen versuchen. Ich weiß nicht, wie für das Bestehen einer variablen Liste der Primärschlüssel der Zeilen in PLSQL zu erklären, ich aktualisieren möchten.

FUNCTION EXECUTE_UPDATE
  ( <parameter_list>
   value IN int)
  RETURN  int IS
BEGIN 
    [...other statements...]
    update table1 set col1 = col1 - value where id in (<parameter_list>) 

    RETURN SQL%ROWCOUNT ;
END;

Auch ich mag diese Prozedur von C # nennen, so dass es mit .NET-Funktionen kompatibel sein muß.

Danke, Robert

War es hilfreich?

Lösung

Mit CSV ist wahrscheinlich der einfachste Weg, vorausgesetzt, Sie zu 100% sicher sein, dass Ihre Elemente werden sich Strings nicht enthalten.

Eine Alternative, und wahrscheinlich robuster Weg, dies zu tun ist, einen benutzerdefinierten Typ als Tabelle von Zeichenketten zu erstellen. Nimmt man die Saiten wurden nie länger als 100 Zeichen, dann könnten Sie haben:

CREATE TYPE string_table AS TABLE OF varchar2(100);

Sie können dann eine Variable dieses Typs in Ihrer gespeicherten Prozedur übergeben und direkt verweisen. In Ihrem Fall, so etwas wie folgt aus:

FUNCTION EXECUTE_UPDATE(
    identifierList string_table,
    value int)
RETURN int
IS
BEGIN

    [...other stuff...]

    update table1 set col1 = col1 - value 
    where id in (select column_value from table(identifierList));

    RETURN SQL%ROWCOUNT;

END

Die table() Funktion macht aus Ihrem benutzerdefinierten Typ in eine Tabelle mit einer einzigen Spalte „spalten“, die Sie dann wie jede andere Tabelle behandeln (so tut beitritt oder, in diesem Fall Subselects).

Das Schöne daran ist, dass Oracle einen Konstruktor für Sie erstellen, so dass, wenn Ihre gespeicherte Prozedur aufrufen können Sie einfach schreiben:

execute_update(string_table('foo','bar','baz'), 32);

Ich gehe davon aus, dass Sie behandeln können diesen Befehl programmatisch von C # Aufbau.

Als Nebenwirkung in meinem Unternehmen haben wir eine Reihe dieser benutzerdefinierten Typen haben als Standard definiert für Listen von Strings, Doppel-, Ints und so weiter. Wir machen auch die Verwendung von Oracle JPublisher der Lage sein, Karte direkt aus diesen Typen in Java-Objekte entsprechen. Ich hatte einen kurzen Blick um, aber ich konnte keine direkten Mittel für C # sehen. Nur dachte ich, es im Fall erwähnen würde Java Entwickler über diese Frage kommen.

Andere Tipps

fand ich die folgenden Artikel von Mark A. Williams, die ich dachte, wäre eine sinnvolle Ergänzung zu diesem Thread sein. Der Artikel gibt ein gutes Beispiel für Arrays von C # zu PL / SQL-Prozeduren unter Verwendung von assoziativen Arrays vorbei (TYPE myType IS TABLE OF mytable.row% TYPE INDEX BY PLS_INTEGER):

Große Artikel von Mark A. Williams

Ich denke, es gibt keine direkte Möglichkeit ist es, Verfahren mit variabler Anzahl von Parametern zu erstellen. Allerdings gibt es einige, zumindest teilweise Lösungen für das Problem beschrieben,

Warum nicht nur eine lange Parameterliste verwenden und die Werte in eine Tabelle Konstruktor laden? Hier ist die SQL / PSM für diesen Trick

UPDATE Foobar
   SET x = 42
 WHERE Foobar.keycol
      IN (SELECT X.parm
            FROM (VALUES (in_p01), (in_p02), .., (in_p99)) X(parm)
           WHERE X.parm IS NOT NULL);

Warum hat es eine gespeicherte Prozedur sein? Sie könnten programmatisch eine vorbereitete Anweisung aufzubauen.

Ich habe es nicht für Oracle getan, aber mit SQL Server können Sie eine Funktion verwenden, um einen CSV-String in eine Tabelle umgewandelt werden, die dann in einer IN-Klausel verwendet werden. Es sollte geradlinig sein, dies für Oracle neu zu schreiben (ich glaube!)

CREATE Function dbo.CsvToInt ( @Array varchar(1000)) 
returns @IntTable table 
    (IntValue nvarchar(100))
AS
begin

    declare @separator char(1)
    set @separator = ','

    declare @separator_position int 
    declare @array_value varchar(1000) 

    set @array = @array + ','

    while patindex('%,%' , @array) <> 0 
    begin

      select @separator_position =  patindex('%,%' , @array)
      select @array_value = left(@array, @separator_position - 1)

        Insert @IntTable
        Values (Cast(@array_value as nvarchar))

      select @array = stuff(@array, 1, @separator_position, '')
    end

    return
end

Dann können Sie in einem CSV-String übergeben (z '0001,0002,0003) und tun so etwas wie

UPDATE table1 SET 
       col1 = col1 - value 
WHERE id in (SELECT * FROM csvToInt(@myParam)) 
scroll top