Doch, es ist typisiert, die erste Spalte explizit und die zweite implizit durch den Wert des ersten Satzes im union. Wenn Du nur das innere select ausführst:
Code: Alles auswählen
select cast('aa' as varchar(10)) substr, 'aabbaabb' string from rdb$database
union all
select null, 'aabbaabb' from rdb$database
union all
select 'aa', null from rdb$database
union all
select null, null from rdb$database
verhalten sich 2.5 und 3 korrekt und beide liefern das gleiche Ergebnis und die <null>s nach außen.
Man muss nicht jedesmal, wenn man eine derived table um ein statement wickelt, explizit typisieren, sonst wäre das Konstrukt ziemlich unbrauchbar.
Und andersrum, wenn man jeden Wert der unions explizit typisiert, nicht nur den ersten Satz, bleibt es bei Firebird 2.5 trotzdem falsch, hier mal bei der ersten Spalte umgesetzt:
Code: Alles auswählen
select substr, string, position(substr, string) pos, char_length(substr) len
from (
select cast('aa' as varchar(10)) substr, 'aabbaabb' string from rdb$database
union all
select cast(null as varchar(10)), 'aabbaabb' from rdb$database
union all
select cast('aa' as varchar(10)), null from rdb$database
union all
select cast(null as varchar(10)), null from rdb$database)
Und schließlich, wenn kein union im Spiel ist, wird <null> nach außen transportiert, auch bei Firebird 2.5, und ohne Typisierung:
Code: Alles auswählen
select str from
(select str from
(select null str
from rdb$database))
Das scheint ein Bug im Zusammenhang mit unions zu sein, und eine der Firebird-Versionen macht es falsch. Tendiere zu Firebird 2.5, denn die Ausgabe von Leerstrings statt <null>s bedeutet ja, dass Firebird den Wert als String interpretiert, aber die <null> nicht erhält. Alle Datentypen der Datenbank können <null>, es gibt hier keinen Grund, es auf einen echten Wert abzubilden.
Viele Grüße, Volker