Ошибка типа во время цикла по массиву в PL / pgSQL - PullRequest
0 голосов
/ 28 октября 2018

Я новичок в PostgreSQL.Попытка зациклить здесь значения, которые я передаю:

companyregistration, просто вызывая companyRegistrationValidator

Вызов функции:

SELECT companyregistration(
'876786576544', 
'TraderAnalytics',
'TraderAnalytics@gmail.com,
'@kjvfhjh88976',
ARRAY['86578657865','Natali','Vladimirov','Natali.Vladimirov1990@gmail.com', '+@jvfhjh88976'],
ARRAY [['Maks','Burkov'],['Yan','Burkov']],
'Netherlands',
'Company');
[2018-10-28 18:29:15] [42804] ERROR: FOREACH expression must yield an array, not type text
[2018-10-28 18:29:15] Where: PL/pgSQL function companyregistrationvalidator(character varying,character varying,character varying,character varying,text[],text[],character varying) line 28 at FOREACH over array

Определение функции:

CREATE OR REPLACE FUNCTION companyRegistrationValidator (company_id VARCHAR, comp_name VARCHAR, comp_email VARCHAR, comp_password VARCHAR, employees text[], creators text[], country VARCHAR)
  RETURNS BOOLEAN AS $$
DECLARE
    checked BOOLEAN := FALSE ;
    r_id VARCHAR; r_name VARCHAR; r_email VARCHAR; r_password VARCHAR; r_country VARCHAR;
    cr_counter INTEGER = 0; em_counter INTEGER = 0; c_ar_length INTEGER  = 0; e_ar_length INTEGER = 0;
    ar_index text; creator text; val text;

BEGIN
    SELECT id_r , email_r , password_r , country_r , firstname_r INTO r_id , r_email , r_password, r_country , r_name FROM regex;

    c_ar_length := cardinality(creators);
    e_ar_length := cardinality(employees);

    FOREACH val IN ARRAY employees LOOP
        IF val ~ r_id THEN em_counter := +1;
        ELSEIF val ~ r_name THEN  em_counter := +1;
        ELSEIF val ~ r_email THEN em_counter := +1;
        ELSEIF val ~ r_password THEN em_counter := +1;
        END IF;
    END LOOP;

    FOREACH creator IN ARRAY creators LOOP
        FOREACH ar_index IN ARRAY creator LOOP
            IF ar_index ~ r_name THEN cr_counter := +1;
            END IF;
        END LOOP;
    END LOOP;

    IF cr_counter = c_ar_length AND em_counter = e_ar_length AND company_id ~ r_id AND comp_name ~ r_name AND comp_email ~ r_email AND comp_password ~ r_password AND country ~ r_country
        THEN checked := TRUE;
    END IF;

    RETURN checked;
 END;
$$ LANGUAGE plpgsql;

В чем ошибка в моем коде?

1 Ответ

0 голосов
/ 29 октября 2018

Эта конструкция с вложенным циклом хороша для указанной вами ошибки:

    FOREACH creator IN ARRAY creators LOOP
        FOREACH ar_index IN ARRAY creator LOOP
            IF ar_index ~ r_name THEN cr_counter := +1;
            END IF;
        END LOOP;
    END LOOP;

Переменная цикла creator во внешнем цикле определяется как тип text, что нормально.Но вы не можете вложить другой цикл через creator, как пытаетесь - и вам не нужно.
Руководство по Цикл по массивам :

Элементы посещаются в порядке хранения, независимо от количества измерений массива.

Итак, чтобы пройти по всем базовым элементам, независимо от размеров массива , все, что вам нужно, это:

    FOREACH creator IN ARRAY creators LOOP
       IF creator ~ r_name THEN cr_counter := cr_counter + 1;
       END IF;
    END LOOP;

Также обратите внимание, что cr_counter := +1 не будет увеличивать cr_counter, как вы, кажется, пытаетесь.Просто назначил бы 1 повторно.Я заменил его на выражение для фактического приращения.

Однако , как это часто бывает, если только массив не является крошечным, подход на основе множеств будет (очень) Быстрее.Например:

    SELECT INTO cr_counter
           count(*) FILTER (WHERE _creator ~ r_name)::int
    FROM   unnest(creators) _creator;

(И вы действительно хотите, чтобы оператор регулярных выражений ~ был там?)

...