Using unix array in sql

Hi all,

I have declared an array in unix as below.

 #!/bin/ksh
arr=()
for i in {0..4}
do
    arr=$i;
done

.

i want to insert these array variables into the oracle table.can you guys please help me in doing this. my code is as below.

value=`sqlplus -s fos/fos << EOF

begin
for j in 0..4 loop
insert into test values ('${arr[j]}');
end loop;
end;
/
exit;
EOF` 

its inserting 5 rows with value 4.
but it should insert

 0
1
2
3
4 

.

---------- Post updated 06-24-12 at 02:11 AM ---------- Previous update was 06-23-12 at 12:41 PM ----------

hi guys,
please help me i need it badly.

That will not work, because ${arr[j]} will get expanded in the here document, before it is passed to sqlplus, so the j in the SQL loop has nothing to do with the j in the array element..

so can you please tell me what should i do to make it work?

Try something like this:

#!/bin/ksh
arr= ( $(seq 0 4) )
value=$( (
   printf "begin\n"
   printf "insert into test values ('%s');\n" "${arr[@]}"
   printf "end;\nexit;\n") | sqlplus -s fos/fos )

---------- Post updated at 09:43 AM ---------- Previous update was at 09:22 AM ----------

BTW: the brace expansion {0..4} you used to create your array is a bash thing, and will not work in ksh you need to use $(seq 0 4) for ksh.

1 Like

Try this for running SQL/Plus in a co-process to reduce overhead. I modified an existing example script I had created to illustrate using the co-process. It could use some error handling but you get the idea. For this example it may be overkill, but assuming you want to loop through array elements and perform some processing before inserting, this sets up a framework. Output is logged too:

In SQL/Plus:

SQL> create table test (
  2  a integer
  3  )
  4  ;

Table created.

Code:

#!/bin/ksh
##
##  Coprocess example.  Start SQL/Plus in the background, and communicate
##  with it via a pipe as long as you need it.  This saves overhead of
##  starting it multiple times.  It stays running while we need it.
##
##  This example reads an array and inserts a row for each array element.
##
##  print -p to send to the coprocess,
##  read -p to read from it a line at a time.
##

output=""                    ## Output from SQL/Plus goes here.
set -f output                ## Don't do filename expansion on this variable.
                             ##  For when an error from SQL/Plus contains
                             ##  a splat (*).
typeset -r LOGFILE=$0.log    ## Define a log file for SQL/Plus output.
typeset -r EOF="DONE"        ## Text used to indicate the end of
                             ##   SQL/Plus output.
set -A test_array 0 1 2 3 4  ## Create and load array.
integer i=0                  ## Array element pointer.

## Create the log file or zero it out if it already exists.
> $LOGFILE

## Start sqlplus in a coprocess.
sqlplus -S login/password@database |&

##  Exit SQL/Plus if any of the following signals are received:
##  0=normal exit, 2=interrupt, 3=quit, 9=kill, 15=termination
trap 'print -p "exit;"' 0 2 3 9 15

##
## Loop through the array elements, inserting a row for each element.
##
## ${#test_array
[*]} is the number of elements in the array.
##
while (( i < ${#test_array
[*]} ))
do
  print "Inserting element $i of ${#test_array
[*]} - Value: ${test_array[$i]}" \
    >> $LOGFILE
  print -p "insert into test values (${test_array[$i]});"
  print -p "prompt $EOF;" ## This is an indicator that we reached the end
                          ## of output.  When we read a $EOF from
                          ## the coprocess we know we have no more output.

  ##  Read the output from SQL/Plus a line at a time. When $EOF
  ##  is read, that indicates the end of output.
  read -p output  # Prime the pump.
  while [[ "$output" != "$EOF" ]]
  do
    print "$output" >> $LOGFILE
    read -p output
  done
  # Increment the array pointer.
  (( i = $i + 1 ))
done

# Done reading the array.
print -p "commit;"

# Close the coprocess. Technically this is handled by the trap.
print -p "exit;"

exit 0

After running:

SQL> select * from test;

         A
----------
         0
         1
         2
         3
         4

5 rows selected.

Logfile contents:

$ cat *.log
Inserting element 0 of 5 - Value: 0

1 row created.

Inserting element 1 of 5 - Value: 1

1 row created.

Inserting element 2 of 5 - Value: 2

1 row created.

Inserting element 3 of 5 - Value: 3

1 row created.

Inserting element 4 of 5 - Value: 4

1 row created.

$
2 Likes

Nice clean example of using coprocesses gary_w.

Just hope OP is using ksh, as posted code is bash but with " #!/bin/ksh" at the top.

Thanks. Yeah I noticed that. Hopefully the OP will reply with what worked.

The code in post #1 should run in a recent ksh93, but since the the shebang is shifted one character to the right, it will just be treated as a comment and not be used anyway.

I noticed that too but the first line of the desired output example also was shifted over by a space so I figured it was a copy/paste formatting issue.

Thank you very much gary_w for this . i was breaking my head for this script.....thanks a lot.....

You bet. FYI - I just realized there is no logging of the commit result. You would want to check that with another loop to read the output of the commit and report if it is not successful. Perhaps put the reading of the output loop in a function? I'll leave that as an exercise. :slight_smile: