sql >> Databasteknik >  >> RDS >> Oracle

Oracle Select * returnerar rader men Select count(1) returnerar 0

Fel resultat kan orsakas av korruption, buggar och funktioner som tyst ändrar SQL-satser.

  1. Korrupt index. Mycket sällan blir ett index korrupt och data från ett index matchar inte data från en tabell. Detta orsakar oväntade resultat när frågeplanen ändras och ett index används, men allt ser normalt ut för olika frågor som använder tabellåtkomst. Ibland kan det åtgärdas genom att helt enkelt bygga om objekt. Om det inte gör det måste du skapa ett helt reproducerbart testfall (inklusive data); antingen publicera det här eller skicka det till Oracle Support. Det kan ta många timmar att spåra detta.
  2. Bug. Mycket sällan kan en bugg göra att frågor misslyckas när data returneras eller ändras. Återigen, ett fullt reproducerbart testfall krävs för att diagnostisera detta, och det kan ta ett tag.
  3. Funktion som växlar SQL Det finns några sätt att på ett transparent sätt ändra SQL-satser. Titta på Virtual Private Database (VPD), DBMS_ADVANCED_REWRITE och SQL Translation Framework.

För att utesluta #3 visar koden nedan dig ett av de onda sätten att göra detta och hur du upptäcker det. Skapa först schemat och lite 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;

Till en början fungerar allt som förväntat:

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

Då gör någon så här:

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 är resultaten "fel":

SQL> ALTER SESSION SET query_rewrite_integrity = trusted;

Session altered.

SQL> SELECT COUNT(1) FROM TRACKING;

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

Detta kan förmodligen upptäckas genom att titta på förklara planen. I exemplet nedan, predikatet 2 - filter(ROWNUM=1) är en ledtråd om att något är fel, eftersom det predikatet inte finns i den ursprungliga frågan. Ibland kommer avsnittet "Anteckningar" i förklaraplanen att berätta exakt varför det omvandlades, men ibland ger det bara ledtrådar.

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 orelaterade notering - använd alltid COUNT(*) istället för COUNT(1) . COUNT(1) är en gammal myt som ser ut som lastkultprogrammering.)



  1. Kategorisera automatisk kompletteringsdata

  2. CakePHP 3:Bästa praxis för tillfälliga SQL-tabeller

  3. Hämta alla överordnade/barnposter från databasen på Laravel (hierarkiska data)

  4. MySQL atomoperationer och bordslåsning