Funkcja dezynfekcji
To, co obecnie posiadasz, można uprościć/odkazić do:
CREATE OR REPLACE FUNCTION func_a (username text = '', databaseobject text = '')
RETURNS ????
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE
format ('SELECT * FROM %s v1 LEFT JOIN %I v2 USING (id)'
, CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END
, databaseobject);
END
$func$;
Potrzebujesz tylko dodatkowych wystąpień BEGIN ... END
w ciele funkcji, aby rozpocząć oddzielne bloki kodu z własnym zakresem, co jest rzadko potrzebne.
Standardowym operatorem łączenia SQL jest ||
. +
jest "kreatywnym" dodatkiem twojego byłego dostawcy.
Nie używaj identyfikatorów CaMeL-case, chyba że umieścisz je w podwójnym cudzysłowie. Najlepiej w ogóle ich nie używać Zobacz:
- Czy w nazwach kolumn PostgreSQL jest rozróżniana wielkość liter?
varchar(4000)
jest również dostosowany do konkretnego ograniczenia SQL Server. W Postgresie nie ma to szczególnego znaczenia. Używaj tylko varchar(4000)
jeśli faktycznie potrzebujesz limitu 4000 znaków. Po prostu użyłbym text
- poza tym, że nie potrzebujemy żadnych zmiennych w ogóle tutaj, po uproszczeniu funkcji.
Jeśli nie użyłeś format()
, jednak zapoznaj się z instrukcją tutaj.
Typ zwrotu
Teraz, jeśli chodzi o twoje rzeczywiste pytanie:typ zwracany dla zapytania dynamicznego może być trudny, ponieważ SQL wymaga, aby został zadeklarowany najpóźniej w czasie wywołania. Jeśli masz w bazie danych tabelę, widok lub typ złożony, który już pasuje do listy definicji kolumn, możesz po prostu użyć tego:
CREATE FUNCTION foo()
RETURNS SETOF my_view AS
...
W przeciwnym razie przeliteruj listę definicji kolumn bez out za pomocą (najprostszego) RETURNS TABLE
:
CREATE FUNCTION foo()
RETURNS TABLE (col1 int, col2 text, ...) AS
...
Jeśli wpisujesz wiersz na bieżąco, możesz zwrócić anonimowe rekordy:
CREATE FUNCTION foo()
RETURNS SETOF record AS
...
Ale wtedy musisz dostarczyć listę definicji kolumn przy każdym wywołaniu, więc prawie nigdy tego nie używam.
Nie użyłbym SELECT *
najpierw. Użyj ostatecznej listy kolumn do zwrotu i odpowiednio zadeklaruj typ zwrotu:
CREATE OR REPLACE FUNCTION func_a(username text = '', databaseobject text = '')
RETURNS TABLE(col1 int, col2 text, col3 date)
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE
format ($f$SELECT v1.col1, v1.col2, v2.col3
FROM %s v1 LEFT JOIN %I v2 USING (id)$f$
, CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END
, databaseobject);
END
$func$;
W przypadku całkowicie dynamicznych zapytań rozważ najpierw zbudowanie zapytania w swoim kliencie, zamiast używania funkcji.
Najpierw musisz zrozumieć podstawy:
- Refaktoryzuj funkcję PL/pgSQL, aby zwrócić dane wyjściowe różnych zapytań SELECT
- PL/pgSQL w podręczniku Postgresa
Następnie są bardziej zaawansowane opcje z typami polimorficznymi, które pozwalają przekazać typ zwracany w czasie połączenia. Więcej w ostatnim rozdziale:
- Refaktoryzuj funkcję PL/pgSQL, aby zwrócić dane wyjściowe różnych zapytań SELECT