2013-08-06 17 views
40

W jednym z moich wybranych sprawozdań Mam następujący błąd:udało się znaleźć funkcji konwersji z nieznanych do tekstu

ERROR: failed to find conversion function from unknown to text 
********** Error ********** 
ERROR: failed to find conversion function from unknown to text 
SQL state: XX000 

To było łatwo rozwiązać stosując cast, ale nie w pełni zrozumieć, dlaczego tak się stało . Przedstawię moje zamieszanie dwoma prostymi stwierdzeniami.

Ten jest OK:

select 'text' 
union all 
select 'text'; 

ten powróci błąd:

with t as (select 'text')  
select * from t 
union all 
select 'text' 

wiem, że mogę to naprawić w prosty sposób:

with t as (select 'text'::text)  
select * from t 
union all 
select 'text' 

Dlaczego konwersja nie w drugi przykład? Czy jest jakaś logika, której nie rozumiem, czy zostanie to naprawione w przyszłej wersji PostgreSQL?

PostgreSQL 9.1.9

To samo zachowanie na PostgreSQL 9.2.4 (SQL Fiddle)

Odpowiedz

36

Postgres jest szczęśliwy, jeśli można go wykryć rodzaje niewstukane stałych z kontekstu. Ale gdy jakikolwiek kontekst nie jest możliwy, a zapytanie jest nieco bardziej skomplikowane niż trywialne, mechanizm ten zawodzi. Zasady te są specyficzne dla każdej klauzuli SELECT, a niektóre są bardziej rygorystyczne, inne nie. Jeśli mogę powiedzieć, to starsze procedury są bardziej tolerancyjne (ze względu na wyższą kompatybilność z Oracle i mniej negatywny wpływ na początkujących), nowoczesne są mniej tolerancyjne (ze względu na wyższe bezpieczeństwo błędów typu).

Było kilka propozycji, które próbują pracować z każdą nieznaną stałą literową, taką jak stała tekstu, ale została odrzucona z innych powodów. Nie oczekuję więc znaczących zmian w tym obszarze. Ten problem jest zwykle związany z testami syntetycznymi - a mniej z rzeczywistymi, gdzie typy są wyprowadzane z typów kolumn.

+2

Rozumiem. Często spotykam się z tym problemem w prawdziwym życiu. Używamy PostgreSQL do analityki/bi/data mining, a łączenie stałych bez typów jest powszechne. Ale jak już powiedziałem, łatwo jest rzucać. –

+1

Dlaczego nie muszę przesyłać liczbowych literałów takich jak '1 :: int'? –

+0

@IainElder - typy liczbowe są mniejszymi klasami - każda literalna stała (określana jako "nieznana") może być niejawnie rzutowana na dowolny typ - liczba nie - więc sin ('2,34') działa, ale długość (1) nie –