Avatar billede kegel Nybegynder
08. februar 2000 - 09:49 Der er 13 kommentarer og
1 løsning

Dato fejl

I et system som jeg - meget nødtvunget - yder support på findes en sql script som ser således ud:

select *
from  contrib
where  inmsuranceprogramid = <parameterværdi> and to_date(startperiod,'dd-mm-yyyy') > trunc(sysdate)

Omtalte script har altid fungeret - indtil efter år 2000.Herefter fungerer det kun en gang imellem! Til tider kommer der en fejlmeddelse som fortæller, at dato formattet ikke en langt nok.

Jeg skal for en god ordens skyld fortælle to ting:
For det første bliver session dato formattet (NVL) sat til dd-mm-yyyy.
For det andet er feltet startperiod defineret som varchar2 og kan indeholde en 'talværdi' fx. 13, tegnet '-' og altså en dato.

ja, ja jeg ved det - tåbeligt database design med en attribut der kan fortolkes på mange forskellige måder, men jeg har som nævnt ikke udviklet lortet. Faktisk er jeg primært Delphi programmør og ikke den store Oracle haj, men selv jeg kunne næppe finde på ovenstående design ;-)

Mit spørgsmål er - hvad fanden kan være årsagen til en sådan fejl? Kan Oracle's sql parse være involveret i nævnte problemstilling?

Lad mig afslutningsvis nævne, at omtalte sql script fungere upåklagelig på vores test database, men hvis jeg tager et kopi via CREATE TABLE Tmp_Contrib as (select * from contrib)så virker omtalte sql-script ikke!? Eftersom indholdet af den oprindelige contrib og backup kopien er den samme kan det vel næppe være datagrundlaget som kan medfører fejlen?!
Avatar billede gollum Nybegynder
08. februar 2000 - 10:11 #1
Vi fik i forbindelse med år 2000 besked fra oracle om at yyyy skulle erstattes med rrrr.

Om det hjælper på dit problem ved jeg ikke.
Avatar billede jhh Nybegynder
08. februar 2000 - 10:12 #2
Jeg tror kun det kan være startperiod der laver unoder. Er du 100% sikker på at startperiod indeholder valide datoer i DD-MM-YYYY formatet i *samtlige* de rækker du SELECT'er?

Prøv evt. blot at køre
SELECT to_date(startperiod,'dd-mm-yyyy') FROM contrib
og se hvad der sker.

Session dato formatet burde ikke betyde noget i denne her sammenhæng, da der netop benyttes explicit konvertering mellem formaterne. Det er kun hvis man bruger implicit format konvertering, at session formatet er vigtigt (fx. WHERE datofelt = varchar2felt).

/Jesper
Avatar billede jhh Nybegynder
08. februar 2000 - 10:15 #3
gollum: rrrr er til brug på klienten, så århundrede udfyldes korrekt, hvis brugeren kun taster yy.

/Jesper
Avatar billede dmk Nybegynder
08. februar 2000 - 10:18 #4
Jeg skal lige forstå din dato-strengs format.
Har jeg forstået det rigtigt, hvis den fx. ser sådan ud: '10-21-09-1999' ? Og ser din streng
ALTID sådan ud? Eller er der nogle gange, hvor den kun indeholder datoen ('21-09-1999')?

Jeg kan ikke umiddelbart få den til at æde den første streng. Men hvis jeg indsætter begge strenge i en tabel, og laver en query hvor der kommer andre where-clauses på, som udelukker den illegale streng, så får jeg ingen problemer, da ORACLE åbenbart vælger at evaluere de(n) andre where-clauses først, og ikke evaluerer to_date for de rows der ikke opfylder dem. Det vil sige, at hvis jeg indsætter følgende i min database:

  TIMESTAMP:              ID:
'10-10-1999'              1
'gnyfferblaf'            2

Så kan jeg altså godt få følgende forspørgsel til at virke:
select * from TestDate where to_date(TimeStamp,'dd-mm-yyyy') < trunc(sysdate) and id=1

Men ikke:
select * from TestDate where to_date(TimeStamp,'dd-mm-yyyy') < trunc(sysdate) and id=2


Kan det være sådan noget, eller har jeg misforstået dit format?

DMK
Avatar billede kegel Nybegynder
08. februar 2000 - 10:31 #5
Til JHH

Nej, jeg er helt sikker på at samtlige rækker i CONTRIB tabellens startperiod attribut IKKE indeholder en streng med et valid dato format. Problemet med designet er nemlig, at strengen nogle gange kun indeholder et tal fx. 83 (men altså ikke nogen dato format). Det som sker er at InsuranceprogramId udvælger de rækker i CONTRIB tabellen som indeholder strenge på et valid dato format. Jeg har naturligvis først undersøgt om det så også er tilfældet på det konkrete insuranceprogramId, der i første omgang udløste fejlen.

Umiddelbart er sql parseren under mistanke fordi den eneste grund til, at sql-scriptet ikke virker på et eksakt kopi af tabellen kunne være at rækkerne indsættes i en anden rækkefølge og parseren derfor fortolker indholdet af tabellen anderledes(?)
Avatar billede jhh Nybegynder
08. februar 2000 - 10:33 #6
Hvis startperiod indeholder 'xx-dd-mm-yyyy' som DMK skriver, så kan du ikke select'e to_date(startperiod)

Du skal istedet først have fat i dato-delen af strengen: SUBSTR(startperiod,4)
- den kan du så lave en TO_DATE på.

Altså: TO_DATE(SUBSTR(startperiod,4),'DD-MM-YYYY')

/Jesper
Avatar billede dmk Nybegynder
08. februar 2000 - 10:35 #7
Det lyder rigtigt hvad JHH siger. Det er også nogenlunde hvad jeg har fået testet mig frem til.
Men er det nu også sådan dit format ser ud? Hvis ikke, kan du så ikke sætte nogle eksempler ind på, hvad feltet indeholder?

DMK
Avatar billede kegel Nybegynder
08. februar 2000 - 10:51 #8
Jeg kan se, at i misforstår indholdet af de enkelte rækker. Det kunne eksempelvis se således ud:

InsuranceprogramId    StartPeriod
          1          1
          2          '01-01-1999'
          3          15%
          4          '31-12-2000'
          5          '-'

som det fremgår vil sqlscriptet selvfølgelig fejle, hvis insuranceprogram id IKKE er 2 eller 4 fordi de øvrige strenge ikke opfylder datoformattet. Problemet opstår også når insuranceprogramId = 2 eller 4. Som tidligere nævnt så bestod min første undersøgelse i at fastslå, hvorvidt de enkelte række også indeholdte en valid dato streng på den konkrete insuranceprogramid - det gør de. Selv om database designet stinker så har denne sammenblanding af betydning i startperiod fungerer før. Det mærkelige er nemlig, at det også engang imellem virker på nuværende tidspunkt. Kan der være pillet ved nogle oracle konfigurations parameter som påvirker eksekveringen af scriptet fx. rule baset parsing af sql scriptet?
Avatar billede dmk Nybegynder
08. februar 2000 - 10:58 #9
Ud fra fejlbeskeden og hvad din database indeholder, så lyder det altså meget som om den prøver at parse en streng der ikke er en dato.

Kan du for en god ordens skyld ikke sætte en  "and length(StartPeriod)=10" på din query? Hvis det stadig går galt, så begynder jeg at tro på, at det ikke er fordi du parser en ikke-dato-streng.

DMK
Avatar billede kegel Nybegynder
08. februar 2000 - 11:03 #10
Det vil jeg prøve DMK. Jeg vender tilbage når jeg har haft tid til at se nærmere på problemet. Jeg har som foreslået ændret på where klausulen således at den ser således ud:

where to_date(startperiod,'dd-mm-yyyy') > trunc(sysdate)
  and  insuranceprogramId = <parameterværdi>

Det gik godt! Men hvorfor fanden skulle sql parseren lige pludselig begynde at opfører sig anderledes når den evaluere et ellers validt datagrundlag?
Avatar billede kegel Nybegynder
08. februar 2000 - 11:13 #11

Jeg har nu også forsøgt en length check, men den fejler stadigvæk. Det konkrete insuranceprogramid har udlukkende strenge med det korrekte dato format og de er alle 10 tegn lange. Sidstnævnte har jeg også undersøgt på baggrund af dit forslag.

mystisk
Avatar billede dmk Nybegynder
08. februar 2000 - 11:18 #12
Nu er jeg ved at være blank.

Prøv følgende i stedet:

select * from
(select * from contrib where inmsuranceprogramid = <parameterværdi> )
where to_date(startperiod,'dd-mm-yyyy') > trunc(sysdate)

Jeg ved ikke om evaluerings rækkefølgen for where kan have noget at gøre med det. Hvis ORACLE nogle gange kan finde på, at evaluere to_date før inmsuranceprogramid, så vil det naturligvis gå galt.

Med ovenstående sql er du sikker på, at det ikke vil ske.

DMK
Avatar billede dmk Nybegynder
08. februar 2000 - 11:38 #13
Æhh, virkede det?

DMK
Avatar billede kegel Nybegynder
08. februar 2000 - 11:40 #14
Ja dit sql script virker. Hvorvidt det vil vedblive med det er usikkert, men jeg har accepteret svaret fordi din hjælp har kastet lys over hele problemstilingen.

Tak for hjælpen dmk
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester