尝试执行 FOREACH 时出现语法错误
Syntax error when trying to perform FOREACH
我有以下功能:
begin;
CREATE OR REPLACE FUNCTION convert_categories_16_12_2019() RETURNS VOID AS $$
DECLARE
category_index VARCHAR;
has_extra1_content BOOLEAN;
has_extra2_content BOOLEAN;
result_category BOOLEAN;
r RECORD;
BEGIN
FOR r IN (SELECT * FROM campaign_campaign) LOOP
result_category = FALSE;
has_extra1_content = FALSE;
has_extra2_content = FALSE;
FOREACH category_index IN ARRAY regexp_split_to_array(r.category, ',') LOOP
IF (category_index::int = 6 OR
category_index::int = 7)
THEN has_extra1_content = TRUE
END IF;
IF (category_index::int = 0 OR
category_index::int = 1 OR
category_index::int = 2 OR
category_index::int = 3 OR
category_index::int = 4 OR
category_index::int = 5)
THEN has_extra2_content = TRUE
END IF;
CASE
WHEN has_extra1_content AND NOT has_extra2_content
THEN result_category = 0;
WHEN has_extra2_content AND has_extra1_content
THEN result_category = 1;
ELSE
result_category = 2;
END CASE;
END LOOP;
UPDATE campaign_campaign
SET campaign_campaign.category = result_category
WHERE id = r.id;
END LOOP;
RETURN;
END
$$ LANGUAGE plpgsql;
select convert_categories_16_12_2019();
DROP FUNCTION convert_categories_16_12_2019;
rollback;
但是当我尝试 运行 时,我得到:
ERROR: ERROR: syntax error(near: "END")
LINE 21: END IF;
有人可以解释为什么会出现这个错误吗?我没有看到任何语法问题。
我使用的资源:
https://dba.stackexchange.com/questions/234657/syntax-error-when-using-exception-inside-for-loop
https://www.postgresql.org/docs/9.4/plpgsql-control-structures.html
问题是 THEN
分支中缺少 ;
after 语句,因此应该是:
IF (category_index::int = 6 OR
category_index::int = 7)
THEN has_extra1_content = TRUE; /* semicolon here too! */
END IF;
亲爱的 Whosebug 用户,我已经用这个 UPDATE
语句替换了函数:
UPDATE campaign_campaign SET category =
CASE WHEN (
campaign_campaign.category != ''
AND regexp_split_to_array(campaign_campaign.category, ',')::int[] && ARRAY[6,7]
AND NOT regexp_split_to_array(campaign_campaign.category, ',')::int[] && ARRAY[0,1,2,3,4,5]
) THEN 0
WHEN (
campaign_campaign.category != ''
AND regexp_split_to_array(campaign_campaign.category, ',')::int[] && ARRAY[0,1,2,3,4,5]
AND NOT regexp_split_to_array(campaign_campaign.category, ',')::int[] && ARRAY[6,7]
) THEN 1
ELSE 2
END;
看起来你可以将所有内容替换为:
UPDATE campaign_campaign
SET category =
CASE WHEN string_to_array(category, ',') && '{6,7}'::text[] THEN
CASE WHEN string_to_array(category, ',') && '{0,1,2,3,4,5}'::text[] THEN '1' ELSE '0' END
ELSE '2' END;
这假定您的原始文本字符串中没有无关紧要的空格。否则,仍然需要强制转换为 int[]
(就像您所做的那样)。
UPDATE
语句中的目标列不能是 table 限定的,顺便说一句,所以不是 SET campaign_campaign.category = ...
.
然后您应该将列 category
转换为 integer
。
或者在 boolean
列中使用 true
/ false
/ null
。
我有以下功能:
begin;
CREATE OR REPLACE FUNCTION convert_categories_16_12_2019() RETURNS VOID AS $$
DECLARE
category_index VARCHAR;
has_extra1_content BOOLEAN;
has_extra2_content BOOLEAN;
result_category BOOLEAN;
r RECORD;
BEGIN
FOR r IN (SELECT * FROM campaign_campaign) LOOP
result_category = FALSE;
has_extra1_content = FALSE;
has_extra2_content = FALSE;
FOREACH category_index IN ARRAY regexp_split_to_array(r.category, ',') LOOP
IF (category_index::int = 6 OR
category_index::int = 7)
THEN has_extra1_content = TRUE
END IF;
IF (category_index::int = 0 OR
category_index::int = 1 OR
category_index::int = 2 OR
category_index::int = 3 OR
category_index::int = 4 OR
category_index::int = 5)
THEN has_extra2_content = TRUE
END IF;
CASE
WHEN has_extra1_content AND NOT has_extra2_content
THEN result_category = 0;
WHEN has_extra2_content AND has_extra1_content
THEN result_category = 1;
ELSE
result_category = 2;
END CASE;
END LOOP;
UPDATE campaign_campaign
SET campaign_campaign.category = result_category
WHERE id = r.id;
END LOOP;
RETURN;
END
$$ LANGUAGE plpgsql;
select convert_categories_16_12_2019();
DROP FUNCTION convert_categories_16_12_2019;
rollback;
但是当我尝试 运行 时,我得到:
ERROR: ERROR: syntax error(near: "END")
LINE 21: END IF;
有人可以解释为什么会出现这个错误吗?我没有看到任何语法问题。
我使用的资源:
https://dba.stackexchange.com/questions/234657/syntax-error-when-using-exception-inside-for-loop
https://www.postgresql.org/docs/9.4/plpgsql-control-structures.html
问题是 THEN
分支中缺少 ;
after 语句,因此应该是:
IF (category_index::int = 6 OR
category_index::int = 7)
THEN has_extra1_content = TRUE; /* semicolon here too! */
END IF;
亲爱的 Whosebug 用户,我已经用这个 UPDATE
语句替换了函数:
UPDATE campaign_campaign SET category =
CASE WHEN (
campaign_campaign.category != ''
AND regexp_split_to_array(campaign_campaign.category, ',')::int[] && ARRAY[6,7]
AND NOT regexp_split_to_array(campaign_campaign.category, ',')::int[] && ARRAY[0,1,2,3,4,5]
) THEN 0
WHEN (
campaign_campaign.category != ''
AND regexp_split_to_array(campaign_campaign.category, ',')::int[] && ARRAY[0,1,2,3,4,5]
AND NOT regexp_split_to_array(campaign_campaign.category, ',')::int[] && ARRAY[6,7]
) THEN 1
ELSE 2
END;
看起来你可以将所有内容替换为:
UPDATE campaign_campaign
SET category =
CASE WHEN string_to_array(category, ',') && '{6,7}'::text[] THEN
CASE WHEN string_to_array(category, ',') && '{0,1,2,3,4,5}'::text[] THEN '1' ELSE '0' END
ELSE '2' END;
这假定您的原始文本字符串中没有无关紧要的空格。否则,仍然需要强制转换为 int[]
(就像您所做的那样)。
UPDATE
语句中的目标列不能是 table 限定的,顺便说一句,所以不是 .SET campaign_campaign.category = ...
然后您应该将列 category
转换为 integer
。
或者在 boolean
列中使用 true
/ false
/ null
。