Compound trigger behaves different when it's the first insertion and when it's not
<p>I have the runnable code below that is just printing messages and is intriging me. I do not have any other trigger related to this table (I do a drop table to reinforce it), but when the compound trigger is fired for the first time (first insertion on the table) the following behavers occurs:</p>

<ul>
<li>Test 1) The BEFORE STATEMENT runs twice for the first insertion but just once after that</li>
</ul>

<blockquote>
  <p>BEFORE STATEMENT IS Qty: 0 BEFORE STATEMENT IS Qty: 0</p>
</blockquote>

<ul>
<li>Test 2) The variable qty have NULL value for the first insertion and the expected value after that.</li>
</ul>

<blockquote>
  <p>AFTER STATEMENT IS Qty:</p>
</blockquote>

<p>Can you explain this behavior?</p>

<hr>

<pre><code>SET SERVEROUTPUT ON;    
--DROP TABLE teste_var_global;

CREATE TABLE teste_var_global(
  idVal NUMBER
);


create or replace TRIGGER compounder
FOR UPDATE OR INSERT OR DELETE ON teste_var_global
COMPOUND TRIGGER

    qty NUMBER;

     BEFORE STATEMENT IS
      BEGIN
        SELECT COUNT(*) INTO qty FROM teste_var_global;
        DBMS_OUTPUT.PUT_LINE('BEFORE STATEMENT IS');
        DBMS_OUTPUT.PUT_LINE('Qty: ' || qty);
     EXCEPTION
      WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('(' || SQLCODE || ') - ' || SQLERRM);
     END BEFORE STATEMENT;

     BEFORE EACH ROW IS
     BEGIN
        DBMS_OUTPUT.PUT_LINE(CHR(9)||'BEFORE EACH ROW IS');
       IF INSERTING THEN 
          DBMS_OUTPUT.PUT_LINE(CHR(9)||':new.idVal ' || :new.idVal);
       ELSIF DELETING THEN 
          DBMS_OUTPUT.PUT_LINE(CHR(9)||':old.idVal ' || :old.idVal);
       ELSE --UPDATING 
          DBMS_OUTPUT.PUT_LINE(CHR(9)||':old.idVal ' || :old.idVal);
          DBMS_OUTPUT.PUT_LINE(CHR(9)||':new.idVal ' || :new.idVal);
        END IF;
     END BEFORE EACH ROW;

     AFTER EACH ROW IS
     BEGIN
       DBMS_OUTPUT.PUT_LINE(CHR(9)||'AFTER EACH ROW IS');
       IF INSERTING THEN 
          DBMS_OUTPUT.PUT_LINE(CHR(9)||':new.idVal ' || :new.idVal);
          DBMS_OUTPUT.NEW_LINE();
          qty:= qty + 1; -- increment
       ELSIF DELETING THEN 
          DBMS_OUTPUT.PUT_LINE(CHR(9)||':old.idVal ' || :old.idVal);
          DBMS_OUTPUT.NEW_LINE();
          qty:= qty -1; -- decrement
       ELSE --UPDATING 
          DBMS_OUTPUT.PUT_LINE(CHR(9)||':old.idVal ' || :old.idVal);
          DBMS_OUTPUT.PUT_LINE(CHR(9)||':new.idVal ' || :new.idVal);
          DBMS_OUTPUT.NEW_LINE();
       END IF;
     END AFTER EACH ROW;

    AFTER STATEMENT IS
    BEGIN
       DBMS_OUTPUT.PUT_LINE('AFTER STATEMENT IS');
       DBMS_OUTPUT.PUT_LINE('Qty: ' || qty);
       DBMS_OUTPUT.NEW_LINE();
     END AFTER STATEMENT;
   END;
/

-- Test 1, will fire BEFORE STATMENT twice when the first row is inserted
INSERT INTO teste_var_global
(
SELECT 1 FROM DUAL
UNION ALL
SELECT 2 FROM DUAL
UNION ALL
SELECT 3 FROM DUAL
)
/

--Test 2, qty will become NULL when this trigger is fired for the first time
--drop the table and rerun the trigger before executing this command
INSERT INTO teste_var_global VALUES(1);
/
</code></pre>