我正在编写python脚本来将表从MSSQL数据库同步到Postgresql DB。原作者倾向于使用超宽表,其中包含许多区域连续execute()
个洞。
对于插入速度,我在INSERT INTO A( {col_list} )
SELECT * FROM ( VALUES (row_1), (row_2),...) B( {col_list} )
NULL
在行序列化期间,它不可能在python中确定None
或NULL
的数据类型。这使得工作变得复杂。 timestamp
列,integer
列等中的所有connection.description
值都需要显式类型转换为适当的类型,或者Pg抱怨它。
目前,我正在检查每个列的数据库API ::timestamp
属性并比较列type_code,并根据需要添加类型转换,如None
。
但这会让人感觉很麻烦,额外的工作是:驱动程序已经将数据从文本转换为适当的python数据类型,现在我必须重做那些包含那么多onSelect
s的列。
有没有更好的方法来解决这个问题与优雅&简单?
答案 0 :(得分:2)
如果您需要 SELECT
,请使用@Nick's answer。
如果你需要它(比如使用CTE多次使用输入行),有一些变通方法取决于你的用例的细节。
示例,使用 完整行 :
时INSERT INTO A -- complete rows
SELECT * FROM (
VALUES ((NULL::A).*), (row_1), (row_2), ...
) B
OFFSET 1;
在这种特殊情况下, {col_list}
是可选噪音,因为我们无论如何都需要提供完整的行。
详细说明:
答案 1 :(得分:1)
您可以尝试使用json_populate_record(..)
从数据创建json,然后从json创建rowset。
postgres=# create table js_test (id int4, dat timestamp, val text);
CREATE TABLE
postgres=# insert into js_test
postgres-# select (json_populate_record(null::js_test,
postgres(# json_object(array['id', 'dat', 'val'], array['5', null, 'test']))).*;
INSERT 0 1
postgres=# select * from js_test;
id | dat | val
----+-----+------
5 | | test
您可以使用json_populate_recordset(..)
一次性对多行执行相同操作。你只需传递json 值即json数组。确保它不是json的数组。
所以这没关系:'[{"id":1,"dat":null,"val":6},{"id":3,"val":"tst"}]'::json
这不是:array['{"id":1,"dat":null,"val":6}'::json,'{"id":3,"val":"tst"}'::json]
select *
from json_populate_recordset(null::js_test,
'[{"id":1,"dat":null,"val":6},{"id":3,"val":"tst"}]')
答案 2 :(得分:1)
您可以直接将SELECT
子句附加到VALUES
,而不是从INSERT
插入,即:
INSERT INTO A ({col_list})
VALUES (row_1), (row_2), ...
当您从查询中插入时,Postgres在尝试推断列类型时会单独检查查询,然后尝试强制它们匹配目标表(仅发现它不能)。
直接从VALUES
列表插入时,它在执行类型推断时知道目标表,然后可以假设任何无类型的NULL
与相应的列匹配。