SQLAlchemy的,Psycopg2和PostgreSQL COPY(SQLAlchemy, P

2019-07-03 10:27发布

它看起来像Psycopg具有用于执行自定义命令COPY :

使用cursor.copy_from()psycopg2 COPY较大输入冻结

有没有从SQLAlchemy的访问此功能的方法吗?

Answer 1:

它看起来并不像它 。

您可能只使用psycopg2揭露此功能,并放弃了ORM功能。 我想我真的不明白ORM的好处在这样的操作呢,因为它是一个直BULK INSERT和处理单个对象一拉一个ORM不会真的做了一大堆的道理。



Answer 2:

接受的答案是正确的,但如果你想不仅仅是EoghanM的评论多了去了,在接下来的在复制一个表出来,以CSV为我工作...

from sqlalchemy import sessionmaker, create_engine

eng = create_engine("postgresql://user:pwd@host:5432/db")
ses = sessionmaker(bind=engine)

dbcopy_f = open('/tmp/some_table_copy.csv','wb')

copy_sql = 'COPY some_table TO STDOUT WITH CSV HEADER'

fake_conn = eng.raw_connection()
fake_cur = fake_conn.cursor()
fake_cur.copy_expert(copy_sql, dbcopy_f)

sessionmaker是没有必要的,但如果你在同一时间创造的发动机和会话的习惯是使用raw_connection你需要将它们分开(除非有某种方式,通过会话对象访问引擎,我不知道)。 提供的SQL字符串copy_expert也没有给它的唯一的方式,有一个基本的copy_to ,您可以使用,你可以过去的正常参数的子集使用功能COPY TO查询。 该命令的整体表现似乎快给我,抄写〜20000行的表。

http://initd.org/psycopg/docs/cursor.html#cursor.copy_to http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.Engine.raw_connection



Answer 3:

如果您的发动机配置了psycopg2连接字符串(这是默认的,所以无论是"postgresql://...""postgresql+psycopg2://..." ),你可以创建一个psycopg2光标从SQL使用炼金术会议

cursor = session.connection().connection.cursor()

你可以用它来执行

cursor.copy_from(...)

光标将活跃在相同的事务中会话目前是。 如果commitrollback发生时,任何进一步的使用光标抛出的psycopg2.InterfaceError ,你必须创建一个新的。



Answer 4:

您可以使用:

def to_sql(engine, df, table, if_exists='fail', sep='\t', encoding='utf8'):
    # Create Table
    df[:0].to_sql(table, engine, if_exists=if_exists)

    # Prepare data
    output = cStringIO.StringIO()
    df.to_csv(output, sep=sep, header=False, encoding=encoding)
    output.seek(0)

    # Insert data
    connection = engine.raw_connection()
    cursor = connection.cursor()
    cursor.copy_from(output, table, sep=sep, null='')
    connection.commit()
    cursor.close()

我插入200000线在5秒内,而不是在4分钟



Answer 5:

你并不需要下降到psycopg2,使用raw_connection也不光标。

刚刚执行的SQL像往常一样,你甚至可以使用带有绑定参数text()

engine.execute(text('''copy some_table from :csv
                       delimiter ',' csv'''
                   ).execution_options(autocommit=True),
               csv='/tmp/a.csv')

您可以删除execution_options(autocommit=True)如果这个PR将被接受



Answer 6:

如果你能得到的引擎,你拥有所有你需要做的是:

engine = create_engine('postgresql+psycopg2://myuser:password@localhost/mydb')
# or 
engine = session.engine
# or any other way you know to get to the engine

现在,你可以工作。

# isolate a connection
connection = engine.connect().connection

# get the cursor
cursor = connection.cursor()

这里有一些模板的COPY语句来使用cursor.copy_expert()比一个更完整,更灵活的选择copy_from()copy_to()因为它是在此间表示: http://initd.org/psycopg/docs/cursor的.html#cursor.copy_expert 。

# to dump to a file
dump_to = """
COPY mytable 
TO STDOUT
WITH (
    FORMAT CSV,
    DELIMITER ',',
    HEADER
);
"""

# to copy from a file:
copy_from = """
COPY mytable 
FROM STDIN
WITH (
    FORMAT CSV,
    DELIMITER ',',
    HEADER
);
"""

查看一下上述选项的含义和其他可能会感兴趣的您的具体情况https://www.postgresql.org/docs/current/static/sql-copy.html 。

重要说明:链接的文档cursor.copy_expert()指示要使用STDOUT写出来到一个文件,STDIN从文件复制。 但是,如果你看一下在PostgreSQL的手册中的语法,你会发现,你还可以指定写入或直接在COPY语句文件。 不这样做,你可能只是浪费你的时间,如果你不是root运行(谁在开发过程中运行Python作为根?)只是做什么在psycopg2的文档显示,并与您的语句中指定STDIN或STDOUT cursor.copy_expert()它应该是罚款。

# running the copy statement
with open('/path/to/your/data/file.csv') as f:
     cursor.copy_expert(copy_from, file=f)

# don't forget to commit the changes.
connection.commit()


文章来源: SQLAlchemy, Psycopg2 and Postgresql COPY