Los resultados erróneos pueden ser causados por corrupción, errores y funciones que cambian silenciosamente las declaraciones SQL.
- Í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.
- 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.
- 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).