【问题标题】:Pandas to_sql - append vs replacePandas to_sql - 追加与替换
【发布时间】:2021-01-07 13:41:07
【问题描述】:

我正在尝试了解如何根据我的需要修改 to_sql 函数。这是df_interface的数据框:

| YEAR | QUARTER | USER_ACCOUNT | BYTES         | USER_CODE |
|------|---------|--------------|---------------|-----------|
| 2020 | 2       | SHtte34      | 7392577516389 | 2320885   |
| 2020 | 2       | Exel2        | 441712306685  | 348995    |

我正在尝试将其插入表 USER_USAGE(通过 oracle+cx 和 SQLAlchemy)。该表在插入前的内容为:

| YEAR | QUARTER | USER_ACCOUNT | BYTES         | USER_CODE |
|------|---------|--------------|---------------|-----------|
| 2020 | 1       | SHtte34      | 34560         | 2320885   |
| 2020 | 1       | Exel2        | 5478290       | 348995    |

我希望仅在新季度 AND 帐户的情况下插入新行。基本上我想在插入后这样:

| YEAR | QUARTER | USER_ACCOUNT | BYTES         | USER_CODE |
|------|---------|--------------|---------------|-----------|
| 2020 | 1       | SHtte34      | 7392577516389 | 2320885   |
| 2020 | 1       | Exel2        | 5478290       | 348995    |
| 2020 | 2       | SHtte34      | 7392577516389 | 2320885   |
| 2020 | 2       | Exel2        | 441712306685  | 348995    |

这是带有“替换”的代码:

conn = create_engine('oracle+cx_oracle://{}:{}@{}/?service_name={}'.format(s_uid,s_pwd,s_db,s_service))

df_interface.to_sql('USER_USAGE', conn, if_exists='replace',dtype={'USER_ACCOUNT': types.String(df_interface.USER_ACCOUNT.str.len().max()),'USER_CODE': types.String(df_interface.USER_CODE.str.len().max())},index=False)

这似乎也删除了上一季度 (1) 的值。替换后的输出:

 | YEAR | QUARTER | USER_ACCOUNT | BYTES         | USER_CODE |
|------|---------|--------------|---------------|-----------|
| 2020 | 2       | SHtte34      | 7392577516389 | 2320885   |
| 2020 | 2       | Exel2        | 441712306685  | 348995    |

Append 更接近我想要看到的,但是如果我不小心运行了两次程序,我会看到重复的行:

| YEAR | QUARTER | USER_ACCOUNT | BYTES         | USER_CODE |
|------|---------|--------------|---------------|-----------|
| 2020 | 1       | SHtte34      | 7392577516389 | 2320885   |
| 2020 | 1       | Exel2        | 5478290       | 348995    |
| 2020 | 2       | SHtte34      | 7392577516389 | 2320885   |
| 2020 | 2       | Exel2        | 441712306685  | 348995    |
| 2020 | 1       | SHtte34      | 7392577516389 | 2320885   |
| 2020 | 1       | Exel2        | 5478290       | 348995    |
| 2020 | 2       | SHtte34      | 7392577516389 | 2320885   |
| 2020 | 2       | Exel2        | 441712306685  | 348995    |

如何使用“追加”,同时防止在无意运行时创建重复项?

【问题讨论】:

    标签: python pandas oracle sqlalchemy


    【解决方案1】:

    if_exists 参数指的是整个表,而不是表中的单个行。 if_exists="replace" 表示“如果表存在则删除它并使用 DataFrame 中的行创建一个新表,而 if_exists="append" 表示“将 DataFrame 行附加到现有表中”。

    如果您可能只想在现有表中插入一些(或不)行,那么您不能使用to_sql 直接插入它们。相反,您可以:

    • 创建一个与主USER_USAGE 表结构相同的临时表(例如USER_USAGE_TEMP)。

    • 使用to_sql 将DataFrame 上传到临时表(使用if_exists="append")。

    • 执行 INSERT 语句,如

    INSERT INTO USER_USAGE (YEAR, QUARTER, USER_ACCOUNT, BYTES, USER_CODE)
    SELECT YEAR, QUARTER, USER_ACCOUNT, BYTES, USER_CODE FROM USER_USAGE_TEMP
    WHERE NOT EXISTS (
        SELECT * FROM USER_USAGE UU
        WHERE UU.YEAR = USER_USAGE_TEMP.YEAR AND UU.QUARTER = USER_USAGE_TEMP.QUARTER
        )
    

    【讨论】:

    • 谢谢。使用 SQLAlchemy/Oracle+cx 仅插入一些行(根据上述要求)的其他方法是什么?
    • 您可以使用like this 方法,除了使用INSERT … WHERE NOT EXISTS … 而不是UPDATE 语句。
    • @Shallunsard 如果您真的需要使用 to_sql(),您可以使用具有触发器的表,该触发器会在另一个表中为您执行插入操作。不要指望这很容易、快速或便携。但如果你曾经需要这样的 hack,我想这是唯一的选择。
    • 我对不需要 to_sql 的选项持开放态度,实际上只是在 SQLAlchemy/Oraclecx/PyODBC 模块中寻找最轻松的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2015-01-02
    • 2017-05-24
    • 2019-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多