Python 如何避免在Postgresql中插入时显式转换NULL

Python 如何避免在Postgresql中插入时显式转换NULL,python,postgresql,psycopg2,Python,Postgresql,Psycopg2,我正在编写python脚本,以便将表从MSSQL数据库同步到Postgresql数据库。最初的作者倾向于使用超宽表,其中有许多区域连续的NULL孔 为了提高插入速度,我在execute() 在行序列化期间,无法确定python中NULL或None的数据类型。这使工作变得复杂。timestamp列、integer列等中的所有NULL值都需要显式类型转换为适当的类型,否则Pg会对此提出投诉 目前,我正在检查DB API连接。description属性,比较每列的列类型\u代码,并根据需要添加类型转换

我正在编写python脚本,以便将表从MSSQL数据库同步到Postgresql数据库。最初的作者倾向于使用超宽表,其中有许多区域连续的
NULL

为了提高插入速度,我在
execute()

在行序列化期间,无法确定python中
NULL
None
的数据类型。这使工作变得复杂。
timestamp
列、
integer
列等中的所有
NULL
值都需要显式类型转换为适当的类型,否则Pg会对此提出投诉

目前,我正在检查DB API
连接。description
属性,比较每列的列类型\u代码,并根据需要添加类型转换,如
::timestamp

但这感觉很麻烦,需要做额外的工作:驱动程序已经将数据从文本转换为正确的python数据类型,现在我必须为包含许多
None
s的列重做


有没有更好的方法来解决这一问题,使其简洁明了?

您可以尝试从数据创建json,然后使用
json\u populate\u record(…)
从json创建行集

您可以使用
json\u populate\u 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"}]')

您可以尝试从数据创建json,然后使用
json\u populate\u record(..)
从json创建行集

您可以使用
json\u populate\u 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"}]')

您可以将
子句直接附加到
插入
,而不是从
选择插入,即:

INSERT INTO A ({col_list}) 
VALUES (row_1), (row_2), ...
当您从查询中插入时,Postgres在尝试推断列类型时会孤立地检查查询,然后尝试强制它们与目标表匹配(结果发现它不能)


当您直接从
值列表中插入时,它在执行类型推断时知道目标表,然后可以假定任何未类型化的
NULL
与相应列匹配。

而不是从
选择中插入,您可以将
子句直接附加到
插入
,即:

INSERT INTO A ({col_list}) 
VALUES (row_1), (row_2), ...
当您从查询中插入时,Postgres在尝试推断列类型时会孤立地检查查询,然后尝试强制它们与目标表匹配(结果发现它不能)

当您直接从
值列表中插入时,它在执行类型推断时知道目标表,然后可以假定任何未类型化的
NULL
与相应列匹配。

如果您不需要
选择
,请使用。
如果您需要它(如使用CTE多次使用输入行),根据用例的详细信息,有一些变通方法

例如,使用完整行时:

INSERT INTO A -- complete rows
SELECT * FROM (
   VALUES ((NULL::A).*), (row_1), (row_2), ...
   ) B
OFFSET 1;
插入到--完整的行中
从中选择*(
值((NULL::A)。*),(第1行),(第2行)。。。
)B
偏移量1
{col_list}
在这种特殊情况下是可选的噪声,因为我们无论如何都需要提供完整的行

详细说明:

    • 如果您不需要
      选择
      ,请选择。
      如果您需要它(如使用CTE多次使用输入行),根据用例的详细信息,有一些变通方法

      例如,使用完整行时:

      INSERT INTO A -- complete rows
      SELECT * FROM (
         VALUES ((NULL::A).*), (row_1), (row_2), ...
         ) B
      OFFSET 1;
      插入到--完整的行中
      从中选择*(
      值((NULL::A)。*),(第1行),(第2行)。。。
      )B
      偏移量1
      
      {col_list}
      在这种特殊情况下是可选的噪声,因为我们无论如何都需要提供完整的行

      详细说明:


      你好,卢卡斯,看起来不错。但是有了这个json函数,我不知道如何一次插入多行而不重复每行的列名。@Ben我已经更新了答案,将在一次调用中生成行集的函数包括在内:
      json\u populate\u recordset(…)
      谢谢,但是这些重复的列名似乎是多余的,在我的例子中,这些表有十几列,每列都有许多空值。开销似乎有点高。嗨,卢卡斯,看起来不错。但是有了这个json函数,我不知道如何一次插入多行而不重复每行的列名。@Ben我已经更新了答案,将在一次调用中生成行集的函数包括在内:
      json\u populate\u recordset(…)
      谢谢,但是这些重复的列名似乎是多余的,在我的例子中,这些表有十几列,每列都有许多空值。开销似乎有点高。您真的需要
      选择
      ?在您给出的示例中,
      插入(…)值…
      就足够了。我认为Postgres在没有查询的情况下对未知参数类型不那么挑剔。你真的需要
      选择
      ?在您给出的示例中,
      插入(…)值…
      就足够了。我认为在没有查询的情况下,Postgres对未知参数类型不那么挑剔。谢谢你的技术。我没有用CTE。但是这种行类型转换看起来非常有用。我希望早点知道。谢谢你的技术指导