【问题标题】:How to upload "empty" attributes to PostgreSQL database with python?如何使用 python 将“空”属性上传到 PostgreSQL 数据库?
【发布时间】:2020-10-20 18:00:06
【问题描述】:

我有一个如下所示的 .dat 文件:

1*100*100*
2*100*200*
3*100*100*
4**100*
5*100*200*
6***
7*100**
8*150*100*

我想将此文件的内容上传到 PostgreSQL 数据库,如下所示:

id   | attr1 | attr2
--------------------
int  | int   | int

如果原始文件中没有“空”记录,则使用以下 pyhton 脚本一切正常。但是当有一个时,它会给我一条错误消息。

请注意,原始文件的结构始终保持不变。无论 emtpy 属性如何,分隔符(本例中为 *)的数量始终相同。

我使用了以下代码,正如我所提到的,当没有空属性时它可以正常工作。

import csv
import psycopg2

try:
    connection = psycopg2.connect(user = 'myuser', host = 'localhost',
    port = "5432", database = 'mydatabase')
    cursor = connection.cursor()

    with open('c:\\some_dir\\my_filedat','r') as f:
        for row in csv.reader(f,delimiter='*'):
            query = '''
            insert into my_schema.my_table (id, attr1, attr2)
            values ({},{},{});
            '''.format(row[0],row[1],row[2])
            cursor.execute(query)
            connection.commit()

except(Exception, psycopg2.Error) as error:
    print("Error while connecting to PostgreSQL", error)

finally: 
    if(connection):
        cursor.close()
        connection.close()
        print("PostgreSQL connection is closed")

我收到的错误信息: 连接到 PostgreSQL 语法错误时在“,”或附近出错 第 4 行:值 (4,,100);

现在我知道我可以在每次迭代中调查每个属性的值,如果它是 '',那么我可以为它分配 '0',但实际上至少有 20 个属性和数十万行,其中会非常耗时且效率低下。

我还可以将 .dat 文件转换为 .csv 并使用 ogr2ogr 上传,但最后我只需要文件的某些部分,我打算在 python 中过滤这些部分。

【问题讨论】:

    标签: python postgresql csv psycopg2


    【解决方案1】:

    没有办法。您需要确保如果在数据文件中遇到空白值,则替换为null,以便生成的值列表看起来像values (4,null,100) 而不是values (4,,100)

    所以,我猜你会做类似的事情

    . . .
    '''.format(row[0] or "null", row[1] or "null", row[2] or "null")
    . . .
    

    【讨论】:

    • 谢谢!它可以正常工作,但前提是列的类型是字符变化
    • 使用字符串格式将变量传递给 SQL 查询容易出错,并可能导致 SQL 注入。
    【解决方案2】:

    我找到了一个不太好但可行的解决方案。如果我将 PostgreSQL 中的列类型更改为字符变化,我可以使用以下修改。我把 {}-s 放在撇号之间。上传后,我可以将列转换为整数。不是很方便,但它正在工作。

    query = '''
    insert into my_schema.my_table (id, attr1, attr2)
    values ('{}','{}','{}');
    '''.format(row[0],row[1],row[2])
    

    【讨论】:

    • 使用字符串格式将变量传递给 SQL 查询容易出错,并可能导致 SQL 注入。 – Ilja Everilä 刚刚
    【解决方案3】:

    这是错误的方法。使用绑定值而不是 Python 字符串格式。

    代替

    query = '''
    insert into my_schema.my_table (id, attr1, attr2)
    values ({},{},{});
    '''.format(row[0],row[1],row[2])
    cursor.execute(query)
    

    试试这个

    query = '''
    insert into my_schema.my_table (id, attr1, attr2)
    values (%s, %s, %s)
    '''
    cursor.execute(query, (int(row[0]), int(row[1]), int(row[2])))
    

    【讨论】:

    • @588chm 顺便说一句 - 您的原始代码存在 SQL 注入的风险。尽可能使用绑定值。如果不能绑定变量,必须格式化成动态查询,那么请确保连接数据库的角色遵循最小权限原则。
    猜你喜欢
    • 2014-05-24
    • 2012-11-19
    • 2022-11-06
    • 2017-04-25
    • 2017-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    相关资源
    最近更新 更多