Django:RunSQL:使用 PostgreSQL COPY 命令

Posted

技术标签:

【中文标题】Django:RunSQL:使用 PostgreSQL COPY 命令【英文标题】:Django: RunSQL: use PostgreSQL COPY command 【发布时间】:2015-10-30 18:42:04 【问题描述】:

我尝试使用以下RunSQL 命令运行迁移:

class Migration(migrations.Migration):
    operations = [
        RunSQL(
r'''
COPY auth_group (id, name) FROM stdin;
1   TEST-GROUP
\.
''')]

这样失败:

File "/home/foo/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 63, in execute
     return self.cursor.execute(sql)
django.db.utils.ProgrammingError: syntax error at or near "1"
LINE 3: 1 TEST-GROUP

RunSQL 中是否不允许有 COPY

我们使用 psycopg2

【问题讨论】:

这肯定不是标准输入,是吗?为什么不使用 INSERT 语句? @DanielRoseman 它适用于psql -f myfile.sql。这两种用法看起来都非常类似于新手。 【参考方案1】:

psycopg2 驱动程序公开了copy_tocopy_from 方法,可用于实现与psql 客户端相同的行为;关键是使用RunPython 操作而不是RunSQL 操作。

你需要:

迁移中用于打开文件并与复制方法交互的函数 迁移的 operations 列表中的 RunPython 操作以调用函数

例如,使用 Django 1.8.4、Python 2.7.10、psycopg2 2.6.1 -

from django.db import models, migrations

def forwards(apps, schema_editor):
    with open('./path/to/file.csv', 'r') as infile:
        with schema_editor.connection.cursor() as stmt:
            #for finer control, use copy_expert instead
            stmt.copy_from(infile, 'your_table', sep=',')

class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        #this runs your function
        migrations.RunPython(forwards)
    ]

一些注意事项:

传递给copyfile 对象在语句中本质上是STDIN。 复制命令可能对列很挑剔;使用copy_expert,您可以控制与命令相同的所有选项:格式、标题、分隔符等。

有关copy_* 方法的更多信息,请查看 psycopg2 文档:http://initd.org/psycopg/docs/cursor.html

【讨论】:

谢谢。方法copy_from() 解决了copy 的一个语句。不幸的是,我的转储文件中有几个复制语句。但我可以把它切成N块。 啊,我没有建立这种联系。我想您确实有几个不同的选项 - 1) 剪切文件(小心解析出 SQL 语句),2) 重新审视数据的生成方式,或者 3) 通过process.popen 生成 psql 命令。 #3 更脆弱,具体取决于命令将在何处运行。对于 #2,您可以直接使用 copy_to 方法获取您感兴趣的数据的 .csv,并在每个转储中省略 SQL 语句。

以上是关于Django:RunSQL:使用 PostgreSQL COPY 命令的主要内容,如果未能解决你的问题,请参考以下文章

使用 Django 从 Postgres 导出 JSON 时结果不一致

Postgres:使用 django 对 json 键进行值查询

如何在 Django 中管理 Postgres 枚举类型?

在 Docker 上使用 Nginx、uWSGI 和 Postgres 配置 Django

DoCmd.RunSQL 中的 VBA 变量

在较旧的 Postgres (9.4) 上使用 Django 3+