【问题标题】:Type error while looping through array in PL/pgSQL在 PL/pgSQL 中循环遍历数组时输入错误
【发布时间】:2019-04-01 16:41:25
【问题描述】:

我是 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;

我的代码有什么错误?

【问题讨论】:

  • 哦,我明白了。不久前我有一个类似的问题。当您在嵌套 FOREACH 中遍历数组时。那是行不通的。第一个 FOREACH 已经将所有内容取消嵌套在一个“级别”中,因此它产生文本,而不是数组,因此您不能对其结果进行另一个 FOREACH。不记得我是如何绕过它的。
  • 如果你能用代码示例给我答案,那就太好了

标签: arrays postgresql loops foreach plpgsql


【解决方案1】:

这个嵌套循环结构对你引用的错误很有好处:

    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 嵌套另一个循环 - 您也不需要这样做。
The manual on Looping Through Arrays:

元素按存储顺序访问,与数组维数无关。

因此,要遍历所有基本元素,无论数组尺寸如何,您只需要:

    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;

(您确定要在此处使用正则表达式运算符~ 吗?)

【讨论】:

  • 感谢您的完整回答,我很感激我会测试您的示例..
猜你喜欢
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
相关资源
最近更新 更多