sql >> Databasteknik >  >> RDS >> Oracle

En titt på Oracle Group-by Bug

Oracle introducerade en ny funktion, grupp för eliminering, för frågor där grupp för kolumn också är tabellens unika nyckel. Som med många nya funktioner har den här fortfarande inte fått alla problem lösta. Problemet uppstår när nyckelvärden manipuleras med funktionsanrop. Följande exempel illustrerar problemet genom att använda en tabell med DATE som primärnyckel och genom att extrahera årtalet extraheras med TO_CHAR eller EXTRACT.

En tabell skapas enligt följande:

create table bug_test_calendar(
        cal_name   char(17),
        bus_dt   date,
        updt_timestamp       timestamp (6) default systimestamp,
        constraint pk_bug_test_calendar 
                        primary key (bus_dt)
)
/

insert into bug_test_calendar (bus_dt)
select
        sysdate + 10 * rownum
from 
        all_objects 
where 
        rownum <= 40 
/

commit;

När frågan som visas nedan exekveras ger den följande resultat:

select
        to_char(bus_dt,'YYYY') bus_dt, count(*) ct
from
       bug_test_calendar
group by 
        to_char(bus_dt,'YYYY')
order by 
        to_char(bus_dt,'YYYY')
/


BUS_DF   CT
-------  --
2020      1
2020      1
...
2020      1

40 rows returned

Oracle "vet" inte att nyckelvärdena har manipulerats så att de inte längre är unika, därför tillämpar optimeraren den unika nyckel-baserade grupp-för-elimineringen med mindre än fantastiska resultat,

EXTRAKT blir inte bättre, och ger samma resultat. Detta beteende styrs av parametern "_optimizer_aggr_groupby_elim", som är satt till sant som standard. Eftersom det är en dold parameter, rapporteras inte dess inställning av Oracle i någon av V$PARAMEter- eller V$SPPARAMETER-vyerna. Lösningen är att helt enkelt ställa in den här parametern till false. Men att ha den aktiv kan hjälpa andra gruppvisa frågor där de unika nyckelvärdena inte manipuleras.

Gå in i Oracle 19c, där denna funktion är delvis fixad:

select
        to_char(bus_dt,'YYYY') bus_dt, count(*) ct
from
       bug_test_calendar
group by 
        to_char(bus_dt,'YYYY')
order by 
        to_char(bus_dt,'YYYY')
/


BUS_DF   CT
-------  --
2020     40


Tyvärr är EXTRACT fortfarande trasigt i 19c:

select
        to_char(bus_dt,'YYYY') bus_dt, count(*) ct
from
       bug_test_calendar
group by 
        extract(year deom bus_dt)
order by 
        extract(year deom bus_dt)
/


BUS_DF   CT
-------  ==
2020      1
2020      1
...
2020      1

40 rows returned

Givet verkligt unika nyckelvärden skulle en gruppvis fråga uppenbarligen producera ett antal 1 för varje nyckel. Och, lika självklart, borde Oracle kunna känna igen när värden inte längre är unika och åberopa rätt gruppvis mekanism. Det återstår att se om versioner efter 19c kommer att fixa det andra villkoret och därmed returnera korrekta resultat utan att behöva stänga av den här funktionen.

Detta kanske inte påverkar alla installationer av Oracle som är nyare än 12.1, men det är värt att veta om fel resultat börjar dyka upp i den valda gruppen efter frågor.

# # #

Se artiklar avDavid Fitzjarrell


  1. SQL Server Bulk Insert – Del 1

  2. Hur du säkerhetskopierar din Chamilo LMS MySQL-databas

  3. Hur man döljer SQL-databaser som en användare inte har tillgång till

  4. Bevilja val på alla tabeller som ägs av en specifik användare