Оператор выбора SQL, дающий те же результаты, что и цикл PL / pgSQL FOR - PullRequest
0 голосов
/ 01 мая 2019

Мне трудно понять, когда использовать цикл PL / pgSQL FOR по сравнению с обычным SQL.

Этот вопрос определенно показывает мою наивность, но вот что меня смущает:

с учетом этой таблицы:

CREATE TABLE bins  AS 
SELECT * FROM GENERATE_SERIES(1, 10) AS id;

, если я хочу добавить плюс 1в поле id в каждой строке я бы сделал это:

select id+1 from bins;

, который бы правильно вернул

2
3
4
5
6
7
8
9
10
11

Теперь, если бы я использовал функцию PL / pgSQL для этой операции,это будет выглядеть примерно так:

CREATE OR REPLACE FUNCTION add_one(
n integer
) 
RETURNS VOID AS $$
DECLARE
    rec RECORD;
BEGIN
    FOR rec IN SELECT id
        FROM bins
    LOOP 
 RAISE NOTICE '%', rec.id+n;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

, тогда

select add_one(1)

даст

-- Executing query:
select add_one(1)
NOTICE:  2
CONTEXT:  PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE:  3
CONTEXT:  PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE:  4
CONTEXT:  PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE:  5
CONTEXT:  PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE:  6
CONTEXT:  PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE:  7
CONTEXT:  PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE:  8
CONTEXT:  PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE:  9
CONTEXT:  PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE:  10
CONTEXT:  PL/pgSQL function add_one(integer) line 9 at RAISE
NOTICE:  11
CONTEXT:  PL/pgSQL function add_one(integer) line 9 at RAISE

, поэтому мой вопрос в том, что оператор SQL в некотором родедействует как цикл for, потому что в этом примере он добавляет 1 к каждой строке ... это то же самое, что происходит в функции PL / pgSQL.это точное описание?

1 Ответ

0 голосов
/ 02 мая 2019

Ваше описание является точным.

Вероятно, ваша самая большая проблема на данный момент состоит в том, чтобы понять непроцедурную природу SQL.На этом языке вы не указываете шаги, необходимые для достижения результата, вы описываете только тот результат, который вам нужен.

Таким образом, оператор SQL, который вы использовали выше, вы хотите, чтобы id увеличилось на единицу для каждой строкив таблице.Если база данных делает это, выполняя цикл внутренне или с помощью стихийного бедствия, это не ваша основная задача.

Поначалу это странно для многих процедурных программистов, но это делает жизнь лучше, когда вы привыкнете к ней: вам не нужно знать все внутренности базы данных, чтобы найти лучший способ обработки запроса.Оптимизатор сделает это за вас, и обычно лучше, чем вы могли бы сделать это самостоятельно.

Конечно, любопытно узнать, как обрабатывается запрос внутри.Для этого вы используете оператор EXPLAIN.Это особенно необходимо для анализа и устранения проблем с производительностью.

Практическое правило состоит в том, что обычно лучше выполнять как можно большую часть работы в одном большом операторе SQL, чем во многих простых небольших, связанных вместе скод приложения.Это связано с тем, что таким образом меньше накладных расходов, а также потому, что большее выражение часто открывает больше возможностей для оптимизатора.Например, вложенные циклы - это самый простой, но не всегда лучший способ решения проблемы.

...