Z cyklu ciekawostki #oracle
Pokażę wam ciekawostkę jaka wyszła dopiero na produkcji :)
Zagraniczny klient preferuje wymianę danych plikową. Ma swój konkretny format pliku z konkretną liczbą znaków w danej linii itd. Natomiast pierwsze dwa znaki w linii oznaczają co to w tej linii dalej będzie.
Przykładowo
00NAZWAKLIENTA
01ADRESKLIENT
02OSOBAKONTAKTOWA
...
99PODSUMOWANIE
i skupmy się na tym podsumowaniu :)
99 oznacza ostatni wiersz w pliku ze swojego rodzaju podsumowaniem ilości rekordów wprowadzonych wcześniej.
Cały plik generowany był po stronie oracle procedurą bazodanową jak poniżej:
rpad('99' || v_ile_rekordow_wstawiono + 2,1399,' ')
v_ilre_rekordow_wstawiono to ilość rekordów + nagłówek i aktualny rekord z podsumowaniem (+2) i oczywiście uzupełniamy spacjami do końca 1399 znaków
Na środowiskach testowych gdzie danych było niewiele ostatnia linia wyglądała mniej więcej tak
991... (na dev)
9930... (na środowisku testowym dla developerów)
9950... (na środowisku testerów)
czyli prefix 99 + ilość rekordów.
Natomiast na produkcji zamiast 99xxx... pojawiło się 10001
Wynika to z prostej przyczyny, że użyty został znak || zamiast np concat
okazuje się, że oracle ogólnie łączy || ale w momencie kodu jak powyżej najpierw '99' zamienia na wartość liczbową a dopiero potem wykonuje operacje matematyczne, a dzieje się to przez ten +2 na końcu :) Przykład poniżej:
select to_char('99'||1) from dual
union all
select to_char('99'||1+2) from dual
union all
select concat('99',1+2) from dual
/
daje wynik:
Nagłówek 1 |
---|
991 |
993 |
993 |
natomiast jak 1 zamienimy na 99
select to_char('99'||101) from dual
union all
select to_char('99'||99+2) from dual
union all
select concat('99',99+2) from dual
/
wyniki jakie dostajemy to już:
Nagłówek 1 |
---|
99101 |
10001 |
99101 |
Zatem przestrzegam przed używaniem operatorów matematycznych przy łączeniu varcharów za pomocą ||
ShalomNa oko to jest bardziej kwestia priorytetu operatorów, tzn czy najpierw skleją się stringi
||
a dopiero potem wykona dodawanie, czy odwrotnie. W przypadkuconcat
najpierw ewaluowane są argumenty funkcji więc dostajeszconcat('99',101)
podczas gdy w przypadku||
wiązanie tego operatora wykona się przed dodawaniem więc'99'||99+2
przechodzi w'9999'+2