问题
How does one create multiple tables using a for loop in postgresql?
For example : I need to create c_emloyee, r_employee, i_employee, etc. I got a syntax error near FOR
! /bin/sh
#Invoke postgre
SQLVARCHAR="varchar"
SQLINTEGER="integer"
SQLBIGINT="bigint"
SQLSMALLINT="smallint"
SQLTINYINT="smallint"
SQLCIDR="cidr"
SQLBINARY="varbinary"
SQLTIME="timestamp"
SQLMACADDRESS="macaddr"
prefix[0]=c_
prefix[1]=r_
prefix[2]=s_
prefix[3]=i_
echo ${prefix[0]}
echo ${prefix[1]}
echo ${prefix[2]}
echo ${prefix[3]}
psql -d postgres <<EOF
BEGIN
FOR i IN 0 1 2 3 LOOP
create table ${prefix[i]}employee (e_name $SQLVARCHAR(32) primary key, type $SQLTINYINT not null, description $SQLVARCHAR(128), ip_address $SQLCIDR);
END LOOP;
END;
回答1:
You're making two mistakes:
FOR,BEGIN ... END, etc are part of PL/PgSQL, not regular SQL. You can't use these in plain SQL, you need aDOblock orCREATE OR REPLACE FUNCTION.You're seriously muddled about the order of evaluation. You've written a PL/PgSQL
FORloop overi, then you referenceiin a bash variable expansion. That'll be expanded during the generation of the PL/PgSQL function text, way before the variableiever exists.
You can see the latter problem clearly if you just replace psql -d postgres with cat so it prints the generated SQL you're trying to run:
BEGIN
FOR i IN 0 1 2 3 LOOP
create table c_employee (e_name varchar(32) primary key, type smallint not null, description varchar(128), ip_address cidr);
END LOOP;
END;
As you can see, ${prefix[i]} evaluated to c_ because i, being undefined, was treated as zero by bash. So the other entries in your prefix array will never be used.
You need to:
Use
DOblock orCREATE OR REPLACE FUNCTIONand a function call to execute your PL/PgSQL code; andUse
EXECUTE format(...)to run dynamic SQL
Alternately, you can generate the plain SQL CREATE TABLE statements in a bash for loop, doing away entirely with the need for PL/PgSQL. I would use this approach, as it's much simpler.
for p in ${prefix[*]}; do
echo "create table ${p}employee (e_name $SQLVARCHAR(32) primary key, type $SQLTINYINT not null, description $SQLVARCHAR(128), ip_address $SQLCIDR);"
done | psql
By the way, there is no such thing as postgre. I think you meant "Postgres" or "PostgreSQL".
You probably want bytea not varbinary. What's with the SQL types as variables, anyway? Are you trying to write a DDL generation system? If so, don't reinvent that wheel, there are lots of them already out there.
Also, if you're doing things like this, there's a fairly strong chance you need to read up on schemas (if you're trying to do multi-tenant), table partitioning, etc.
来源:https://stackoverflow.com/questions/13841773/how-to-create-multiple-tables-using-for-loop-in-postgresql