我们正在从SQL Server转换为Postgres。我有一个我想要容纳的场景。它涉及将记录从一个表插入到另一个表中,而不列出所有列。我意识到这不是推荐的练习,但是现在让我们把它放在一边。
drop table if exists pk_test_table;
create table public.pk_test_table
(
recordid SERIAL PRIMARY KEY NOT NULL,
name text
);
--example 1: works and will insert a record with an id of 1
insert into pk_test_table values(default,'puppies');
--example 2: fails
insert into pk_test_table
select first_name from person_test;
我在第二个例子中收到错误:
专栏" recordid"是整数类型但表达式是类型 字符变化提示:你需要重写或强制转换 表达
default
关键字将告诉数据库获取下一个值
有没有办法在第二个例子中使用这个关键字?或者某种方式告诉数据库忽略自动递增的列,只是像普通的那样填充它们?
我宁愿不使用子查询来获取下一个" id"。
此功能适用于SQL Server,因此存在问题
在此先感谢您的帮助!
答案 0 :(得分:1)
如果您无法列出列名,则应该使用DEFAULT
关键字,就像您在简单插入示例中所做的那样。这不适用于insert into ... select ...
。
为此,您需要调用nextval
。不需要子查询,只需:
insert into pk_test_table
select nextval('pk_test_table_id_seq'), first_name from person_test;
您需要知道序列名称。您可以使用仅将表名作为参数的函数,根据表名从information_schema
获取并推断其主键。它很难看,但它起作用。我不认为有任何方法需要知道表名。
答案 1 :(得分:0)
您已将值插入第一列,但您需要在第二个位置添加值。
因此,您可以使用INSERT INTO table(field) VALUES(value)
语法。
由于您需要从另一个表中获取值,因此必须删除VALUES
并将子查询放在那里。
insert into pk_test_table(name)
select first_name from person_test;
我希望它有所帮助
答案 2 :(得分:0)
我是通过一个单独的函数这样做的 - 尽管我认为我通过基于每个字段的DEFAULT设置的表级来解决问题。
create table public.pk_test_table
(
recordid integer NOT NULL DEFAULT nextval('pk_test_table_id_seq'),
name text,
field3 integer NOT NULL DEFAULT 64,
null_field_if_not_set integer,
CONSTRAINT pk_test_table_pkey PRIMARY KEY ("recordid")
);
有功能:
CREATE OR REPLACE FUNCTION func_pk_test_table() RETURNS void AS
$BODY$
INSERT INTO pk_test_table (name)
SELECT first_name FROM person_test;
$BODY$
LANGUAGE sql VOLATILE;
然后只需通过SELECT FROM func_pk_test_table();
执行该功能请注意,只要约束允许,就不必指定所有字段。