4

I would like to repeat the following query 8760 times, replacing ‘2’ with 1 to 8760 for every hour in the year. The idea is to create a separate CSV file for each hour for further processing.

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

I have put together the following function (testing with only a few hours):

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 seem to be having two separate problems:

Firstly, I’m getting:

Error: column "i" does not exist.

Secondly, when I test the concatenation statement only by replacing “i” with e.g. “2”, I get:

Error: relative path not allowed for COPY to file

I am the postgres superuser, so I do not understand why I am having this problem.

Note: Removing the $concat$ double-quoting around the concatenation statement gives the following error:

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

I would be very grateful for any help.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
Diane Palmer
  • 49
  • 1
  • 6
  • Since we are dealing with the file system, you need to provide the OS of the server. Looks like Windows. And you *alyways* need to provide the version of Postgres in use. – Erwin Brandstetter Dec 09 '13 at 17:04

1 Answers1

2

Assuming your server OS is 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;
  • You had one layer of dollar-quoting too many.
  • You also accidentally concatenated the letter "i" instead of its value.
  • Use forward-slashes, even with windows. Or you may have to double up the backslashes, depending on your settings. More in this related answer:
    PostgreSQL: export resulting data from SQL query to Excel/CSV

Simpler with format()

Since Postgres 9.1 you can use format() to simplify complex concatenations:

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;
Community
  • 1
  • 1
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • format() works beautifully - many thanks. However, I'm still having problems with the concatenation: ERROR: syntax error at or near "||" LINE 9: TO 'C:/temp/' || i::text. Format() solves my problem but I would really like to figure out what I am doing wrong with the concatenation for future reference. Sorry, I should have said I'm using OS Windows 7 PostgreSQL 9.3. I'll give the details properly in future. – Diane Palmer Dec 10 '13 at 15:52
  • @DianePalmer: Sorry, my first version had missing quotes. Should be fixed now. – Erwin Brandstetter Dec 10 '13 at 16:15