<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
	<channel>
		<title><![CDATA[Forum PostgreSQL - problem z funkcja zwracajaca SETOF record]]></title>
		<link>https://forum.postgresql.org.pl/viewtopic.php?id=442</link>
		<description><![CDATA[Najświeższe odpowiedzi w problem z funkcja zwracajaca SETOF record.]]></description>
		<lastBuildDate>Fri, 21 May 2010 09:36:35 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Odp: problem z funkcja zwracajaca SETOF record]]></title>
			<link>https://forum.postgresql.org.pl/viewtopic.php?pid=2052#p2052</link>
			<description><![CDATA[Pomoglo. Musialem jeszcze typ funkcji zmeinic zze STABLE na VOLATILE i poszlo.

Mam jeszcze blad Accessa Error 3151 - ODBC connection - gdy funkcja jest w orginalnym ciele - blad nie wystepuje ( tzn gdy jest ten select distinct). gdy dorzucam reszte - wywala ten blad.

Szukalem troche w necie i pisza ze to blad bazy danych - ze np timeout jest, albo zapytanie daje zly wynik. W moim przypadku jest ok ( podejrzalem sobie query ktore jest wykonywane w bazie - wykonalem je recznie i dalo wynik o ktory mi chodzilo) i nie bardzo wiem co z tyum dalej.

WIem ze to niekoniecznie ten sam temat, ale moze ktos pomoze...?]]></description>
			<author><![CDATA[dummy@example.com (capd)]]></author>
			<pubDate>Fri, 21 May 2010 09:36:35 +0000</pubDate>
			<guid>https://forum.postgresql.org.pl/viewtopic.php?pid=2052#p2052</guid>
		</item>
		<item>
			<title><![CDATA[Odp: problem z funkcja zwracajaca SETOF record]]></title>
			<link>https://forum.postgresql.org.pl/viewtopic.php?pid=2050#p2050</link>
			<description><![CDATA[Myślę, że problem jest w tym że po 'RETURN QUERY' masz CREATE TEMPORARY...';
[quote]
RETURN QUERY

--stworzenie 2 tablic tymczasowych
CREATE TEMPORARY TABLE temp_tab(id SERIAL PRIMARY KEY, id_kor int, nazwa text, ul varchar, nr_bud varchar, nr_lok varchar, miejsc varchar, kod_poczt varchar) ;
CREATE TEMPORARY TABLE temp_tab_sort(id SERIAL PRIMARY KEY, id_kor int, nazwa text, ul varchar, nr_bud varchar, nr_lok varchar(10), miejsc varchar, kod_poczt varchar) ;

--wrzucenie do tablicy tymczasowej wartosci z excela
[/quote]


Powinieneś przenieść RETURN QUERY przed SELECTA
[quote]
SELECT id_kor id_korespondenta, nazwa, ul ulica, nr_bud numer_budynku, nr_lok numer_lokalu, miejsc miejscowosc, kod_poczt kod_pocztowy FROM temp_tab_sort WHERE
(ID>=(SELECT MAX(ID) FROM temp_tab_sort WHERE nazwa = formatuj_imiona_nazwisko_firma('', '', 'Kowalski', '') AND ul='' AND miejsc='' AND kod_poczt='')-3
OR ID<=(SELECT MAX(ID) FROM temp_tab_sort WHERE nazwa = formatuj_imiona_nazwisko_firma('', '', 'Kowalski', '') AND ul='' AND miejsc='' AND kod_poczt='')+3)
AND ID !=(SELECT MAX(ID) FROM temp_tab_sort WHERE nazwa = formatuj_imiona_nazwisko_firma('', '', 'Kowalski', '') AND ul='' AND miejsc='' AND kod_poczt='')
UNION
SELECT DISTINCT
[/quote]]]></description>
			<author><![CDATA[dummy@example.com (rski)]]></author>
			<pubDate>Thu, 20 May 2010 18:45:20 +0000</pubDate>
			<guid>https://forum.postgresql.org.pl/viewtopic.php?pid=2050#p2050</guid>
		</item>
		<item>
			<title><![CDATA[problem z funkcja zwracajaca SETOF record]]></title>
			<link>https://forum.postgresql.org.pl/viewtopic.php?pid=2046#p2046</link>
			<description><![CDATA[Witam,

Mam do przerobienia funkcje ktora zwraca SETOF record. DOtychczas zbyt duzo postgresem sie nie zajmowalem i ten problem jest dla mnie dosc powazny a sprawa pilna. Acces laczy sie z postgresem i wywolywane jest zapytanie:

"SELECT * FROM szukaj_duplikatow_korespondenta('" & nazwisko & "', '" & _firma_1 & "', ' " & ulica & "', '" & miejscowość & "', " & idTypuKorespondenta & ", '" & kodPocztowy & "')" & vbNewLine & _ 
"AS (id_korespondenta integer, imie_nazwisko_firma text, ulica varchar, nr_budynku varchar, nr_lokalu varchar, miejscowosc varchar, kod_pocztowy varchar);"

Funkcja jest zbudowana nastepujaco:

CREATE OR REPLACE FUNCTION szukaj_duplikatow_korespondenta(p_nazwisko character varying, p_firma_1 character varying, p_ulica character varying, p_miejscowosc character varying, p_id_typu_korespondenta integer, p_kod_pocztowy character varying)
  RETURNS SETOF RECORD AS
$BODY$
DECLARE
BEGIN
RETURN QUERY


SELECT DISTINCT
 k.id_korespondenta,formatuj_imiona_nazwisko_firma(imie_1, imie_2, nazwisko, nazwa_firmy_1), ulica, numer_budynku, numer_lokalu, miejscowosc,kod_pocztowy
FROM public.t_korespondenci k
LEFT OUTER JOIN public.t_dane_osobowe AS dos USING(id_korespondenta)
LEFT OUTER JOIN public.t_dane_firm AS df USING(id_korespondenta)
LEFT OUTER JOIN public.t_adresy AS a USING (id_korespondenta)
LEFT OUTER JOIN public.t_miejscowosci m USING (id_miejscowosci)
WHERE (--sprawdzenie dla osób fizycznych
p_id_typu_korespondenta IN
(SELECT id_typu_korespondenta
FROM    t_typy_korespondentow
WHERE   osoba_fizyczna = TRUE
)
AND (dos.nazwisko ILIKE regexp_replace(lower(p_nazwisko),'[śżźćęąłńó]', '_','ig')OR p_nazwisko ILIKE regexp_replace(lower(dos.nazwisko),'[śżźćęąłńó]', '_','ig')
OR ((m.miejscowosc ILIKE regexp_replace(lower(p_miejscowosc), '[śżźćęąłńó]', '_','ig')OR p_miejscowosc ILIKE regexp_replace(lower(m.miejscowosc), '[śżźćęąłńó]', '_','ig')
) AND (a.ulica ILIKE regexp_replace(lower(p_ulica), '[śżźćęąłńó]', '_','ig') OR p_ulica ILIKE regexp_replace(lower(a.ulica), '[śżźćęąłńó]', '_','ig')))))
OR (--sprawdzenie dla osób prawnych
p_id_typu_korespondenta IN
(SELECT id_typu_korespondenta
FROM    t_typy_korespondentow
WHERE   osoba_fizyczna = FALSE
)
AND p_id_typu_korespondenta = k.id_typu_korespondenta AND ((df.nazwa_firmy_1 ILIKE regexp_replace('%' || lower(p_firma_1)|| '%', '[śżźćęąłńó]', '_','ig')
OR p_firma_1 ILIKE regexp_replace('%'|| lower(df.nazwa_firmy_1)|| '%', '[śżźćęąłńó]', '_','ig'))
AND ( p_kod_pocztowy = a.kod_pocztowy
OR ((m.miejscowosc ILIKE regexp_replace(lower(p_miejscowosc), '[śżźćęąłńó]', '_','ig')OR p_miejscowosc ILIKE regexp_replace(lower(m.miejscowosc), '[śżźćęąłńó]', '_','ig'))
 AND (a.ulica ILIKE regexp_replace(lower(p_ulica), '[śżźćęąłńó]', '_','ig')OR p_ulica ILIKE regexp_replace(lower(a.ulica), '[śżźćęąłńó]', '_','ig'))))));

END;
$BODY$
  LANGUAGE 'plpgsql' STABLE
  COST 100
  ROWS 4;


Chce zeby ta funkcja oprocz tego co robi tworzyla 2 tabele tymczasowe segregowala je a nastepnie zwracala jednego selecta polaczonego UNIONEM.

Ponizej cialo zmienionej przeze mnie funkcji:



CREATE OR REPLACE FUNCTION szukaj_duplikatow_korespondenta(p_nazwisko character varying, p_firma_1 character varying, p_ulica character varying, p_miejscowosc character varying, p_id_typu_korespondenta integer, p_kod_pocztowy character varying)
  RETURNS SETOF RECORD AS
$BODY$
DECLARE
BEGIN
RETURN QUERY

--stworzenie 2 tablic tymczasowych
CREATE TEMPORARY TABLE temp_tab(id SERIAL PRIMARY KEY, id_kor int, nazwa text, ul varchar, nr_bud varchar, nr_lok varchar, miejsc varchar, kod_poczt varchar) ;
CREATE TEMPORARY TABLE temp_tab_sort(id SERIAL PRIMARY KEY, id_kor int, nazwa text, ul varchar, nr_bud varchar, nr_lok varchar(10), miejsc varchar, kod_poczt varchar) ;

--wrzucenie do tablicy tymczasowej wartosci z excela

INSERT INTO temp_tab(nazwa, ul, miejsc, kod_poczt)
--VALUES (formatuj_imiona_nazwisko_firma('', '', p_nazwisko, p_firma_1),p_ulica,p_miejscowosc,p_kod_pocztowy);
VALUES (formatuj_imiona_nazwisko_firma('', '', 'Kowalski', ''),'','','');

--wrzucenie do tablicy tymczasowej wszystkich rekordow z bazy
INSERT INTO temp_tab(id_kor, nazwa, ul, nr_bud, nr_lok, miejsc, kod_poczt)
SELECT k.id_korespondenta , formatuj_imiona_nazwisko_firma(imie_1, imie_2, nazwisko, nazwa_firmy_1), ulica, numer_budynku, numer_lokalu, miejscowosc, kod_pocztowy 
FROM public.t_korespondenci k
LEFT OUTER JOIN public.t_dane_osobowe dos ON k.id_korespondenta=dos.id_korespondenta
LEFT OUTER JOIN public.t_dane_firm df ON df.id_korespondenta=k.id_korespondenta
LEFT OUTER JOIN public.t_adresy a ON a.id_korespondenta=k.id_korespondenta
LEFT OUTER JOIN public.t_miejscowosci m ON m.id_miejscowosci=k.id_korespondenta;

--przerzucenie danych do drugiej tablicy wraz z posortowaniem ich
INSERT INTO temp_tab_sort(id_kor, nazwa, ul, nr_bud, nr_lok, miejsc, kod_poczt)
SELECT id_kor, nazwa, ul, nr_bud, nr_lok, miejsc, kod_poczt FROM temp_tab ORDER BY miejsc, ul, nazwa;

--wybranie 3 rekordow nad ( o ile istnieja) i trzech pod ( o ile istnieja) rekordem pobranym z excela plus wynik "starej" funkcji
SELECT id_kor id_korespondenta, nazwa, ul ulica, nr_bud numer_budynku, nr_lok numer_lokalu, miejsc miejscowosc, kod_poczt kod_pocztowy FROM temp_tab_sort WHERE 
(ID>=(SELECT MAX(ID) FROM temp_tab_sort WHERE nazwa = formatuj_imiona_nazwisko_firma('', '', 'Kowalski', '') AND ul='' AND miejsc='' AND kod_poczt='')-3
OR ID<=(SELECT MAX(ID) FROM temp_tab_sort WHERE nazwa = formatuj_imiona_nazwisko_firma('', '', 'Kowalski', '') AND ul='' AND miejsc='' AND kod_poczt='')+3)
AND ID !=(SELECT MAX(ID) FROM temp_tab_sort WHERE nazwa = formatuj_imiona_nazwisko_firma('', '', 'Kowalski', '') AND ul='' AND miejsc='' AND kod_poczt='')
UNION
SELECT DISTINCT
 k.id_korespondenta,formatuj_imiona_nazwisko_firma(imie_1, imie_2, nazwisko, nazwa_firmy_1), ulica, numer_budynku, numer_lokalu, miejscowosc,kod_pocztowy
FROM public.t_korespondenci k
LEFT OUTER JOIN public.t_dane_osobowe AS dos USING(id_korespondenta)
LEFT OUTER JOIN public.t_dane_firm AS df USING(id_korespondenta)
LEFT OUTER JOIN public.t_adresy AS a USING (id_korespondenta)
LEFT OUTER JOIN public.t_miejscowosci m USING (id_miejscowosci)
WHERE (--sprawdzenie dla osób fizycznych
p_id_typu_korespondenta IN
(SELECT id_typu_korespondenta
FROM    t_typy_korespondentow
WHERE   osoba_fizyczna = TRUE
)
AND (dos.nazwisko ILIKE regexp_replace(lower(p_nazwisko),'[śżźćęąłńó]', '_','ig')OR p_nazwisko ILIKE regexp_replace(lower(dos.nazwisko),'[śżźćęąłńó]', '_','ig')
OR ((m.miejscowosc ILIKE regexp_replace(lower(p_miejscowosc), '[śżźćęąłńó]', '_','ig')OR p_miejscowosc ILIKE regexp_replace(lower(m.miejscowosc), '[śżźćęąłńó]', '_','ig')
) AND (a.ulica ILIKE regexp_replace(lower(p_ulica), '[śżźćęąłńó]', '_','ig') OR p_ulica ILIKE regexp_replace(lower(a.ulica), '[śżźćęąłńó]', '_','ig')))))
OR (--sprawdzenie dla osób prawnych
p_id_typu_korespondenta IN
(SELECT id_typu_korespondenta
FROM    t_typy_korespondentow
WHERE   osoba_fizyczna = FALSE
)
AND p_id_typu_korespondenta = k.id_typu_korespondenta AND ((df.nazwa_firmy_1 ILIKE regexp_replace('%' || lower(p_firma_1)|| '%', '[śżźćęąłńó]', '_','ig')
OR p_firma_1 ILIKE regexp_replace('%'|| lower(df.nazwa_firmy_1)|| '%', '[śżźćęąłńó]', '_','ig'))
AND ( p_kod_pocztowy = a.kod_pocztowy
OR ((m.miejscowosc ILIKE regexp_replace(lower(p_miejscowosc), '[śżźćęąłńó]', '_','ig')OR p_miejscowosc ILIKE regexp_replace(lower(m.miejscowosc), '[śżźćęąłńó]', '_','ig'))
 AND (a.ulica ILIKE regexp_replace(lower(p_ulica), '[śżźćęąłńó]', '_','ig')OR p_ulica ILIKE regexp_replace(lower(a.ulica), '[śżźćęąłńó]', '_','ig'))))));

END;
$BODY$
  LANGUAGE 'plpgsql' STABLE
  COST 100
  ROWS 4;




Niestety proba wywolania funkcji zwraca nastepujacy blad:

cannot open CREATE TABLE query as cursor

Czy mozna sobie jakos z tym poradzic? Niezaleznie od tego co zrobie wewnatrz funkcji, jesli umieszcze w niej cokolwiek innego niz ten SELECT nie chce zadzialac.]]></description>
			<author><![CDATA[dummy@example.com (capd)]]></author>
			<pubDate>Thu, 20 May 2010 08:01:31 +0000</pubDate>
			<guid>https://forum.postgresql.org.pl/viewtopic.php?pid=2046#p2046</guid>
		</item>
	</channel>
</rss>
