Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Oracle Select * retorna linhas, mas Select count(1) return 0


Resultados errados podem ser causados ​​por corrupção, bugs e recursos que alteram silenciosamente as instruções SQL.
  1. Índice corrompido. Muito raramente um índice fica corrompido e os dados de um índice não correspondem aos dados de uma tabela. Isso causa resultados inesperados quando o plano de consulta é alterado e um índice é usado, mas tudo parece normal para consultas diferentes que usam acesso à tabela. Às vezes, simplesmente reconstruir objetos pode corrigir isso. Caso contrário, você precisará criar um caso de teste totalmente reproduzível (incluindo dados); poste-o aqui ou envie-o ao Suporte da Oracle. Pode levar muitas horas para rastrear isso.
  2. Erro. Muito raramente um bug pode fazer com que as consultas falhem ao retornar ou alterar dados. Novamente, um caso de teste totalmente reproduzível é necessário para diagnosticar isso e pode demorar um pouco.
  3. Recurso que alterna SQL Existem algumas maneiras de alterar de forma transparente as instruções SQL. Analise o Virtual Private Database (VPD), DBMS_ADVANCED_REWRITE e o SQL Translation Framework.

Para descartar o número 3, o código abaixo mostra uma das maneiras malignas de fazer isso e como detectá-la. Primeiro, crie o esquema e alguns dados:
CREATE TABLE TRACKING (
  A_ID NUMBER,
  D_CODE NUMBER,
  HOD NUMBER,
  ADR_CNT NUMBER,
  TTL_CNT NUMBER,
  CREATED DATE,
  MODIFIED DATE
);
CREATE INDEX HOD_D_CODE_IDX ON TRACKING (HOD, D_CODE);
CREATE UNIQUE INDEX TRACKING_PK ON TRACKING (A_ID, D_CODE, HOD);
CREATE INDEX MOD_DATE_IDX ON TRACKING (MODIFIED);
ALTER TABLE TRACKING ADD CONSTRAINT TRACKING_PK PRIMARY KEY (A_ID, D_CODE, HOD);

insert into tracking values (1,2,3,4,5,sysdate,sysdate);
commit;

A princípio, tudo funciona como esperado:
SQL> SELECT * FROM TRACKING;

      A_ID     D_CODE        HOD    ADR_CNT    TTL_CNT CREATED   MODIFIED
---------- ---------- ---------- ---------- ---------- --------- ---------
         1          2          3          4          5 17-JUN-16 17-JUN-16

SQL> SELECT COUNT(1) FROM TRACKING;

  COUNT(1)
----------
         1

Então alguém faz isso:
begin
  sys.dbms_advanced_rewrite.declare_rewrite_equivalence(
    'april_fools',
    'SELECT COUNT(1) FROM TRACKING',
    'SELECT 0 FROM TRACKING WHERE ROWNUM = 1',
    false);
end;
/

Agora os resultados estão "errados":
SQL> ALTER SESSION SET query_rewrite_integrity = trusted;

Session altered.

SQL> SELECT COUNT(1) FROM TRACKING;

  COUNT(1)
----------
         0

Isso provavelmente pode ser detectado olhando para o plano de explicação. No exemplo abaixo, o Predicado 2 - filter(ROWNUM=1) é uma pista de que algo está errado, já que esse predicado não está na consulta original. Às vezes, a seção "Notas" do plano de explicação lhe dirá exatamente por que ele foi transformado, mas às vezes apenas fornece pistas.
SQL> explain plan for SELECT COUNT(1) FROM TRACKING;

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------
Plan hash value: 1761840423

------------------------------------------------------------------------------------
| Id  | Operation         | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                |     1 |     2 |     1   (0)| 00:00:01 |
|   1 |  VIEW             |                |     1 |     2 |     1   (0)| 00:00:01 |
|*  2 |   COUNT STOPKEY   |                |       |       |            |          |
|   3 |    INDEX FULL SCAN| HOD_D_CODE_IDX |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(ROWNUM=1)

15 rows selected.

(Em uma nota não relacionada - sempre use COUNT(*) em vez de COUNT(1) . COUNT(1) é um mito antigo que parece programação de culto de carga.)