Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

plpgsql: concatenation of variable into FROM clause

I'm new to Postgresql and struggling to build a function for looping over a series of CSV files and loading them. I can make the COPY work just fine with a single file, but I'm unable to get the FOR LOOP syntax correct. I'm trying to substitute a year number as my flies are named /path/tmp.YEAR.out.csv

This is what I've hacked up:

CREATE OR REPLACE FUNCTION test() RETURNS void as $$
BEGIN
  FOR i IN 1982..1983 LOOP
    COPY myTable 
    FROM '/path/tmp.' || i::VARCHAR || '.out.csv'
    delimiters ','
  END LOOP;
END;
$$ LANGUAGE 'plpgsql';

This throws an error at the first ||. So I suspect I'm managing the concat of the variable i improperly. Any tips?

like image 568
JD Long Avatar asked Jun 06 '11 21:06

JD Long


People also ask

What does := mean in Plpgsql?

:= is the assignment operator in PL/pgSQL. The expression searchsql:= searchsql || ' WHERE 1=1 ' ; appends the string ' WHERE 1=1 ' to the current value of the variable searchsql.

What is || in PostgreSQL?

The PostgreSQL concatenate operator ( || ) is used to concatenate two or more strings and non strings.

How do I concatenate strings and integers in PostgreSQL?

PostgreSQL allows you to directly concatenate strings, columns and int values using || operator. Here is the SQL query to concatenate columns first_name and last_name using || operator. You can even concatenate string with int using || operator.


2 Answers

CREATE OR REPLACE FUNCTION test() RETURNS void as $$
BEGIN
FOR i IN 1982..1983 LOOP
  EXECUTE 'COPY myTable FROM ''/path/tmp.' || i::text
                                           || '.out.csv'' DELIMITERS '',''; ';
END LOOP;
END;
$$ language plpgsql;
like image 155
Seth Robertson Avatar answered Nov 13 '22 22:11

Seth Robertson


I don't think I'd use plpgsql for that. A shell script could be much more generally useful:

#!/bin/sh

DBHOST=mydbhost
DBNAME=mydbname

files=$1
target=$2

for file in ${files}; do
    psql -h ${DBHOST} ${DBNAME} -c "\copy ${target} FROM '${file}' delimiters ','"
done

example usage:

csv2psql "$(ls *.out.csv)" someschema.tablename

Note: This way you also sidestep the problem of reading files with COPY which requires the postgres server user to have read permissions on the file.

like image 20
jduckles Avatar answered Nov 13 '22 22:11

jduckles