sql >> Database teknologi >  >> RDS >> Oracle

Oracle Select * returnerer rækker, men Select count(1) returnerer 0

Forkerte resultater kan være forårsaget af korruption, fejl og funktioner, der lydløst ændrer SQL-sætninger.

  1. Korrupt indeks. Meget sjældent bliver et indeks korrupt, og dataene fra et indeks matcher ikke dataene fra en tabel. Dette forårsager uventede resultater, når forespørgselsplanen ændres, og et indeks bruges, men alt ser normalt ud for forskellige forespørgsler, der bruger tabeladgang. Nogle gange kan genbygning af objekter løse dette. Hvis det ikke gør det, skal du oprette en fuldt reproducerbar testcase (inklusive data); enten post det her eller send det til Oracle Support. Det kan tage mange timer at spore dette.
  2. Bug. Meget sjældent kan en fejl forårsage, at forespørgsler mislykkes, når data returneres eller ændres. Igen, et fuldt reproducerbart testtilfælde er påkrævet for at diagnosticere dette, og det kan tage et stykke tid.
  3. Funktion, der skifter SQL Der er et par måder at ændre SQL-sætninger på transparent. Kig ind i Virtual Private Database (VPD), DBMS_ADVANCED_REWRITE og SQL Translation Framework.

For at udelukke #3 viser koden nedenfor dig en af ​​de onde måder at gøre dette på, og hvordan du opdager det. Først skal du oprette skemaet og nogle data:

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;

I starten fungerer alt som forventet:

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

Så gør nogen dette:

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

Nu er resultaterne "forkerte":

SQL> ALTER SESSION SET query_rewrite_integrity = trusted;

Session altered.

SQL> SELECT COUNT(1) FROM TRACKING;

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

Dette kan sandsynligvis opdages ved at se på forklaringsplanen. I eksemplet nedenfor er prædikatet 2 - filter(ROWNUM=1) er et fingerpeg om, at noget er galt, da det prædikat ikke er i den oprindelige forespørgsel. Nogle gange vil afsnittet "Noter" i forklaringsplanen fortælle dig præcis, hvorfor det blev transformeret, men nogle gange giver det kun ledetråde.

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.

(På en ikke-relateret note - brug altid COUNT(*) i stedet for COUNT(1) . COUNT(1) er en gammel myte, der ligner cargo-kultprogrammering.)



  1. Hvordan afgør man, om en MySQL-forespørgsel er gyldig?

  2. ORA-01652:ude af stand til at forlænge temp-segmentet med 128 i tablespace SYSTEM:Hvordan forlænges?

  3. Fuld tekst Søgeresultat svarende til Mysql Like '%%' forespørgsel

  4. -bash:pg_dump:kommando ikke fundet