Функция дезинфекция
Това, което имате в момента, може да бъде опростено/дезинфекцирано до:
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$;
Нуждаете се само от допълнителни екземпляри на BEGIN ... END
в тялото на функцията, за да стартирате отделни кодови блокове със собствен обхват, което рядко е необходимо.
Стандартният оператор за конкатенация на SQL е ||
. +
е "творческо" допълнение на бившия ви доставчик.
Не използвайте CaMeL-case идентификатори, освен ако не ги цитирате. Най-добре не ги използвайте изобщо Вижте:
- Именната на колоните в PostgreSQL зависят ли от малките букви?
varchar(4000)
също така е съобразена със специфично ограничение на SQL Server. Той няма специфично значение в Postgres. Използвайте само varchar(4000)
ако наистина имате нужда от ограничение от 4000 знака. Бих използвал просто text
- с изключение на това, че изобщо не се нуждаем от никакви променливи тук, след опростяване на функцията.
Ако не сте използвали format()
, но вижте ръководството тук.
Тип връщане
Сега, за действителния ви въпрос:Типът на връщане за динамична заявка може да бъде труден, тъй като SQL изисква това да бъде декларирано най-късно в момента на повикване. Ако имате таблица или изглед или съставен тип във вашата база данни, които вече съответстват на списъка с дефиниции на колони, можете просто да използвате това:
CREATE FUNCTION foo()
RETURNS SETOF my_view AS
...
В противен случай напишете списъка с дефиниции на колони с out с (най-простият) RETURNS TABLE
:
CREATE FUNCTION foo()
RETURNS TABLE (col1 int, col2 text, ...) AS
...
Ако правите типа ред, докато вървите, можете да върнете анонимни записи:
CREATE FUNCTION foo()
RETURNS SETOF record AS
...
Но тогава трябва да предоставяте списък с дефиниции на колони с всяко извикване, така че почти никога не го използвам.
Не бих използвал SELECT *
да започнем с. Използвайте окончателен списък с колони, за да върнете и съответно декларирайте своя тип връщане:
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$;
За напълно динамични заявки помислете за начало на изграждането на заявката във вашия клиент, вместо да използвате функция.
Първо трябва да разберете основите:
- Рефакторирайте функция PL/pgSQL, за да върнете резултатите от различни SELECT заявки
- PL/pgSQL в ръководството на Postgres
След това има по-разширени опции с полиморфни типове, които ви позволяват да предадете връщания тип по време на повикване. Повече в последната глава на:
- Рефакторирайте функция PL/pgSQL, за да върнете резултатите от различни SELECT заявки