konto usunięte

Temat: plpgsql i zmienne typu RECORD

Jak w Postgresie osiągnąć coś takiego:

declare
TYPE Employer IS RECORD (
first_name VARCHAR(64),
last_name VARCHAR(64),
);

foo Employer;
begin

foo.first_name := 'Lukasz';
foo.last_name := 'Bandzarewicz';

return foo;
end;


Powyższy kod jest wzięty z tutoriala z plsql. Niestety w plpgsql struktura zmiennej typu RECORD tworzona jest dopiero po wykonaniu SELECT .. INTO.
Czy jest jakiś sposób na obejście tego ograniczenia?

konto usunięte

Temat: plpgsql i zmienne typu RECORD

Rozwiązałem ten w problem w następujący sposób:

declare
foo record;
begin

select
''::character varying (64) as first_name,
''::character varying (64) as last_name
into foo;

foo.first_name := 'Lukasz';
foo.last_name := 'Bandzarewicz';

return foo;
end;


Niestety nie wystarczy proste SELECT foo(), muszę wklepać coś takiego:

select * from foo() as (first_name character varying (64), last_name character varying (64));


Czy jest jakiś sposób by uczynić to rozwiązanie bardziej DRY?

konto usunięte

Temat: plpgsql i zmienne typu RECORD

Za pierwszym razem byłeś blisko. Poza kodem funkcji zadeklaruj typ employer:
create type employer AS (
first_name VARCHAR(64),
last_name VARCHAR(64)
);

CREATE FUNCTION employer_test() returns employer as $X$
DECLARE
foo employer;
BEGIN
foo.first_name='Lukasz';
foo.last_name='Bandzarewicz';
return foo;
END; $X$ language 'plpgsql';

select * from employer_test();

konto usunięte

Temat: plpgsql i zmienne typu RECORD

Super, działa dokładnie tak jak chciałem, dzięki ;)

btw. Zna ktoś może jakiś dobry i darmowy edytor do plpgsql? Ten z pgadmin3 jest troszeczkę siermiężny i nie udostępnia takiej podstawowej opcji jak uzupełnianie kodu..
Marcin Lulek

Marcin Lulek Programista -
WebReactor

Temat: plpgsql i zmienne typu RECORD

Łukasz Bandzarewicz:
Super, działa dokładnie tak jak chciałem, dzięki ;)

btw. Zna ktoś może jakiś dobry i darmowy edytor do plpgsql? Ten z pgadmin3 jest troszeczkę siermiężny i nie udostępnia takiej podstawowej opcji jak uzupełnianie kodu..


czesciowo udostepnia, CTRL+SPACJA albo tab, nie pamietam dokladnie
Dariusz Bujak

Dariusz Bujak Student, młodszy
programista JAVA,
C++

Temat: plpgsql i zmienne typu RECORD

Witam,

Troszeczkę odświeżę temat

Spróbowałem wykorzystać zamieszczone rozwiązanie i w sumie działa tylko że jest zwracana jedna kolumna
z wartością

("Lukasz","Bandzarewicz")


Czy jest możliwość aby wartość była zwracana w dwóch kolumnach?

Napisałem taką funkcje:


CREATE OR REPLACE FUNCTION set_checkpoint_used_detection(in_checkpoint_id bigint)
RETURNS TABLE ( col_status integer, col_date_detection timestamp ) AS
$BODY$DECLARE

date_detection_now timestamp := now();
new_id BIGINT;
BEGIN
SELECT nextval('Public.checkpoint_used_id_key') INTO new_id ;

INSERT INTO Public.checkpoint_used (id, checkpoint_id, date_detection)
VALUES (new_id, in_checkpoint_id, date_detection_now);

IF FOUND THEN
col_status := 0;
col_date_detection := date_detection_now;
ELSE
col_status := 1;
END IF;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION set_checkpoint_used_detection(bigint)
OWNER TO postgres;



funkcja sie wykonuje ale nie zwraca żadnego wyniku podejrzewam że trzeba użyć słowa:

RETURN ;


ale w jaki sposób?

Coś takiego:

RETURN (col_status, col_date_detection);

zwraca błąd przy tworzeniu/zastępowaniu funkcji

Proszę o jaką podpowiedź w tym temacie

Ok, znalazłem rozwiązanie z podziałem na kolumny wystarczy

SELECT * FROM set_checkpoint_used_detection(1);

zamiast

SELECT set_checkpoint_used_detection(1);


Jeżeli by ktoś znał inne rozwiązanie prosze pisać może będzie lepsze:)

PozdrawiamTen post został edytowany przez Autora dnia 12.05.14 o godzinie 11:13
Marcin Mackiewicz

Marcin Mackiewicz Programista JAVA, RS
Adware Polska

Temat: plpgsql i zmienne typu RECORD

Myślę, że najprościej będzie zrobić
RETURN QUERY SELECT col_status, col_date_detection;
zaraz po ostatnim END IF. Ja akurat lubię jak jest RETURN jeżeli funkcja coś zwraca :)

Tak jak masz dobrze jest. Użycie funkcji w zapytaniu
select funckcja();
jeżeli funkcja zwraca table to raczej jej wywołanie powinno nastąpić po klauzuli FROM. Użycie jej jako atrybutu w tym momencie spowoduje zagregowanie kolumn tabeli do jednej kolumny typu RECORD. Funkcja zwróci oczekiwane kolumny jeżeli użyje się jej tak jakbyśmy odnosili się do tabeli
SELECT * FROM funkcja();
Ten post został edytowany przez Autora dnia 13.05.14 o godzinie 00:14
Dariusz Bujak

Dariusz Bujak Student, młodszy
programista JAVA,
C++

Temat: plpgsql i zmienne typu RECORD

Dzięki za pomoc, faktycznie o takie rozwiązanie zaproponowane przez Ciebie mi chodziło.

Wcześniej rozwiązałem ten problem poprzez stworzenie nowego typu, zamieszczę moje wcześniejsze rozwiązanie dla potomnych.


CREATE TYPE return_set_checkpoint_used AS (status_return INTEGER, date_return timestamp);



CREATE OR REPLACE FUNCTION set_checkpoint_used_detection(in_checkpoint_id bigint)
RETURNS return_set_checkpoint_used AS
$BODY$DECLARE
wynik return_set_checkpoint_used;
date_detection_now timestamp := now();
new_id BIGINT;
BEGIN
SELECT nextval('Public.checkpoint_used_id_key') INTO new_id ;

INSERT INTO Public.checkpoint_used (id, checkpoint_id, date_detection)
VALUES (new_id, in_checkpoint_id, date_detection_now);

IF FOUND THEN
wynik.status_return := 1;
wynik.date_return := date_detection_now;
ELSE
wynik.status_return := 0;
END IF;

RETURN wynik;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION set_checkpoint_used_detection(bigint)
OWNER TO postgres;


później jak już było wcześniej napisane aby wynik zapytania zwracany był w oddzielnych kolumnach należy wykonać zapytanie:

SELECT * FROM set_checkpoint_used_detection(1);


Może sie komuś kiedyś przyda, jeżeli by ktoś miał jakieś uwagi do zaprezentowanego rozwiązania to proszę pisać wszelkie sugestie ;)

Pozdrawiam.
Marcin Miga

Marcin Miga Programista. Po
prostu programista.

Temat: plpgsql i zmienne typu RECORD

1. Po co sam obliczasz wartość ID, skoro masz sequencera?
2. Po co stosujesz FOUND?
Te dwie czynności (wg mnie) możesz połączyć w:
CREATE OR REPLACE FUNCTION set_checkpoint_used_detection(in_checkpoint_id bigint)
RETURNS return_set_checkpoint_used AS
$BODY$
DECLARE
wynik return_set_checkpoint_used;
BEGIN
INSERT INTO checkpoint_used(checkpoint_id, date_detection)
VALUES($1,clock_timestamp())
returning id, date_detection
INTO wynik.status_return, wynik.date_return;

return wynik;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 1;
Dariusz Bujak

Dariusz Bujak Student, młodszy
programista JAVA,
C++

Temat: plpgsql i zmienne typu RECORD

Dzięki za zainteresowanie.

Zamieściłem tylko fragment kodu w późniejszym etapie planuje po pobraniu nowego id użyć go jeszcze do innej tabeli a szczerze nie wiem jak po insercie pobrać wartość gdybym to wykonał tak jak napisałeś
Marcin Miga

Marcin Miga Programista. Po
prostu programista.

Temat: plpgsql i zmienne typu RECORD

Marcin M.:
returning id, date_detection
Dariusz Bujak

Dariusz Bujak Student, młodszy
programista JAVA,
C++

Temat: plpgsql i zmienne typu RECORD

W sumie fakt ;) Dzieki za pomoc :)

Pozdrawiam

Następna dyskusja:

[postgreSQL] Dynamiczna naz...




Wyślij zaproszenie do