2

如何for在 postgresql 中使用循环创建多个表?

例如:我需要创建 c_emloyee、r_employee、i_employee 等。在 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;
4

1 回答 1

2

你犯了两个错误:

  • FOR, BEGIN ... END, 等是 PL/PgSQL 的一部分,而不是常规 SQL。您不能在普通 SQL 中使用这些,您需要一个DO块或CREATE OR REPLACE FUNCTION.

  • 您对评估的顺序感到非常困惑。您已经编写了一个 PL/PgSQLFOR循环i,然后ibash变量扩展中引用。这将在 PL/PgSQL 函数文本的生成过程中被扩展,远在变量i存在之前。

如果您只是替换为,则可以清楚地看到后一个问题psql -d postgrescat因此它会打印您尝试运行的生成的 SQL:

 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;

如您所见,${prefix[i]}评估为c_因为i未定义,bash 将其视为零。prefix因此,您的数组中的其他条目将永远不会被使用。

你需要:

  • 使用DO块或CREATE OR REPLACE FUNCTION函数调用来执行您的 PL/PgSQL 代码;和

  • 用于EXECUTE format(...)运行动态 SQL

或者,您可以在 for 循环中生成纯 SQLCREATE TABLE语句,bash完全不需要 PL/PgSQL。我会使用这种方法,因为它更简单。

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

顺便说一句,没有这样的东西postgre。我认为您的意思是“Postgres”或“PostgreSQL”。

你可能bytea不想varbinary。无论如何,作为变量的 SQL 类型有什么用?您是否正在尝试编写 DDL 生成系统?如果是这样,不要重新发明那个轮子,那里已经有很多了。

此外,如果您正在做这样的事情,那么您很有可能需要阅读模式(如果您尝试进行多租户)、表分区等。

于 2012-12-12T23:40:17.487 回答