2009-03-02 10 views
7

Mam zapytanie, które maOracle10 i JDBC: jak sprawić, aby CHAR ignorował spacje końcowe w porównaniu?

... gdzie PRT_STATUS = 'ONT' ...

Pole prt_status jest zdefiniowany jako CHAR (5), choć. Więc zawsze jest wypełniony spacjami. Zapytanie nic nie pasuje do wyniku. Do tej pracy zapytania muszę zrobić

... gdzie RTRIM (PRT_STATUS) = 'ONT'

który działa.

To denerwujące.

W tym samym czasie, kilka czystych java DBMS klientów (Oracle SQLDeveloper i AquaStudio) NIE mam problemu z pierwszym zapytaniem, zwracają poprawny wynik. TOAD również nie ma problemu.

Podejrzewam, że po prostu łączą w pewnym trybie zgodności (na przykład ANSI), więc Oracle wie, że CHAR (5) ma być porównywany bez żadnego szacunku do znaków końcowych.

Jak mogę to zrobić z obiektami połączeń, które otrzymuję w mojej aplikacji?

AKTUALIZACJA Nie można zmienić schematu bazy danych.

ROZWIĄZANIE To rzeczywiście sposób, w jaki Oracle porównuje pola z przekazanymi parametrami.

Po zakończeniu wiązania łańcuch jest przekazywany za pomocą metody PreparedStatement.setString(), która ustawia typ na VARCHAR, a tym samym Oracle używa porównania bez uzupełniania - i kończy się niepowodzeniem.

Próbowałem użyć setObject (n, str, Types.CHAR). Fails. Dekompilacja pokazuje, że Oracle ignoruje CHAR i przekazuje ją ponownie jako VARCHAR.

Wariant że wreszcie działa jest

setObject(n,str,OracleTypes.FIXED_CHAR); 

To sprawia, że ​​kod nie przenośny chociaż.

Klientom UI udaje się z innego powodu - używają literałów znaków, które nie są wiążące. Kiedy wpisuję PRT_STATUS = "ONT", "ONT" jest literałem, a jako takie porównywane przy użyciu wyściełanej drogi.

Odpowiedz

8

Zauważ, że Oracle compares CHAR values using blank-padded comparison semantics.

Od Datatype Comparison Rules,

Oracle wykorzystuje puste wyściełane porównanie semantykę tylko wtedy, gdy obie wartości w porównaniu są znakami wyrażenia typu danych char, nchar, literałów tekstowych lub wartości zwracane przez funkcję UŻYTKOWNIKA .

W twoim przykładzie, czy 'ONT' przekazano jako parametr wiązania, czy jest on wbudowany w zapytanie tekstowo, jak pokazano na ilustracji? Jeśli parametr wiązania, upewnij się, że jest powiązany jako typ CHAR. W przeciwnym razie zweryfikuj wersję używanej biblioteki klienta, ponieważ naprawdę stare wersje Oracle (np. V6) będą miały inną semantykę porównania dla CHAR.

+0

W porządku. Zobacz moją zaktualizowaną odpowiedź. – vladr

+0

Hmm ... to ma sens. Zbiór setString JDBC używa VARCHAR do wiązania parametru ciągu. Nie jestem pewien, czy mogę go użyć, aby rozwiązać problem, ale przynajmniej staje się teraz jaśniejszy. –

+0

Masz prawdopodobnie rację: "Oracle używa nonpadded semantyki porównania, gdy jedna lub obie wartości w porównaniu mają typ danych VARCHAR2 lub NVARCHAR2". Muszę zrobić test, żeby to sprawdzić. –

0

Chciałbym zmienić kolumnę CHAR (5) w varchar2 (5) w db.

+0

Out pytania. DB nie należy do naszej grupy. –

1

Jeśli nie można zmienić tabeli bazy danych, można zmodyfikować zapytanie.

Niektóre alternatywy dla RTRIM:

.. Gdzie PRT_STATUS jak '%' ONT ...

.. Gdzie PRT_STATUS = 'ONT' ... - 2 białe przestrzenie za T

.. Gdzie PRT_STATUS = rpad ('ONT', 5”„) ...

0

można użyć oddanych do eksploatacji char w zapytaniu:

... WHERE PRT_STATUS=cast('ONT' as char(5)) 

Albo w bardziej ogólny sposób JDBC:

... WHERE PRT_STATUS=cast(? as char(5)) 

A potem w kodzie JDBC należy używać statement.setString(1, "ONT");

Powiązane problemy