【问题标题】:Postgres how to insert python dictionary from csv file?Postgres如何从csv文件插入python字典?
【发布时间】:2021-12-24 04:23:41
【问题描述】:

我有一个 csv events.csv:

"PATIENT ID,PATIENT NAME,EVENT TYPE,EVENT VALUE,EVENT UNIT,EVENT TIME"
"1,Jane,HR,82,beats/minute,2021-07-07T02:27:00Z"
"1,Jane,RR,5,breaths/minute,2021-07-07T02:27:00Z"

然后我用python csv读取它:

import csv
with open(r'/Users/williaml/Downloads/events.csv') as csvfile: 
    spamreader = csv.DictReader(csvfile, delimiter=',' ,quotechar=' ')
    for row in spamreader:            
        print(row)

输出:

{'"PATIENT ID': '"1', 'PATIENT NAME': 'Jane', 'EVENT TYPE': 'HR', 'EVENT VALUE': '82', 'EVENT UNIT': 'beats/minute', 'EVENT TIME"': '2021-07-07T02:27:00Z"'}

{'"PATIENT ID': '"1', 'PATIENT NAME': 'Jane', 'EVENT TYPE': 'RR', 'EVENT VALUE': '5', 'EVENT UNIT': 'breaths/minute', 'EVENT TIME"': '2021-07-07T02:27:00Z"'}

我尝试将这些行插入数据库:

import psycopg2
conn = psycopg2.connect(host='localhost', dbname='patientdb',user='username',password='password',port='')
cur = conn.cursor()
import csv
with open(r'apps/patients/management/commands/events.csv') as csvfile:
        spamreader = csv.DictReader(csvfile, delimiter=',' ,quotechar=' ')
        for row in spamreader:
                cur.execute(f"""INSERT INTO patients_event (patient_id, event_type_id , event_value ,event_unit, event_time) VALUES
  ({row['"PATIENT ID']},{row['EVENT TYPE']},{row['EVENT VALUE']},
   {row['EVENT UNIT']},{row['EVENT TIME"']})""")

错误:

psycopg2.errors.UndefinedColumn: column "1,HR,82,
   beats/minute,2021-07-07T02:27:00Z" does not exist
LINE 2:   ("1,HR,82,
           ^

但是,如果我直接在数据库命令终端中运行以下 sql,它就可以工作:

INSERT INTO patients_event (patient_id, event_type_id , event_value ,event_unit, event_time) VALUES('1','HR','82','beats/minute','2021-07-07T02:27:00Z');

所以我认为这部分代码似乎不正确:

cur.execute(f"""INSERT INTO patients_event (patient_id, event_type_id , event_value ,event_unit, event_time) VALUES
      ({row['"PATIENT ID']},{row['EVENT TYPE']},{row['EVENT VALUE']},
       {row['EVENT UNIT']},{row['EVENT TIME"']})""")

有朋友可以帮忙吗?

【问题讨论】:

  • 您能在{'"PATIENT ID': '"1', 中看到任何内容吗?这可能是造成这种情况的原因。这是来自您正在写入数据库的上述输出。
  • 为什么不使用COPY
  • @balderman 并非每一列都需要。例如,不需要患者姓名,我还能使用复制吗?
  • @William 我认为 COPY 知道如何处理这种情况。
  • CSV 文件是否真的在每一行的开头和结尾都有双引号,而其他地方没有?这将使每一行成为一个字段,这似乎非常可疑。如果可能的话,这应该在上游修复。一旦你解决了这个问题,请使用proper parameter passing 而不是字符串格式将值传递给 SQL 查询。

标签: python sql database postgresql


【解决方案1】:

使用这个:

cur.execute("""INSERT INTO patients_event (patient_id, event_type_id , event_value ,event_unit, event_time) VALUES ({1},{2},{3},{4},{5})"""
            .format(row['"PATIENT ID'][1:], row['EVENT TYPE'], row['EVENT VALUE'], row['EVENT UNIT'], row['EVENT TIME"'][:-1]))

所以,这基本上处理了我在comment 中提到的输出字典中的额外引号,这导致了这个问题。

这就是为什么

INSERT INTO patients_event (patient_id, event_type_id , event_value ,event_unit, event_time) VALUES('1','HR','82','beats/minute','2021-07-07T02:27:00Z');

通过 db 终端,您可以看到以两种方式插入此处的值之间的差异。

更新:避免使用 python 的字符串格式进行查询,因为它可能导致错误的查询或 sql 注入的漏洞点。请参阅 parameters 以了解正确的方法,正如 Adrian 在下面的 cmets 中提到的那样。

【讨论】:

  • 感谢您的回答,使用您的代码后,错误变为:psycopg2.errors.SyntaxError: syntax error at or near "T02" LINE 3: beats/minute,2021-07-07T02 :27:00Z)
  • 不要使用格式化字符串来执行此操作。阅读这部分文档Parameters 以了解正确的方法。这不应该是一个公认的答案,因为它会促进糟糕的编码。
  • @AdrianKlaver psycopg 没有明确提到应该避免对查询使用字符串格式。此外,他们在您提到的reference 的最后一个代码块中使用了.format
  • 也就是psycopg2.sql提供的format,是关闭sql.SQL()的方法。这是另一回事,特别是因为它确实正确转义。 f strings 只是字符串插值的一种形式,不适合构建 SQL 查询。
  • 好吧,我的错!但是,我认为问题更多的是关于 OP 哪里错了,以及他认为的解决方案是什么。我相应地回答了。我会更新我的答案。
【解决方案2】:

所以 CSV 的一个问题是 " 在每一行的开头和结尾。您解释它的方式导致它成为 SQL 表达式的一部分。

           here 
LINE 2:   ("1,HR,82

这会导致错误,因为它没有正确关闭",实际上它并不打算出现在生成的 SQL 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 2021-03-25
    相关资源
    最近更新 更多