如何在plpgsql中引用模式变量

时间:2016-02-15 22:51:51

标签: postgresql plpgsql

我正在尝试学习plpgsql代码以自动化数据库中的某些数据清理。

我目前的任务是用'NaN'替换数字字段中的所有'999'值。我想要做的是: 1)查找模式中的所有数字列 2)循环使用这些并使用'update / replace'

我的代码如下。我认为我的主要问题是找出如何在update语句中引用schema.table(但我确信还有其他一些我做得不太好的事情。)

我得到的错误是无法识别关系。 任何帮助将不胜感激

贝基

CREATE OR REPLACE FUNCTION household.nodata_replace(schemanm text)
RETURNS VOID as $$
DECLARE
  cname text;
  tname text;
BEGIN
   --FOR col IN
  for cname,tname in SELECT column_name::text,table_name::text FROM information_schema.columns
     where table_schema = schemanm and data_type in ('integer','double precision')

     LOOP

     RAISE NOTICE 'cname is: % from %', cname, tname;
     EXECUTE 'update '||schemanm::regclass||'.' ||tname::regclass||
 ' set ' || quote_ident(cname) ||' = replace('  || quote_ident(cname) ||', 999, NaN);';
     END LOOP;


END;
$$
LANGUAGE plpgsql;

2 个答案:

答案 0 :(得分:2)

我宁愿使用format()。如果需要,占位符%I负责正确引用标识符。

replace()用于字符串操作,不用于替换数字。要使用set xxx = 'NaN' 分配值NaN,您无法对integer值执行此操作。整数不支持NaN

所以你的动态SQL归结为:

execute format('update %I.%I set %I = ''NaN'' where %I = 999, schemanm, tname, cname, cname);

但是您需要将where子句更改为不包含integer列。您可能还希望包含numericreal

and data_type in ('numeric','double precision', 'real')

如果您只想标记“缺少信息”,我宁愿将null存储在这些列中。在这种情况下,您无需区分不同的数据类型:

execute format('update %I.%I set %I = null where %I = 999, schemanm, tname, cname, cname);

答案 1 :(得分:1)

尝试重新编写您的查询,如下所示:

EXECUTE 'update '|| (schemanm||'.'||tname)::regclass ||' set ' || quote_ident(cname) ||' = ''NaN'' WHERE '|| quote_ident(cname) ||' = 999;'

因为转向regclass正试图在已注册的关系中进行搜索。和架构不是关系。

或者你可以

EXECUTE 'update '|| quote_ident(schemanm)||'.'||quote_ident(tname) ||' set ' || quote_ident(cname) ||' = ''NaN'' WHERE '|| quote_ident(cname) ||' = 999;'