sql >> Base de Datos >  >> RDS >> Oracle

Oracle Select * devuelve filas pero Select count (1) devuelve 0

Los resultados erróneos pueden ser causados ​​por corrupción, errores y funciones que cambian silenciosamente las declaraciones SQL.

  1. Índice corrupto. En muy raras ocasiones, un índice se corrompe y los datos de un índice no coinciden con los datos de una tabla. Esto provoca resultados inesperados cuando cambia el plan de consulta y se usa un índice, pero todo parece normal para diferentes consultas que usan acceso a tablas. A veces, simplemente reconstruir objetos puede solucionar esto. Si no es así, deberá crear un caso de prueba completamente reproducible (incluidos los datos); publíquelo aquí o envíelo a Oracle Support. Puede tomar muchas horas rastrear esto.
  2. Error. En muy raras ocasiones, un error puede hacer que las consultas fallen al devolver o cambiar datos. Nuevamente, se requiere un caso de prueba completamente reproducible para diagnosticar esto, y puede llevar un tiempo.
  3. Característica que cambia SQL Hay algunas formas de alterar de forma transparente las sentencias SQL. Mire en Virtual Private Database (VPD), DBMS_ADVANCED_REWRITE y SQL Translation Framework.

Para descartar el #3, el siguiente código le muestra una de las formas malvadas de hacer esto y cómo detectarlo. Primero, crea el esquema y algunos datos:

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;

Al principio, todo funciona como se esperaba:

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

Entonces alguien hace esto:

begin
  sys.dbms_advanced_rewrite.declare_rewrite_equivalence(
    'april_fools',
    'SELECT COUNT(1) FROM TRACKING',
    'SELECT 0 FROM TRACKING WHERE ROWNUM = 1',
    false);
end;
/

Ahora los resultados son "incorrectos":

SQL> ALTER SESSION SET query_rewrite_integrity = trusted;

Session altered.

SQL> SELECT COUNT(1) FROM TRACKING;

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

Esto probablemente se pueda detectar mirando el plan de explicación. En el siguiente ejemplo, el Predicado 2 - filter(ROWNUM=1) es una pista de que algo anda mal, ya que ese predicado no está en la consulta original. A veces, la sección "Notas" del plan de explicación le dirá exactamente por qué se transformó, pero a veces solo da 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.

(En una nota no relacionada, siempre use COUNT(*) en lugar de COUNT(1) . COUNT(1) es un viejo mito que parece programación de culto de carga).