PL/SQL function to read a string of characters into an array

I was wondering if there is an easier way than using the substr function multiple times. Here is the example:
Suppose you have a varchar2 variable that contains the word 'Apple'. The function should take it and produce an array. We would invoke it like this:
<what data structure?> a := stringunpackerfunction(x);
// x is the varchar2 containing 'Apple'.
The resulting a would be such that a[0] is 'A', a[1] is 'p', a[2] is 'p', a[3] is 'l' and a[4] is 'e'.
If there is no direct function to do this in a single invocation, is there a function to simply read a string of characters and return 'the next character'?
Thanks,
Regards,
Srini

There is a procedure out there called PS_PARSE which takes a string and converts to an array provided with an identified separator. Works for us pretty well.
I just grabbed this off of google. I am presuming this should work fine. It has been sometime since we implemented ours that I forget if there were any additional modifications that we made. I think there was one regarding the size of the string that could be handled. I forget precisely. Anyways... take a peek at it. Its makes things easy in that your logic is pretty streamlined.
Barry C
http://www.myoracleportal.com
create or replace PACKAGE PS_Parse
IS
     || PL/SQL table structures to hold atomics retrieved by parse_string.
     || This includes the table type definition, a table (though you can
     || declare your own as well, and an empty table, which you can use
     || to clear out your table which contains atomics.
     TYPE atoms_tabtype IS TABLE OF VARCHAR2(60) INDEX BY BINARY_INTEGER;
     atoms_table atoms_tabtype;
     empty_atoms_table atoms_tabtype;
     || The standard list of delimiters. You can over-ride these with
     || your own list when you call the procedures and functions below.
     || This list is a pretty standard set of delimiters, though.
     std_delimiters VARCHAR2 (50) := ' !@#$%^&*()-_=+\|`~{{]};:''",<.>/?';
     /* Display contents of table using DBMS_OUTPUT */
     PROCEDURE display_atomics
          (table_in IN atoms_tabtype, num_rows_in IN NUMBER);
     || The parse_string procedure: I provide two, overloaded definitions.
     || The first version puts all atomics into a PL/SQL table and would
     || be used in a PL/SQL Version 2 environment. The second version places
     || all atomics into a string, separating each atomic by a vertical bar.
     || (My code does NOT do any special handling when it finds a "|" in
     || the string. You have to deal with that when you extract the atomics.
     ||
     || See the program definition for more details on other parameters.
     PROCEDURE parse_string
          (string_in IN VARCHAR2,
          atomics_list_out OUT atoms_tabtype,
          num_atomics_out IN OUT NUMBER,
          delimiters_in IN VARCHAR2 := std_delimiters);
     PROCEDURE parse_string
          (string_in IN VARCHAR2,
          atomics_list_out IN OUT VARCHAR2,
          num_atomics_out IN OUT NUMBER,
          delimiters_in IN VARCHAR2 := std_delimiters);
     /* Count the number of atomics in a string */
     FUNCTION number_of_atomics
          (string_in IN VARCHAR2,
          count_type_in IN VARCHAR2 := 'ALL',
          delimiters_in IN VARCHAR2 := std_delimiters)
     RETURN INTEGER;
     /* Return the Nth atomic in the string */
     FUNCTION nth_atomic
          (string_in IN VARCHAR2,
          nth_in IN NUMBER,
          count_type_in IN VARCHAR2 := 'ALL',
          delimiters_in IN VARCHAR2 := std_delimiters)
     RETURN VARCHAR2;
END PS_Parse;
create or replace PACKAGE BODY PS_Parse
IS
/* Package variables used repeatedly throughout the body. */
len_string     NUMBER;
start_loc     NUMBER;
next_loc     NUMBER;     
|| Since the PUT_LINE procedure regards a string of one or more
|| spaces as NULL, it will not display a space, which is in
|| PS_Parse a valid atomic. So I save a_blank in the PL/SQL
|| table instead of the space itself.
a_blank CONSTANT VARCHAR2(3) := '" "';
/*--------------------- Private Modules ---------------------------
|| The following functions are available only to other modules in
|| package. No user of PS_Parse can see or use these functions.
FUNCTION a_delimiter
(character_in IN VARCHAR2,
delimiters_in IN VARCHAR2 := std_delimiters)
RETURN BOOLEAN
|| Returns TRUE if the character passsed into the function is found
|| in the list of delimiters.
IS
BEGIN
RETURN INSTR (delimiters_in, character_in) > 0;
END;
FUNCTION string_length (string_in IN VARCHAR2)
RETURN INTEGER
IS
BEGIN
RETURN LENGTH (LTRIM (RTRIM (string_in)));
END;
FUNCTION next_atom_loc
(string_in IN VARCHAR2,
start_loc_in IN NUMBER,
scan_increment_in IN NUMBER := +1)      
|| The next_atom_loc function returns the location
|| in the string of the starting point of the next atomic (from the
|| start location). The function scans forward if scan_increment_in is
|| +1, otherwise it scans backwards through the string. Here is the
|| logic to determine when the next atomic starts:
||
||          1. If current atomic is a delimiter (if, that is, the character
||               at the start_loc_in of the string is a delimiter), then the
||               the next character starts the next atomic since all
||               delimiters are a single character in length.
||
||          2. If current atomic is a word (if, that is, the character
||               at the start_loc_in of the string is a delimiter), then the
||               next atomic starts at the next delimiter. Any letters or
||               numbers in between are part of the current atomic.
||
|| So I loop through the string a character at a time and apply these
|| tests. I also have to check for end of string. If I scan forward
|| the end of string comes when the SUBSTR which pulls out the next
|| character returns NULL. If I scan backward, then the end of the
|| string comes when the location is less than 0.
RETURN NUMBER
IS
/* Boolean variable which uses private function to determine
|| if the current character is a delimiter or not.
was_a_delimiter BOOLEAN :=
PS_Parse.a_delimiter (SUBSTR (string_in, start_loc_in, 1));     
/* If not a delimiter, then it was a word. */
was_a_word BOOLEAN := NOT was_a_delimiter;
/* The next character scanned in the string */
          next_char VARCHAR2(1);
|| The value returned by the function. This location is the start
|| of the next atomic found. Initialize it to next character,
|| forward or backward depending on increment.
return_value NUMBER := start_loc_in + scan_increment_in;
BEGIN
LOOP
-- Extract the next character.
next_char := SUBSTR (string_in, return_value, 1);
-- Exit the loop if:
EXIT WHEN
/* On a delimiter, since that is always an atomic */
a_delimiter (next_char)
OR
/* Was a delimiter, but am now in a word. */
(was_a_delimiter AND NOT a_delimiter (next_char))
OR
/* Reached end of string scanning forward. */
next_char IS NULL
OR
/* Reached beginning of string scanning backward. */
return_value < 0;
/* Shift return_value to move the next character. */
return_value := return_value + scan_increment_in;
END LOOP;
-- If the return_value is negative, return 0, else the return_value
RETURN GREATEST (return_value, 0);
END;
PROCEDURE increment_counter
(counter_inout IN OUT NUMBER,
count_type_in IN VARCHAR2,
atomic_in IN CHAR)
|| The increment_counter procedure is used by nth_atomic and
|| number_of_atomics to add to the count of of atomics. Since you
|| can request a count by ALL atomics, just the WORD atomics or
|| just the DELIMITER atomics. I use the a_delimiter function to
|| decide whether I should add to the counter. This is not a terribly
|| complex procedure. I bury this logic into a separate module,
however,
|| to make it easier to read and debug the main body of the programs.
IS
BEGIN
IF count_type_in = 'ALL' OR
(count_type_in = 'WORD' AND NOT a_delimiter (atomic_in)) OR
(count_type_in = 'DELIMITER' AND a_delimiter (atomic_in))
THEN
counter_inout := counter_inout + 1;
END IF;
END increment_counter;
/* ------------------------- Public Modules -----------------------*/
PROCEDURE display_atomics
(table_in IN atoms_tabtype, num_rows_in IN NUMBER)
|| Program to dump out contents of table. Notice I must also pass in
|| the number of rows in the table so that I know when to stop the
|| loop. Otherwise I will raise a NO_DATA_FOUND exception. For a more
|| elaborate display_table module, see Chapter 7 on PL/SQL tables.
IS
BEGIN
FOR table_row IN 1 .. num_rows_in
LOOP
DBMS_OUTPUT.PUT_LINE (NVL (table_in (table_row), 'NULL'));
END LOOP;
END;
PROCEDURE parse_string
(string_in IN VARCHAR2,
atomics_list_out OUT atoms_tabtype,
num_atomics_out IN OUT NUMBER,
delimiters_in IN VARCHAR2 := std_delimiters)
|| Version of parse_string which stores the list of atomics
|| in a PL/SQL table.
||
|| Parameters:
||          string_in - the string to be parsed.
||          atomics_list_out - the table of atomics.
||          num_atomics_out - the number of atomics found.
||          delimiters_in - the set of delimiters used in parse.
IS
BEGIN
/* Initialize variables. */
num_atomics_out := 0;
len_string := string_length (string_in);
IF len_string IS NOT NULL
THEN
|| Only scan the string if made of something more than blanks.
|| Start at first non-blank character. Remember: INSTR returns 0
|| if a space is not found. Stop scanning if at end of string.
start_loc := LEAST (1, INSTR (string_in, ' ') + 1);
WHILE start_loc <= len_string
LOOP
|| Find the starting point of the NEXT atomic. Go ahead and
|| increment counter for the number of atomics. Then have to
|| actually pull out the atomic. Two cases to consider:
||          1. Last atomic goes to end of string.
||          2. The atomic is a single blank. Use special constant.
||          3. Anything else.
next_loc := next_atom_loc (string_in, start_loc);
num_atomics_out := num_atomics_out + 1;
IF next_loc > len_string
THEN
-- Atomic is all characters right to the end of the string.
atomics_list_out (num_atomics_out) :=
SUBSTR (string_in, start_loc);
ELSE
|| Internal atomic. If RTRIMs to NULL, have a blank
|| Use special-case string to stuff a " " in the table.
atomics_list_out (num_atomics_out) :=
NVL (RTRIM (SUBSTR (string_in,
start_loc, next_loc-start_loc)),
                                   a_blank);
END IF;
-- Move starting point of scan for next atomic.
start_loc := next_loc;
END LOOP;
END IF;
END parse_string;
PROCEDURE parse_string
(string_in IN VARCHAR2,
atomics_list_out IN OUT VARCHAR2,
num_atomics_out IN OUT NUMBER,
delimiters_in IN VARCHAR2 := std_delimiters)
|| The version of parse_string which writes the atomics out to a packed
|| list in the format "|A|,|C|". I do not repeat any of the comments
|| from the first iteration of parse_string.
IS
BEGIN
/* Initialize variables */
num_atomics_out := 0;
atomics_list_out := NULL;
len_string := string_length (string_in);
IF len_string IS NOT NULL
THEN
start_loc := LEAST (1, INSTR (string_in, ' ') + 1);
WHILE start_loc <= len_string
LOOP
next_loc := next_atom_loc (string_in, start_loc);
num_atomics_out := num_atomics_out + 1;
IF next_loc > len_string
THEN
atomics_list_out := atomics_list_out || '|' ||      
SUBSTR (string_in, start_loc);
ELSE
atomics_list_out :=
atomics_list_out || '|' ||      
NVL (RTRIM (SUBSTR (string_in,
start_loc, next_loc-start_loc)),
                                   a_blank);
END IF;
start_loc := next_loc;
END LOOP;
/* Apply terminating delimiter to the string. */
atomics_list_out := atomics_list_out || '|' ;
END IF;
END parse_string;
FUNCTION number_of_atomics
(string_in IN VARCHAR2,
count_type_in IN VARCHAR2 := 'ALL',
delimiters_in IN VARCHAR2 := std_delimiters)
RETURN INTEGER
|| Counts the number of atomics in the string_in. You can specify the
|| type of count you want: ALL for all atomics, WORD to count only the
|| words and DELIMITER to count only the delimiters. You can optionally
|| pass your own set of delimiters into the function.
IS
return_value INTEGER := 0;
BEGIN
/* Initialize variables. */
len_string := string_length (string_in);
IF len_string IS NOT NULL
THEN
|| This loop is much simpler than parse_string. Call the
|| next_atom_loc to move to the next atomic and increment the
|| counter if appropriate. Everything complicated is shifted into
|| sub-programs so that you can read the program "top-down",
|| understand it layer by layer.
start_loc := LEAST (1, INSTR (string_in, ' ') + 1);
WHILE start_loc <= len_string
LOOP
increment_counter (return_value, UPPER (count_type_in),
SUBSTR (string_in, start_loc, 1));
start_loc := next_atom_loc (string_in, start_loc);
END LOOP;
END IF;
RETURN return_value;
END number_of_atomics;
FUNCTION nth_atomic
(string_in IN VARCHAR2,
nth_in IN NUMBER,
count_type_in IN VARCHAR2 := 'ALL',
delimiters_in IN VARCHAR2 := std_delimiters)
RETURN VARCHAR2
|| Find and return the nth atomic in a string. If nth_in is greater
|| the number of atomics, then return NULL. If nth_in is negative the
|| function counts from the back of the string. You can again request
|| a retrieval by ALL atomics, just the WORDs or just the DELIMITER.
|| So you can ask for the third atomic, or the second word from the end
|| of the string. You can pass your own list of delimiters as well.
IS
/* Local copy of string. Supports up to 1000 characters. */
local_string VARCHAR2 (1000) :=
LTRIM (RTRIM (SUBSTR (string_in, 1, 1000)));
/* Running count of atomics so far counted. */
atomic_count NUMBER := 1;
/* Boolean variable which controls the looping logic. */
still_scanning BOOLEAN :=
local_string IS NOT NULL AND nth_in != 0;
/* The amount by which I increment the counter. */
scan_increment INTEGER;
/* Return value of function, maximum length of 100 characters. */
return_value VARCHAR2 (100):= NULL;
BEGIN
IF nth_in = 0
THEN
/* Not much to do here. Find 0th atomic? */
RETURN NULL;
ELSE
/* Initialize the loop variables. */
len_string := string_length (local_string);
IF nth_in > 0
THEN
/* Start at first non-blank character and scan forward. */
next_loc := 1;
scan_increment := 1;
ELSE
/* Start at last non-blank character and scan backward. */
next_loc := len_string;
scan_increment := -1;
END IF;
/* Loop through the string until the Boolean is FALSE. */
WHILE still_scanning
LOOP
/* Move start of scan in string to loc of last atomic. */
start_loc := next_loc;
/* Find the starting point of the next atomic. */
next_loc      :=
next_atom_loc (local_string, start_loc, scan_increment);
/* Increment the count of atomics. */
increment_counter
(atomic_count,
UPPER (count_type_in),
SUBSTR (local_string, start_loc, 1));
|| Keep scanning if my count hasn't exceeded the request
|| and I am neither at the beginning nor end of the string.
still_scanning :=
atomic_count <= ABS (nth_in) AND
next_loc <= len_string AND
next_loc >= 1;
END LOOP;
|| Done with the loop. If my count has not exceeded the requested
|| amount, then there weren't enough atomics in the string to
|| satisfy the request.
IF atomic_count <= ABS (nth_in)
THEN
RETURN NULL;
ELSE
|| I need to extract the atomic from the string. If scanning
|| forward, then I start at start_loc and SUBSTR forward.
|| If I am scanning backwards, I start at next_loc+1 (next_loc
|| is the starting point of the NEXT atomic and I want the
|| current one) and SUBSTR forward (when scanning in
|| reverse, next_loc comes before start_loc in the string.
IF scan_increment = +1
THEN
RETURN
SUBSTR (local_string, start_loc, next_loc - start_loc);
ELSE
RETURN
SUBSTR (local_string, next_loc+1, start_loc - next_loc);
END IF;
END IF;
END IF;
END nth_atomic;
END PS_Parse;
/

Similar Messages

  • SQL Function to compare 2 strings

    Hi All
    Is there any SQL function to compare 2 strings?

    If you are looking for a character by character comparison then you would have to do something like...
    SQL> ed
    Wrote file afiedt.buf
      1  WITH T AS (select 'THIS IS MY 1ST STRING' string1, 'THIS IS MY 2ND String Bob' string2 from dual)
      2  --
      3  select s1ch, s2ch, decode(s1ch,s2ch,'Match','Mismatch') as compare
      4  from (
      5        select rn, substr(string1,rn,1) as s1ch, substr(string2,rn,1) as s2ch
      6        from t, (select rownum rn from t connect by rownum <= greatest(length(string1), length(string2)))
      7       )
      8* order by rn
    SQL> /
    S S COMPARE
    T T Match
    H H Match
    I I Match
    S S Match
        Match
    I I Match
    S S Match
        Match
    M M Match
    Y Y Match
        Match
    1 2 Mismatch
    S N Mismatch
    T D Mismatch
        Match
    S S Match
    T t Mismatch
    R r Mismatch
    I i Mismatch
    N n Mismatch
    G g Mismatch
        Mismatch
      B Mismatch
      o Mismatch
      b Mismatch
    25 rows selected.
    SQL>

  • Reading a string of characters

    Hi all,
    How would one allow for a user to enter a random set of 80 characters and put each one of those characters in a cell in an array (one cell for one character)? Is there a special tokenizer or something I could use?
    Thanks,
    Mike

    does something like this work for you?... // read in a line of characters...
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in) ;
    String str = in.readLine() ;
    // put string's chars into an array (limit to 80 chars)...
    char[] buf = new char[80] ;
    int len = str.length() ;
    if (len > buf.length) len = buf.length ;
    str.getChars(0, len, buf, 0) ;     // *************

  • Converting a string of numbers into an array of booleans

    For a homework assignment, I need to convert a string of numbers into an array of booleans.  The string is a bunch of random numbers (0-9) in sequence, with no spaces.  It looks something like this: 0123452348949230740329817438120947392147809231419.  I need to make it so that each even number represents a "True" boolean and so that each odd number represents a "False" boolean.  I think that I first need to convert each element of the string into a number, and then use a case structure (or something) to say, for each element of the array, "If even, then true.  If odd, then false," but I could be wrong.  Any suggestions?

    billko wrote:
    Hooovahh wrote:
    billko wrote:
    Sounds reasonable.  Think about the definition of "odd" and "even" and it will make life a lot easier. 
    I know you are trying to be vague but I'd like to give a key hint.  Use the Quotient and Remainder function.
    LOL maybe that was one of the objectives of the homework. 
    To be fair it sounds like there is more work that is needed.  A new user of LabVIEW will have a hard time figuring out how to process each character one at a time when it isn't in an array.  
    It's just that most people (me at least) stopped thinking about division with quotient and remainder after basic algebra.  I then of course changed my way of thinking when I used LabVIEW.  Still most of the time when you use division you want to know the fractional part as a decimal.  Thinking this way makes the problem more difficult then it needs to be.
    Unofficial Forum Rules and Guidelines - Hooovahh - LabVIEW Overlord
    If 10 out of 10 experts in any field say something is bad, you should probably take their opinion seriously.

  • CONCATENATE a string a characters into a field

    Hi everyone!
    Let's say that i want to CONCATENATE a string of characters (for example: 'ABC') into every WTAB-AUFNR record that i retrieve. How do i do that?
    Let's assume that WTAB-AUFNR's header currently has the value '50-12345', i want it to be 'ABC50-12345'.

    I've got another CONCATENATE question. Here it is:
    Let's say i wanna have the values in CTAB-WTJHR to be in brackets, which i am going to hardcode by doing a CONCATENATE. So it should work if i write it like this:
    DATA: BEGIN OF CTAB OCCURS 0,
          LEDNR LIKE BPJA-LEDNR,  "Ledger
          OBJNR LIKE BPJA-OBJNR,  "Object Number
          TRGKZ LIKE BPJA-TRGKZ,  "Object Indicator
          WRTTP LIKE BPJA-WRTTP,  "Value Type
          GJAHR LIKE BPJA-GJAHR,  "Fiscal Year
          VERSN LIKE BPJA-VERSN,  "Version
          VORGA LIKE BPJA-VORGA,  "Budget Type
          TWAER LIKE BPJA-TWAER,  "Transaction Currency
          WTJHV LIKE BPJA-WTJHV,  "Original Budget
          WTJHR LIKE BPJA-WTJHR,  "Amount Utilised YTD
          V_BEFORE TYPE I,             "Balance Before This Request
          V_CURRENT TYPE I,            "Current Acquisition Cost
          V_BALANCE TYPE I,            "Balance Variation
          END OF CTAB.
    SELECT SINGLE LEDNR OBJNR TRGKZ WRTTP GJAHR VERSN VORGA TWAER WTJHV
    WTJHR
      INTO CTAB
      FROM BPJA
      WHERE OBJNR = WTAB-AUFNR AND
            WRTTP = '42' AND
            GJAHR = ITAB-LFDAT+0(4).
    APPEND CTAB.
    LOOP AT CTAB.
    CONCATENATE '(' CTAB-WTJHR ')' INTO CTAB-WTJHR.
      MODIFY CTAB TRANSPORTING WTJHR.
    ENDLOOP.
    I've looked through it and i can't find any syntax problem or anything else but i keep getting this message when i try to activate my program: "CTAB-WTJHR" must be a character-type data object (data type C, N, D, T or STRING). field string". When i looked at SE11 and i found out that the WTJHR field in BPJA is a type CURR. Is there a way to solve this?

  • Can you parse an array of string characters into separate arrays?

    Hello,
    I didn't see anything directly related to my question, so I'll go ahead and post it.  I'm looking to parse an array of hex characters into three separate arrays for parallel Color to RGB conversion in LabView.  Ideally, after importing an image, I would have liked to use the Color to RGB conversion for the 24-bit pixmap (in hex digit format), but apparently, you can only do this for single number conversions...not arrays.  Another way is what I have mentioned above, which would be to parse each element's red, green, and blue # into three separate arrays as shown below:
    Original Array:   aa11ff     225599
                              cc4488   bbcc11
    Array 1: aa  22
                 cc   bb
    Array 2: 11   55
                  44   cc
    Array 3:  ff    99
                  88   11
    I could then do a parallel conversion of these arrays from hex to numeric and get the desired result.  However, I'm having trouble finding a function that will do this.  So I would like to ask if a function like this does exist and if so, what is it?  I should note that I'm trying to avoid using two while loops because of time constraints (using the program for in-situ measurements), and we do not own, nor are we looking to purchase the $$$ vision/video package that NI makes.

    Nevermind.  I found an adequate way.

  • Problems with different received message from sql function

    Hello all!
    I have a little problem with my BPEL process. I call a sql function that returns a string. In this string I have a xml. The returned message can be something like:
    <error><id>id_error</id><message>descr_error</message></error>
    or
    <comm>
    <header>
    children tags
    </header>
    <body>
    children tags
    </body>
    </comm>
    As you see, I can receive two types of messages. Of course, the process transforms string -> xml.
    Depending on the type, the process must choose between two flows.
    My questions are: what should be the solution(the steps) to determine what type of message the function returns? In my project, where should I define the same message types in order to assignate them to a variable? In a xsd?
    Thanks in advance!!

    seems like you could solve this with a <pick>. Take a look at the section "One Request, One of Two Possible Responses" in chapter 13 of the bpel developer guide.

  • Is sql functions or trigger possible for adf button component

    while developing project using ADF BC and JSF, is possible to invoke sql functions or trigger for an adf button component. plz reply

    For this you define a method in the application module which you expose to the client. Then you can drag this method onto the button. The method is call when you click the button.
    Inside the method you can call pl/sql functions. Read chapter "37.5 Invoking Stored Procedures and Functions" here http://download.oracle.com/docs/cd/E15523_01/web.1111/b31974/bcadvgen.htm#sm0297
    Timo

  • SQL Function to trim characters

    Hi!
    Can someone help me with writing SQL Function which receive a string and return it with all the below ASCII characters values removed:
    chr(n)>31 AND chr(n)<48
    OR
    chr(n)>57 AND chr(n)<65
    OR
    chr(n)>90 AND chr(n)<97
    OR
    chr(n)>122 AND chr(n)<128
    Thanks

    Actually, I forgot chr(127) in there. Try this:
    select regexp_replace(yourstring,  '[[:punct:] '||chr(127)||']', '') from dual;Example:
    SQL> select regexp_replace(
       'hello !"#$%&''()*+,-./:;<=>?@[\]^_`{|}~'||chr(127)||'there'
       , '[[:punct:] '||chr(127)||']'
    ) from dual;
    REGEXP_REP
    hellotherecheers,
    Anthony

  • String Substitutions with PL/SQL Function

    Hello, i user APEX 4.2.1.00.08 in Database 11g
    I new in apex and a try to use String Substitutions.
    When I define a String like CONST with static value like '999' in Edit Applications Definition it's work fine.
    But I need to define the same String 'CONST' but with value to return from PL/SQL function like.. Package.function
    It's Possible ??
    Thanks !!

    No, you'll need to use application items instead - or pass the value as parameter to your function.
    Passing parameters like this makes for good practice anyway, since your modules become more testable outside the apex environment, and more robust.

  • Read consistency in query with pl/sql functions

    Not sure if this is a bug or feature, but a query containing a user-defined pl/sql function does not include tables accessed within the pl/sql function in the read consistent view of data, eg
    select myfunc from tableA
    myfunc is a stored function that queries tableB and returns a value
    If a change to tableB is committed in another session during fetch phase of select statement, then fetched rows reflect the changes. The database does not recognise tables accessed in the plsql function as being part of the query.
    This happens in 7.3.4 and 8.1.6. Don't have 9i so can't tell.
    Anyone know if this is a bug or feature?
    Aside: you can also drop the plsql function whilst the fetch is running. It will kill the fetch. No DDL lock taken on the plsql function whilst select is running! Seems wrong.

    I don't know Forms but I know SQL*Plus and Oracle database. Normally PL/SQL running on the database can only access files on the host where the database instance is running even if you start PL/SQL with a SQL*Plus connection from another host.
    PL/SQL runs only the database instance not on the client side even if you start the PL/SQL code from a remote connection with SQL*Plus.

  • PL/SQL Function call error while reading or assigning returned value

    Hi,
    I am getting the following error while tryih to read the value of the PL/SQL Function. I am calling a function in one of my PL/SQL Packages passing mutliple IN parametes and the function returns some value back. Now on BPEL side when I try to read the return value I am getting an error:
    *<summary>*
    empty variable/expression result.
    xpath variable/expression expression "/ns3:OutputParameters/ns3:TEST_FUNCTION" is empty at line 124, when attempting reading/copying it.
    Please make sure the variable/expression result "/ns3:OutputParameters/ns3:TEST_FUNCTION" is not empty.
    *</summary>*
    Even though in the console when I check the Invoke Output Parameter it does shows me a valid value being retuned by a Function but when I am trying to Assgn this value to some variable using Assign Activity I get the above error.
    Even though all goes fine but looks like I am not able to read or assign the value returned from the Function.
    So just wondering if this even works as to me I have a very simple example and that seems not to work. Function is called successfully and is returning the value as I can see it in the BPEL console but when tryin to read or assign that value to some other variable I get the above error.
    Any ideas?
    Thanks

    This issue has come up a lot. The problem is with a mismatch between the version of JDeveloper and SOA. You'll encounter namespace issues if you use 10.1.3.1 in combination with 10.1.3.3 (or 10.1.3.4). You MUST synchronize both JDev and SOA to 10.1.3.3 or 10.1.3.4 (mixing 10.1.3.3 and 10.1.3.4 is OK). We changed when going to 10.1.3.3 by adding elementFormDefault="qualified" to the generated XSD. We used the default "unqualified" in 10.1.3.1. So you'll encounter namespace issues unless you're using 10.1.3.3 or higher JDev AND SOA. The fact that I see &lt;*db:*...&gt; tells me that you're using 10.1.3.1 JDeveloper. The correct solution is to upgrade your components.

  • SQL report region source to call a pl/sql function using DB link

    Hi - I have a pl/sql function fn_dbtype(id NUMBER) defined in database X. The pl/sql function executes couple DML statements and returns a string (a SELECT query). I am able to call this function using SQL Plus (Connected to Database X) as below and it works fine:
    declare
    vSQL VARCHAR2(100);
    begin
    vSQL := fn_dbtype(1);
    end;
    The DML operations completed fine and vSQL contains the "Select" query now.
    In APEX:
    I am trying to create a SQL report in APEX using SQL query(PL/SQL function returning a sql statement) option. I am trying to figure out what to put in the region source so that the output of the "Select" query is displayed in the report.
    Moreover APEX is hosted in a different database instance. So I would need to call this pl/sql function using a DB Link.
    Please let me know what I need to put in the region source to execute the pl/sql function which returns the "Select" query thereby displaying the query output in the report. Thanks.
    Edited by: user709584 on Mar 19, 2009 2:32 PM
    Edited by: user709584 on Mar 19, 2009 2:34 PM

    try something like this:
    return fn_dbtype(1)@dblink;

  • PL/SQL function. ORA-00933: SQL command not properly ended

    This is my first attempt at pl/sql functions with dynamic sql. It will compile, but when I try to test it I get the ORA-00933 error at line 147. line 147 is OPEN retval FOR report_query;
    Please take a look and let me know what it wrong! thanks
    {CREATE OR REPLACE FUNCTION TSARPTS.Stats (v_Hub       IN VARCHAR2,
                                              v_type      IN VARCHAR2,
                                              v_subtype   IN VARCHAR2)
       RETURN SYS_REFCURSOR
    IS
       retval           SYS_REFCURSOR;
       report_query_a   VARCHAR2 (10000)
                           := '
      SELECT hub,
             CASE
                WHEN Total = 0 OR Pass_1st = 0 THEN 0
                ELSE ROUND (Pass_1st / (Total) * 100, 2)
             END
                AS Pass_1st_percent,
             CASE
                WHEN Total = 0 OR Pass_2nd = 0 THEN 0
                ELSE ROUND (Pass_2nd / (Total) * 100, 2)
             END
                AS Pass_2nd_percent,
             CASE
                WHEN Total = 0 OR Pass_3rd = 0 THEN 0
                ELSE ROUND (Pass_3rd / (Total) * 100, 2)
             END
                AS Pass_3rd_percent,
             CASE
                WHEN Total = 0 OR DNM = 0 THEN 0
                ELSE ROUND (DNM / (Total) * 100, 2)
             END
                AS DNM,
             CASE
                WHEN Total = 0 OR Incomplete = 0 THEN 0
                ELSE ROUND (Incomplete / (Total) * 100, 2)
             END
                AS Incomplete
        FROM (  SELECT hub,
                       SUM (DECODE (result, ''Pass_on_1st'', 1, 0)) Pass_1st,
                       SUM (DECODE (result, ''Pass_on_2nd'', 1, 0)) Pass_2nd,
                       SUM (DECODE (result, ''Pass_on_3rd'', 1, 0)) Pass_3rd,
                       SUM (DECODE (result, ''DNM'', 1, 0)) DNM,
                       SUM (DECODE (result, ''INCOMPLETE'', 1, 0)) Incomplete,
                         SUM (DECODE (result, ''Pass_on_1st'', 1, 0))
                       + SUM (DECODE (result, ''Pass_on_2nd'', 1, 0))
                       + SUM (DECODE (result, ''Pass_on_3rd'', 1, 0))
                       + SUM (DECODE (result, ''DNM'', 1, 0))
                       + SUM (DECODE (result, ''INCOMPLETE'', 1, 0))
                          Total
                  FROM employees_vw a, pse_vw b
                 WHERE     a.emplid = b.emplid
                       AND status IN (''S'', ''I'', ''N'')
                       AND TYPE = ''PSE''
       report_query_b   VARCHAR2 (10000)
                           := ' 
    SELECT hub,
           TYPE,
           subtype,
           CASE
              WHEN Total = 0 OR Pass_1st = 0 THEN 0
              ELSE ROUND (Pass_1st / (Total) * 100, 2)
           END
              AS Pass_1st_percent,
           CASE
              WHEN Total = 0 OR Pass_2nd = 0 THEN 0
              ELSE ROUND (Pass_2nd / (Total) * 100, 2)
           END
              AS Pass_2nd_percent,
           CASE
              WHEN Total = 0 OR Pass_3rd = 0 THEN 0
              ELSE ROUND (Pass_3rd / (Total) * 100, 2)
           END
              AS Pass_3rd_percent,
           CASE
              WHEN Total = 0 OR DNM = 0 THEN 0
              ELSE ROUND (DNM / (Total) * 100, 2)
           END
              AS DNM,
           CASE
              WHEN Total = 0 OR Incomplete = 0 THEN 0
              ELSE ROUND (Incomplete / (Total) * 100, 2)
           END
              AS Incomplete
      FROM (  SELECT hub,
       TYPE,
           subtype
                      SUM (DECODE (result, ''Pass_on_1st'', 1, 0)) Pass_1st,
                       SUM (DECODE (result, ''Pass_on_2nd'', 1, 0)) Pass_2nd,
                       SUM (DECODE (result, ''Pass_on_3rd'', 1, 0)) Pass_3rd,
                       SUM (DECODE (result, ''DNM'', 1, 0)) DNM,
                       SUM (DECODE (result, ''INCOMPLETE'', 1, 0)) Incomplete,
                         SUM (DECODE (result, ''Pass_on_1st'', 1, 0))
                       + SUM (DECODE (result, ''Pass_on_2nd'', 1, 0))
                       + SUM (DECODE (result, ''Pass_on_3rd'', 1, 0))
                       + SUM (DECODE (result, ''DNM'', 1, 0))
                       + SUM (DECODE (result, ''INCOMPLETE'', 1, 0))
                          Total
                  FROM employees_vw a, pse_vw b
                 WHERE     a.emplid = b.emplid
                       AND status IN (''S'', ''I'', ''N'')
                     AND TYPE = ''PSE''
       report_query     VARCHAR2 (10000);
    BEGIN
       IF v_hub <> '*'
       THEN
          report_query := report_query_a;
       ELSE
          report_query := report_query_b;
       END IF;
       IF v_hub <> '*'
       THEN
          report_query :=
             report_query || ' and hub = ''' || v_hub || ''' GROUP BY hub )
    GROUP BY hub,
             Pass_1st,
             Pass_2nd,
             Pass_3rd,
             Total,
             DNM,
             Incomplete';
       END IF;
       IF v_type <> '*' AND v_subtype <> '*' AND v_hub <> '*'
       THEN
          report_query :=
                report_query
             || ' and hub = '''
             || v_hub
             || ''' and type = '''
             || v_type
             || ''' and subtype= '''
             || v_subtype
             || '''
              GROUP BY hub,
                     TYPE,
                     subtype,
            GROUP BY hub,
                     TYPE,
                     subtype,
                     Pass_1st,
                     Pass_2nd,
                     Pass_3rd,
                     Total,
                     DNM,
                     Incomplete';
       END IF;
       OPEN retval FOR report_query;
       RETURN retval;
    END;
    Edited by: user10821012 on May 13, 2010 9:56 AM

    What you are seeing is pretty common. When I work with dynamic SQL I usually include some logic to put the dyanmic SQL into a string and a means to see what was generated, something like (untested here)
      v_sql_c := 'select * from dual';
      open refcur for v_sql_c;
    exception
      when others then
         insert into work_table (clob_column) values (v_sql_c);so I can later query the table to get to the generated SQL for debugging, something like
      select * from work_table;I also try to write dynamic SQL so I can paste it from the work table right into query execution without editing.

  • Data passed from Java to a PL/SQL function

    OK, I am at the beginner-to-intermediate level when it comes to PL/SQL...and a virtual novice when it comes to Java, so please forgive me if my question seems strange or naive.
    We are developing a Java-based web app. Some of the screens are reminiscent of a spreadsheet-type layout--potentially LOTS of rows and LOTS of columns (actually, an open-ended # of rows/columns--the rows represent a particular 'thing' and the columns represent the dates on which that 'thing' occurred), where the user can check off any and all the cells that apply. We are also 'auditing' all database activity (who did what to the data, and when). The approach we have chosen is as follows: When the user clicks save, the first thing we do is 'inactivate' all of the existing active rows in the db for that screen, whether or not they have changed(i.e., there is an 'active' flag that we set to false & we also save the user id of the person making the change and the date time of the change). Then the Java code calls the database once per row/contiguous column unit. For instance, on a single row, if the user checks off columns 1-4 and 7-15 and column 21 the Java code will send three calls to the database for that row with info about the start/stop column for each unit.
    OK--here is my concern...the majority of the time there will be a reasonably small #of 'units'. Occasionally there will be a moderate, and once in awhile a LARGE # of 'units'. So, let's take an extreme case and say that currently the db has 200 such row/contiguous column units for a given screen. The user goes into that screen and adds the 201st unit, then clicks Save. Java calls the db to first inactivate the 200 rows. Then one by one Java calls the db to add the rows back in, only on row #40, the internet connection is lost. The only way the user can tell what happened is to look at the entire screen and reverify ALL the data in order to tell what got saved/resaved and what didn't. Obviously this is a bad situation that we want to avoid.
    I should add that the reason this approach was chosen is that the Java developers thought it would be way too complex in this situation to track the changes the user made on the screen, sort out what has been added/modified/deleted, and only call the db for changes.
    So given this background, can anyone offer any suggestions/ideas on how we can prevent unintended data loss given the auditing constraints and concern about minimizing complexity on the Java side (redesigning the GUI screen is NOT an option, as the users are very attached to this design)?
    Is there a way for Java to pass a multidimensional (& variable-sized) array to a PL/SQL function? Can Oracle's complex (row, table) data types be used in a function's parameter string, and if so...how?...Or else is there some way we can send a single call to the db on a screen like this one? We thought of calling the db once and sending one very large string packed with all the data (could get very big, not sure of Oracle's limatations on passed data--is it 32K for varchar2? )
    Advice, ideas, even random thoughts would be greatly appreciated!

    Tracy,
    <quote>… only on row #40, the internet connection is lost. The only way the user can tell what happened is to look at the entire screen and reverify ALL the data in order to tell what got saved/resaved and what didn't</quote>
    That would be "the only way" if the Java programmers had decided to totally bury the error … what should happen here is the end-user should get a proper error message … no need to re-verify at this point since all bets are off (in fact, nothing should’ve been changed in the database).
    Nonetheless, your concerns regarding the chosen approach are valid … making multiple calls to the database after a Save makes controlling a business transaction rather complex (in an n-tier system) … they should make one call only to the database passing in all the data to be saved … one database transaction … either all changes get applied or none.
    The fact that lots of data may need to be passed in for one Save is of no relevance … if you have to carry 500Kb of data for that screen then, well, you have to do it … 1 bucket of 500Kb or 50 buckets of 10Kb? … it doesn’t really matter as far as the actual transport part is concerned.
    As already answered, one can pass complex types in pl/sql … so one database call per Save would be my first random thought. There are lots of suspect things in here … some things you didn’t mentioned at all … like how is concurrency addressed? … have you/they implemented some sort of optimistic locking mechanism? Of course the architecture of your system won’t be solved in a forum … so, finding a good system/data/Oracle architect on site for the project would be my second random thought.
    PS. One last random thought … fight off that idea of packing and sending large strings (XML or not) … if the data is structured then contemplate XML for no more than few seconds.

Maybe you are looking for

  • End routine to populate Info-cube.

    Hi , Is it possible to load fileds of a Info-cube using End routines in the following scenairos. 1.Loading fields of info-cube by referencing/using a master data table in End routine. 2.Loading fields of info-cube by referencing/using a DSO fields  i

  • Could not complete your request because the file is not compatible with this version of photoshop

    Hello, I'm a beginner in PS. I was edit TIFF file in PS. Size of file is 21x89.1(22.6 MB). Then suddenly power - cuted. But after 5 min turn on PC and PS can't open my TIFF file. Error is (could not complete your request because the file is not compa

  • Can't see any orders in Mobile Device

    Hi all, As described in topic "How to deploy MAM 2.5 into MI Server", I have just installed MI and deployed MAM 2.5 into an WebAS 6.40 SP13. I have also, with the help of the functional guys from my team, followed through the Server Side Configuratio

  • I need a driver for my Deskjet 1280 on Windows 7 64Bit

    I am still having a problem finding a driver for my HP Deskjet 1280 Printer Im using Windows 7 64Bit operating system. Can anyone assist please. I need it for my new HP Pavilion P6-2021UK computer. Rod This question was solved. View Solution.

  • Color Distortion with Mac Lion, CS6, Epson R2880 printer

    When I had Snow Leopard, CS4 and Epson R2280, I got prints that looked like what was on the monitor. When I bought a new Mac which switched my operating system to Lion, and Adobe recommended  I buy CS5 which I did.  When I went to print, trying every