Oracle9i: Funkcja zwraca inną wartość niż zapytanie

0

Werja ORACLE:
Oracle9i Release 9.2.0.8.0 - Production
PL/SQL Release 9.2.0.8.0 - Production

Sprawdzane poprzez: SQL Developer

TabelaA (
...
wartosc number(10,0),
kod VARCHAR2(6 CHAR)
);

TabelaB (
...
a_kod VARCHAR2(6 BYTE)
);
FUNCTION fun(kod varchar2) RETURN number
IS
  wynik number(10,0) := 0;
BEGIN
  select a.wartosc into wynik
  from TabelaB b 
  join TabelaA on a.kod = b.a_kod
  where b.a_kod = kod;
  dbms_output.put_line('f-> ' || wynik);
  return wynik;
END;
select a.wartosc
  from TabelaB b 
  join TabelaA on a.kod = b.a_kod
  where b.a_kod = kod;

Jeżeli użyję zapytania poza obrębem funkcji zwracana jest wartość 5 (jest to prawidłowy wynik), a po wywołaniu funkcji zwracany jest wynik: 6
Jedynie pola tabel nie są wszystkie podane, bo to nie istotne. Funkcja i wywołania tak jak jest to w bazie.

declare
  wynik number(10,0);
begin
  wynik := fun('923154');
  dbms_output.put_line(wynik);
end; 

Czy ktoś wie w czym jest problem?

0

nie jest to możliwe przy podanym przykładzie. Chcesz pomocy to daj całą funkcję
BTW Oracle 9i to już prawie 15 lat ma

0

Napisałem przecież, że to jest cała funkcja. Dla mnie to też nie jet możliwe, ale wynik temu zaprzecza.

0

wobec tego JEST TO NIEMOŻLIWE - błąd jest gdzie indziej

0

Błąd musi być na etapie przekazania parametru, bo jeżeli dodam w kodzie **wparametr **, który zastąpi mi parametr z funkcji to jest OK

FUNCTION fun(kod varchar2) RETURN NUMBER
IS
  wynik NUMBER(10,0) := 0;
  wparametr varchar2(6) := '923154';
BEGIN
  SELECT a.wartosc INTO wynik
  FROM TabelaB b 
  JOIN TabelaA ON a.kod = b.a_kod
  WHERE b.a_kod = wparametr;
  dbms_output.put_line('f-> ' || wynik);
  RETURN wynik;
END;

Czy możliwe by błąd w funkcji powodowany był przez porównywanie typów varchar2 (byte/char)?

0

Definiując pole typu Byte(6) informujesz bazę, że możesz tam przechowywać coś co posiada maksymalnie 6 bajtów co niekoniecznie przełoży się na 6 znaków (bo niektóre znaki - jeśli baza jest w UTF-8 nie da się zapisać na jednym bajcie). Natomiast definiując pole char(6) mówisz bazie, że można tam trzymać 6 znaków bez względu na to ile bajtów to zajmie. Specyfiki 9i nie znam ale nie takie babole w parserze oracla widziałem więc wszystko możliwe, że automatyczna konwersja byte to varchar lub na odwrót powoduje, że coś się krzaczy jak np w przypadku opisanym przez @Shalom http://4programmers.net/Mikroblogi/Tag/exploit

0

Tak wiem o tym, ale zapytanie poza funkcją zwraca co innego. Może rzeczywiście jest babol w oracle.

0

Chociaż wywołanie

alter table TabelaA modify kod varchar2(6 byte);

nic nie zmieniło w temacie zwracanego wyniku.

0

Możesz to jeszcze sprawdzić w ten sposób, że przygotujesz sobie identyczny przykład z identycznymi danymi na http://sqlfiddle.com/ i zobaczysz czy daje te same efekty co u Ciebie.

0

Tak to jest krążyć wokół czegoś i nie widzieć. Zmieniłem nazwę parametru funkcji na inny niż każda z dostępnych nazw z kolumn w obu tabelach i jest OK

0

Szkoda słów normalnie... Niby jak miał ci ktokolwiek pomóc jak się okazało, że jednak błąd był ściśle związany z oryginalną funkcją.

0

@abrakadaber Wszystko było podane w opisie wątku i skoro jesteś taki bystry to mogłeś napisać, że wystarczy zmienić nazwę parametru, a na razie Twoje komentarze są typu "jestem boski, ale nie podam rozwiązania, bo go nie znam" Jak masz grać filozofa to nie wypowiadaj się. Po raz kolejny udowadniasz, że nie czytasz ze zrozumieniem. Wcześniej nie zauważyłeś jak napisałem jak wygląda oryginalna funkcja w Oracle, a teraz to.. śmieszny jesteś.

1

g**no prawda!!!! Ten twój kod się nie wykonywał!! Aby zadziałał należało do zapytania dodać alias zmieniając to

SELECT a.wartosc
  FROM TabelaB b 
  JOIN TabelaA ON a.kod = b.a_kod
  WHERE b.a_kod = kod;

na to

SELECT a.wartosc
  FROM TabelaB b 
  JOIN TabelaA a ON a.kod = b.a_kod
  WHERE b.a_kod = kod;

zarówno w zapytaniu jak i funkcji. I po takiej zmianie to DZIAŁA tak jak powinno ponieważ kod jako nazwa parametru funkcji w zapytaniu NIE JEST TRAKTOWANY jako nazwa kolumny tabeli TabelaA bo NIE JEST poprzedzony aliasem. Ale ty WIESZ LEPIEJ i masz super tajną funkcję, której nie możesz nikomu pokazać bo zaraz ci wykradną te miliony z konta...

0

Fakt, nie wykonywał. Mój błąd. Jednak tak wyglądał oryginalny (zapomniałem o aliasie 'a') potem go modyfikowałem i niewłaściwie wpisałem w poście. Wnioskuję, że dopiero teraz to sprawdziłeś co podtrzymuje wszystko co napisałem w poście wyżej. Mimo wszystko i tak nie działało.

Oczywiście ponownie masz rację, dla potwierdzenia Twoich słów pozwoliłem sobie dodać przykład, który potwierdzi co napisałeś ;-)

create table a ( test varchar2(6));

insert into a(test) values ('abc');
insert into a(test) values ('abc2');
insert into a(test) values ('abc3');

create or replace 
FUNCTION fun2(test varchar2) RETURN varchar2
IS
  wynik varchar2(6);
BEGIN
  SELECT ta.test into wynik
  FROM a ta
  WHERE ta.test = test;
  RETURN wynik;
END;

begin
  dbms_output.put_line(fun2('abc'));
end;
Error report:
ORA-01422: exact fetch returns more than requested number of rows

Teraz zmiana parametru test na ptest i wynik:
abc

1 użytkowników online, w tym zalogowanych: 0, gości: 1