只需获取INSERT statement 的语法即可:
INSERT INTO campaign (id, column_name)
SELECT g.g, t.column_name
FROM (SELECT column_name FROM campaign LIMIT 1) t -- picking arbitrary row
,generate_series(50, 500) g(g); -- 451 times
CROSS JOIN 到 generate_series() 将每个选定的行相乘。
选择一个 任意 行,因为问题没有定义“第一”。表中没有自然顺序。要选择某一行,请添加 ORDER BY 和/或 WHERE。
没有语法快捷方式来选择除了名为“id”的列之外的所有列。您必须使用完整的行或提供选定列的列表。
使用动态 SQL 实现自动化
要解决这个问题,请从目录表(或信息模式)构建查询字符串,并在 plpgsql 函数(或其他一些程序语言)中使用 EXECUTE。仅使用pg_attribute。
format() 需要 Postgres 9.1 或更高版本。
CREATE OR REPLACE FUNCTION f_multiply_row(_tbl regclass
, _idname text
, _minid int
, _maxid int)
RETURNS void AS
$func$
BEGIN
EXECUTE (
SELECT format('INSERT INTO %1$s (%2$I, %3$s)
SELECT g.g, %3$s
FROM (SELECT * FROM %1$s LIMIT 1) t
,generate_series($1, $2) g(g)'
, _tbl
, _idname
, string_agg(quote_ident(attname), ', ')
)
FROM pg_attribute
WHERE attrelid = _tbl
AND attname <> _idname -- exclude id column
AND NOT attisdropped -- no dropped (dead) columns
AND attnum > 0 -- no system columns
)
USING _minid, _maxid;
END
$func$ LANGUAGE plpgsql;
根据您的情况致电:
SELECT f_multiply_row('campaign', 'id', 50, 500);
SQL Fiddle.
要点
-
正确转义标识符以避免 SQL 注入。使用format() 和regclass 作为表名。详情:
_idname 是要排除的列名(在您的情况下为“id”)。区分大小写!
在USING 子句中传递值。 generate_series($1, $2) 中的 $1 和 $2 引用这些参数(不是函数参数)。
相关答案中的更多解释。尝试搜索:
https://stackoverflow.com/search?q=[plpgsql]+[dynamic-sql]+format+pg_attribute