SQLAlchemy,Psycopg2和Postgresql COPY

时间:2012-10-29 16:01:53

标签: postgresql sqlalchemy psycopg2

看起来Psycopg有一个用于执行COPY的自定义命令:

psycopg2 COPY using cursor.copy_from() freezes with large inputs

有没有办法从SQLAlchemy访问此功能?

6 个答案:

答案 0 :(得分:30)

接受的答案是正确的但是如果你想要的不仅仅是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,则需要将它们分开(除非有一些通过我不知道的会话对象访问引擎的方法。提供给copy_expert的sql字符串也不是唯一的方法,有一个基本的copy_to函数,您可以使用参数的子集,可以将其传递给正常COPY要查询。对我来说,命令的整体性能似乎很快,复制出约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

答案 1 :(得分:15)

如果您的引擎配置了psycopg2连接字符串(默认值为"postgresql://...""postgresql+psycopg2://..."),则可以使用

从SQL Alchemy会话创建psycopg2游标
cursor = session.connection().connection.cursor()

可用于执行

cursor.copy_from(...)

光标将在与您当前会话相同的事务中处于活动状态。如果发生commitrollback,则抛出psycopg2.InterfaceError光标的任何进一步使用,您将不得不创建一个新的。

答案 2 :(得分:10)

It doesn't look like it

您可能只需使用psycopg2来公开此功能并放弃ORM功能。我想我在这样的操作中并没有真正看到ORM的好处,因为它是一个直接的批量插入并处理单个对象,而ORM实际上并没有太多意义。

答案 3 :(得分:7)

您可以使用:

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()

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

答案 4 :(得分:4)

您不需要下拉到psycopg2,使用raw_connection或游标。

像往常一样执行sql,你甚至可以使用text()的绑定参数:

execution_options(autocommit=True)

如果this PR将被接受,您可以放弃var columns = []; $.each(actions, function (idx, action) { actionColumn = { template: '#if (selfActions[i].name === "' + action.name + '"){ # <input type="checkbox" /> some text # } # ' } columns.push(actionColumn); }); $("#myId").kendoTreeList({ //... columns: columns });

答案 5 :(得分:2)

如果你可以使用引擎,你就拥有了所需的一切:

...
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  imports: [
    BrowserModule,
    // Include it under 'imports' in your application module after BrowserModule.
    HttpClientModule,
    ...
  ],
  ...

现在你可以工作了。

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()更完整,更灵活的选项,如下所示:http://initd.org/psycopg/docs/cursor.html#cursor.copy_expert

copy_to()

查看上述选项的含义以及您特定情况可能感兴趣的其他选项https://www.postgresql.org/docs/current/static/sql-copy.html

重要说明:# 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 ); """ 文档的链接表示使用STDOUT写入文件,使用STDIN从文件复制。但是如果你看一下PostgreSQL手册上的语法,你会注意到你也可以直接在COPY语句中指定要写入或写入的文件。不要这样做,如果你不是以root身份运行(在开发期间以root身份运行Python,那么你可能只是浪费时间?)只需执行psycopg2文档中指示的内容并在语句中指定STDIN或STDOUT { {1}},应该没问题。

cursor.copy_expert()