【问题标题】:Possible to use pandas/sqlalchemy to insert arrays into sql database? (postgres)可以使用 pandas/sqlalchemy 将数组插入 sql 数据库吗? (postgres)
【发布时间】:2021-10-18 17:17:26
【问题描述】:

以下内容:

engine = sqlalchemy.create_engine(url)

df = pd.DataFrame({
    "eid": [1,2],
    "f_i": [123, 1231],
    "f_i_arr": [[123], [0]],
    "f_53": ["2013/12/1","2013/12/1",],
    "f_53a": [["2013/12/1"], ["2013/12/1"],],
})

with engine.connect() as con:
    con.execute("""
        DROP TABLE IF EXISTS public.test;
        CREATE TABLE public.test
        (
          eid integer NOT NULL,
          f_i INTEGER NULL,
          f_i_arr INTEGER NULL,
          f_53 DATE NULL,
          f_53a DATE[] NULL,
           PRIMARY KEY(eid)
        );;
        """)
    df.to_sql("test", con, if_exists='append')

如果我尝试仅插入列“f_53”(date),它会成功。

如果我尝试添加列“f_53a”(date[]),则会失败:

                                            ^
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) column "f_53a" is of type date[] but expression is of type text[]
LINE 1: ..._53, f_53a, f_i, f_i_arr) VALUES (1, '2013/12/1', ARRAY['201...
                                                             ^
HINT:  You will need to rewrite or cast the expression.
 [SQL: 'INSERT INTO test (eid, f_53, f_53a, f_i, f_i_arr) VALUES (%(eid)s, %(f_53)s, %(f_53a)s, %(f_i)s, %(f_i_arr)s)'] [parameters: ({'f_53': '2013/12/1', 'f_53a': ['2013/12/1', '2013/12/1'], 'f_i_arr': [123], 'eid': 1, 'f_i': 123}, {'f_53': '2013/12/1', 'f_53a': ['2013/12/1', '2013/12/1'], 'f_i_arr': [0], 'eid': 2, 'f_i': 1231})]

【问题讨论】:

  • 错误消息的第一行表明表达式 - ["2008-03-08",] - 是 text[] 类型。可能是 Pandas 没有像 f_53 那样自动转换它。您是否尝试过使用pd.to_datetime() 手动投射它? pandas.pydata.org/pandas-docs/stable/generated/…
  • 如果我将所有日期类型更改为 int 并将字符串值更改为整数,则错误是相同的。在这种情况下,pandas 有一列 dtype=object 保存一个整数列表。似乎它不是特定于日期,而是特定于数组。
  • 确认——编辑中的架构错误。你是对的 pd.to_datetime-ing 日期修复了这个并且日期和日期 [] 正在插入正确lt
  • 太棒了 - 你能写下你是如何修复它的,这样其他人就可以看到是什么解决了它? :)

标签: postgresql pandas sqlalchemy


【解决方案1】:

我已经明确提到了dtypes,它对我来说适用于 postgres。

//sample code

import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.dialects import postgresql
 df.to_sql('mytable',pgConn, if_exists='append', index=False,  dtype={'datetime': sqlalchemy.TIMESTAMP(), 'cur_c':postgresql.ARRAY(sqlalchemy.types.REAL),
        'volt_c':postgresql.ARRAY(sqlalchemy.types.REAL)
        })

【讨论】:

    【解决方案2】:

    是的 -- 可以将 [][][] 类型从数据帧插入到 postgres 形成数据帧。

    与平面 DATE 类型不同,可以被 sql 正确解析,DATE[]DATE[][] 需要先转换为 datetime 对象。像这样。

    with engine.connect() as con:
        con.execute("""
            DROP TABLE IF EXISTS public.test;
            CREATE TABLE public.test
            (
              eid integer NOT NULL,
              f_i INTEGER NULL,
              f_ia INTEGER[] NULL,
              f_iaa INTEGER[][] NULL,
              f_d DATE NULL,
              f_da DATE[] NULL,
              f_daa DATE[][] NULL,
              PRIMARY KEY(eid)
            );
            """)
    
    
        d = pd.to_datetime("2013/12/1")
        i = 99
        df = pd.DataFrame({
            "eid": [1,2],
    
            "f_i": [i,i],
            "f_ia": [None, [i,i]],
            "f_iaa": [[[i,i],[i,i]], None],
    
            "f_d": [d,d],
            "f_da": [[d,d],None],
            "f_daa": [[[d,d],[d,d]],None],
        })
        df.to_sql("test", con, if_exists='append', index=None)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-04
      • 1970-01-01
      • 1970-01-01
      • 2020-11-07
      • 2018-09-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多