OCIErrorGet and multiple error handling for OCI_ERROR

Oracle guarantees that only a single error will be returned per call of OCIErrorGet() (note the singular):

Returns an error message in the buffer provided and an Oracle Database error code.
...
Multiple diagnostic records can be retrieved by calling OCIErrorGet() repeatedly until there are no more records (OCI_NO_DATA is returned). OCIErrorGet() returns at most a single diagnostic record.

Whether you need a similar loop or nor depends on what (PL/)SQL code you're calling. Simple SQL statements will generally only return one error code; for e.g.:

SQL> select 1/0 from dual;
select 1/0 from dual
        *
ERROR at line 1:
ORA-01476: divisor is equal to zero

However, if PL/SQL is involved more may be returned:

SQL> begin
  2     raise_application_error(-20000, 'error');
  3  end;
  4  /
begin
*
ERROR at line 1:
ORA-20000: error
ORA-06512: at line 2

Here the actual error that you're interested in would be ORA-20000. Oracle's exception propagation works from internal block to external block so, assuming you're not dealing with compilation errors, the original cause for the error will be the first exception. If you do catch and re-raise an exception this changes. The example Oracle gives in the docs is:

SQL> begin
  2    dbms_output.put_line(1/0);  -- handled
  3  exception when zero_divide then
  4    dbms_output.put_line(1/0 || ' is undefined');  -- not handled
  5  end;
  6  /
begin
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at line 4
ORA-01476: divisor is equal to zero

DBMS_OUTPUT.PUT_LINE is a procedure hence the same exception appearing twice; note that it's still the first exception that you're interested in.

To answer your questions:

You don't need a similar loop; you only should use one if you want to get more than one error code.

If multiple errors are returned you should probably throw the first error code because of the method in which Oracle propagates exceptions; this is essentially a judgement call you need to make though. It's unclear from the docs whether OCIErrorGet() returns the most recent or the earliest exception first; you might need to throw the last exception.