在附加到数据库之前循环遍历数据框并检查行

Looping trough dataframe and checking rows before appending to database

问题如何将我的数据框附加到数据库,以便它检查 stock_ticker 是否存在,只附加 stock_ticker 不存在的行?

这是我做的过程

  1. 将 CSV 文件导入 pandas 数据框
  2. 指定与数据库中相同的列名
  3. 使用下面的代码将数据帧发送到数据库但得到

sqlite3.IntegrityError: UNIQUE constraint failed: stocks.stock_ticker

conn = sqlite3.connect('stockmarket.db')
c = conn.cursor()

df.to_sql(name='stocks', con=conn, if_exists='append', index=False)

conn.commit()

我查看了其他完整性错误案例,但似乎找不到适用于附加数据帧的案例?我发现并尝试了这个,但它所做的只是不附加任何内容。

try:
    conn = sqlite3.connect('stockmarket.db')
    c = conn.cursor()
    df.to_sql(name='stocks', con=conn, if_exists='append', index=False)
    conn.commit()
except sqlite3.IntegrityError:
    print("Already in database")

我不确定我是否正确理解迭代的东西

How to iterate over rows in a DataFrame in Pandas

所以我尝试了这个,但它只是在数据库中为每个人打印了出来。即使艰难,也有 4 个新的股票代码。

for index, row in df.iterrows():
    try:
        conn = sqlite3.connect('stockmarket.db')
        c = conn.cursor()
        df.to_sql(name='stocks', con=conn, if_exists='append', index=False)
        conn.commit()
    except sqlite3.IntegrityError:
        print("Already in database")

数据库看起来像这样

非常感谢任何见解:)

看起来发生这种情况是因为 Pandas 不允许声明适当的 ON CONFLICT 策略,以防您尝试将数据附加到具有相同 ( unique) primary key 或违反其他一些 UNIQUEness 约束。 if_exists 仅指整个 table 本身,而不是每一行。

我想你已经想出了一个很好的答案,也许稍加修改就可以了:

# After connecting
for i in range(len(df)):
    try:
        df[df.index == i].to_sql(name='stocks', con=conn, if_exists='append', index=False)
        conn.commit()
    except sqlite3.IntegrityError:
        pass

现在,如果您的 Pandas 数据中出现了一个较新的值,并且您想要替换数据库中的旧值,那么这可能是一个问题。在这种情况下,您可能希望将原始 SQL 命令用作字符串,并迭代传递 Pandas 值。例如:

insert_statement = """
INSERT INTO stocks (stock_id,
                    stock_ticker,
                    {other columns})
VALUES (%s, %s, {as many %s as columns})
ON CONFLICT (stock_id) DO UPDATE
    SET {Define which values you will update on conflict}"""

然后你可以运行

for i in range(len(df)):
    values = tuple(df.iloc[i])
    cursor.execute(insert_statement, values)