plpgsql在For循环中选择语句以创建多个CSV文件

时间:2013-12-09 16:54:56

标签: postgresql csv plpgsql pgadmin

我想重复以下查询8760次,在一年中每小时用1到8760替换'2'。我们的想法是为每小时创建一个单独的CSV文件,以便进一步处理。

COPY 
(SELECT *
FROM 
  public.completedsolarirad2012
WHERE 
  completedsolarirad2012."UniquetmstmpID" = 2)
TO 'C:\temp\2012hour2.csv' WITH DELIMITER ','
CSV HEADER

我已将以下功能放在一起(仅用几个小时进行测试):

CREATE OR REPLACE FUNCTION everyhour()
  RETURNS void AS
$BODY$BEGIN
FOR i IN 0..5 LOOP
  EXECUTE $x$ 
  COPY (
    SELECT *
    FROM 
    public.completedsolarirad2012
    WHERE 
    completedsolarirad2012."UniquetmstmpID" = i
    )
   TO $concat$ 'C:\temp.' || i::text 
         || '.out.csv' WITH DELIMITER ',' CSV HEADER $concat$
    $x$;
END LOOP;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION everyhour()
  OWNER TO postgres;

我似乎有两个不同的问题:

首先,我得到了:

  

错误:列“i”不存在。

其次,当我仅通过用例如“i”替换“i”来测试连接语句时“2”,我明白了:

  

错误:COPY到文件

不允许相对路径

我是postgres超级用户,所以我不明白为什么我遇到这个问题。

注意:删除串联语句周围的$concat$双引号会出现以下错误:

ERROR:  syntax error at or near "||"
LINE 9:    TO 'C:\temp.' || i::text

我将非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

假设您的服务器操作系统是Windows。

CREATE OR REPLACE FUNCTION everyhour()
  RETURNS void AS
$func$
BEGIN
FOR i IN 0..5 LOOP
   EXECUTE '
   COPY (
      SELECT *
      FROM   public.completedsolarirad2012 c
      WHERE  c."UniquetmstmpID" = ' || i || $x$)
   TO 'C:/temp.'$x$ || i || $x$'.out.csv' WITH DELIMITER ',' CSV HEADER$x$;
END LOOP;
END
$func$  LANGUAGE plpgsql;
  • 你有一层美元报价过多。
  • 你也意外地连接了这封信"我"而不是它的价值。
  • 使用正斜杠,即使是窗口也是如此。或者您可能需要加倍反斜杠,具体取决于您的设置。更多相关答案:
    PostgreSQL: export resulting data from SQL query to Excel/CSV

使用format()

更简单

自Postgres 9.1以来,您可以使用format()来简化复杂的连接:

CREATE OR REPLACE FUNCTION everyhour()
  RETURNS void AS
$func$
BEGIN
FOR i IN 0..5 LOOP
   EXECUTE format($x$COPY (
   SELECT *
   FROM   public.completedsolarirad2012 c
   WHERE  c."UniquetmstmpID" = %1$s)
   TO 'C:/temp.%1$s.out.csv' WITH DELIMITER ',' CSV HEADER$x$, i);
END LOOP;
END
$func$  LANGUAGE plpgsql;