Guy*_*y s 6 arrays postgresql loops plpgsql
我正在尝试遍历几个字段并在它们上运行一个函数:
FOR field IN ARRAY['f1','f2'] LOOP
execute pg_temp.converFieldToLower(newTableNameRaw,field)
END LOOP;
Run Code Online (Sandbox Code Playgroud)
这是我正在尝试使用的功能:
CREATE OR REPLACE FUNCTION pg_temp.converFieldToLower(t varchar, f varchar) RETURNS void AS $$
#variable_conflict use_variable
BEGIN
EXECUTE concat_ws (' ', 'UPDATE',t,'SET',f,'= LOWER(',f,')');
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
看起来这不是声明数组的正确方法,我做错了什么?
Run Code Online (Sandbox Code Playgroud)ERROR: syntax error at or near "ARRAY" LINE 49: FOR field IN ARRAY['f1','f2'] LOOP
kli*_*lin 10
该FOREACH循环是专门用于通过数组的值,例如的元素迭代设计:
FOREACH field IN ARRAY ARRAY['f1','f2'] LOOP
execute pg_temp.converFieldToLower(newTableNameRaw,field) into res;
END LOOP;
Run Code Online (Sandbox Code Playgroud)
该功能是在Postgres 9.1中引入的.
EXECUTE用于动态 SQL,循环中没有任何动态内容。
您可能打算使用PERFORM丢弃结果。看:
有FOREACHfor循环,就像@klin已经提供的一样。看:
通常,纯 SQL 更简单、更快:
PERFORM pg_temp.converFieldToLower(newTableNameRaw, t.val)
FROM unnest('{f1,f2}'::text[]) t(val);
Run Code Online (Sandbox Code Playgroud)
对于只有两个或三个常量或变量,只需将其拼写出来即可避免任何开销。更简单、更快。
PERFORM pg_temp.converFieldToLower(newTableNameRaw, 'f1');
PERFORM pg_temp.converFieldToLower(newTableNameRaw, 'f2');
Run Code Online (Sandbox Code Playgroud)
FOREACH对于每个数组元素进行更复杂的操作可能是一个好主意。
您添加的函数容易受到SQL 注入攻击。看:
这是一个安全的变体format():
CREATE OR REPLACE FUNCTION pg_temp.converFieldToLower(t text, f text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format(
'UPDATE %1$I
SET %2$I = lower(%2$I)
WHERE %2$I <> lower(%2$I)', t, f);
END
$func$;
Run Code Online (Sandbox Code Playgroud)
在执行此操作时,我添加了一个WHERE子句来跳过不会更改行的更新操作 - 完全成本。