Podstawowe nieporozumienie: zmienna record
zawiera pojedynczy wiersz pojedynczy (lub ma wartość NULL), a nie tabelę (0-n wierszy znanego typu). Istnieje brak "zmiennych tabelarycznych" w Postgres lub PL/pgSQL. W zależności od zadania, istnieją różne możliwości:
W związku z tym nie można przypisać wielu wierszy do zmiennej record
typu. W tym stwierdzeniu:
EXECUTE format('SELECT id, tags FROM %s', _tbl) INTO t;
... Postgres przypisuje tylko pierwszy wiersz i odrzuca resztę. Ponieważ "pierwszy" nie jest dobrze zdefiniowany w zapytaniu, otrzymujesz arbitralny wybór. Oczywiście z powodu wspomnianego na początku nieporozumienia.
Zmienna A także nie może być używana zamiast tabel w zapytaniach SQL. To jest główną przyczyną błędu można uzyskać:
relacja „t” nie istnieje
To powinno być już jasne, że count(*)
nie miałoby sensu, aby rozpocząć, ponieważ t
to tylko jeden rekord/wiersz - poza tym, że i tak jest to niemożliwe.
Na koniec (nawet jeśli reszta zadziała), Twój typ zwrotu wydaje się nieprawidłowy:
(t TEXT[], e TEXT[])
. Ponieważ wybrałeś id, tags
na t
, powinieneś zwrócić coś podobnego do (id int, e TEXT[])
.
Co próbujesz zrobić będzie działać jak ten:
CREATE OR REPLACE FUNCTION func(_tbl regclass)
RETURNS TABLE (id int, e text[]) AS
$func$
DECLARE
_ct int;
BEGIN
EXECUTE format(
'CREATE TEMP TABLE tmp ON COMMIT DROP AS
SELECT id, tags FROM %s'
, _tbl);
GET DIAGNOSTICS _ct = ROW_COUNT; -- cheaper than another count(*)
-- ANALYZE tmp; -- if you are going to run multiple queries
RAISE NOTICE '% results', _ct;
RETURN QUERY TABLE tmp;
END
$func$ LANGUAGE plpgsql;
połączeń (nota składni!):
SELECT * FROM func('test');
Powiązane:
Just a dowód koncepcji. Podczas wybierania całej tabeli wystarczy użyć tabeli bazowej. W rzeczywistości będziesz mieć jakieś WHERE
klauzuli w zapytaniu ...
Ostrożnie z niedopasowania typu Dostrzec count()
powraca bigint
, nie można przypisać do zmiennej integer
. Potrzebował by obsady: count(*)::int
.
Ale zastąpiony że całkowicie, jest to tańsze, aby uruchomić to prawo po EXECUTE
:
GET DIAGNOSTICS _ct = ROW_COUNT;
Details in the manual.
Dlaczego ANALYZE
?
marginesie: CTE w czystym SQL często może wykonać zadanie:
Dziękuję bardzo, Erwin, dla rodzaju i szczegółowa odpowiedź. Powód jest dla mnie bardzo jasny. Będę używał CTE do tego celu. –