在 python 和 SQL 中将数据从 pandas 数据帧有条件地插入到 HANA 表

Conditional inserting of data from pandas data frame to HANA table in python and SQL

提问人:Lyla 提问时间:11/17/2023 最后编辑:Sandra RossiLyla 更新时间:11/17/2023 访问量:29

问:

不幸的是,我无法找到解决方案,这就是为什么我希望你能帮助我。

鉴于:

我在HANA中有一个名为的表。 它如下所示:( = 主键)Table_1ID

编号 COL1型 名字 COL2型
1 someValue 一个 someValue
2 someValue B someValue

我有一个 CSV 文件,其中包含未知数量的列和未知的列名称。我唯一知道的是,每个 CSV 文件都包含一个名为 和 的列。X_IDX_NAME

我将此 CSV 文件读取到名为 .df

Df如下所示:

X_ID X_NAME COL3型 COL4型 山坳。。。
1 一个 someXValue someXValue ...
2 B someXValue someXValue
3 C someXValue someXValue

以下内容适用于 和 :Table_1df

ID = X_ID and NAME = X_NAME

现在我想包括 to 的数据。dfTable_1

我尝试了合并、插入和更新插入,但不幸的是我无法获得正常运行的命令。

如果 已包含在 中,则只有 中的新列应追加到相应的行中。X_IDIDTable_1df

如果不在,则应应用以下内容: ; 和 from 应为 null;并且应包括 中的所有附加列及其值。X_IDIDID = X_ID, NAME = X_NAMECOL1COL2Table_1df

解决方案应如下所示:

Table_1:

编号 COL1型 名字 COL2型 COL3型 COL4型 山坳。。。
1 someValue 一个 someValue someXValue someXValue ...
2 someValue B someValue someXValue someXValue
3 C someXValue someXValue

我已经尝试过的:

我目前的代码:

#!/usr/bin/python3

import pandas as pd
import argparse
from hdbcli import dbapi

parser = argparse.ArgumentParser(
                    prog='ABC',
                    description='XYZ')

parser.add_argument('input_filepath')
args = parser.parse_args()

df = pd.read_csv(args.input_filepath,sep=',')

conn = dbapi.connect(address='ADDRESS', port=PORT, user='USER', password='PSW')

target_table = 'TABLE_NAME'

sql_insert_template = f"""
ALTER TABLE {target_table}
    ADD ({', '.join([f'{col} VARCHAR(200)' for col in df.columns if col != 'X_ID' and col != 'X_NAME'])});

# TODO: SQL Code for data inserting (at the bottom)
"""

try:
    with conn.cursor() as cursor:
        cursor.execute(sql_insert_template)

    conn.commit()

    print("Record inserted successfully")
finally:
    conn.close()

我尝试以下SQL代码来插入数据:

MERGE INTO {target_table} AS target
USING (
    SELECT
        {', '.join(df.columns)}
    FROM {df}
) AS source
ON (target.ID = source.X_ID)

WHEN MATCHED THEN
    UPDATE {target_table} 
        SET {', '.join([f'target.{col} = source.{col}' for col in df.columns if col != 'X_ID' and col != 'X_NAME'])}

WHEN NOT MATCHED THEN
    INSERT INTO  {target_table}(
        ID, NAME, {', '.join(f'{col}' for col in df.columns if col != 'X_ID' and col != 'X_NAME')}
    ) VALUES (
        {', '.join([f'source.X_ID, source.X_NAME, source.{col}' for col in df.columns if col != 'X_ID' and col != 'X_NAME'])}
    );

在此命令中,存在多个错误。第一个是我无法在 Merge 附近解决的语法错误,第二个是从 .因为现在在部分 “” 中,不是值,而是列名作为值包含在内,并且对行、列和值的迭代是错误的。所以现在只包含“一行”(一行,但有列名而不是值)。但是我想将所有行、值都包含在一个 SQL 命令中。dfWHEN NOT MATCHED THAN ... VALUES()dfdf

我真的不知道如何解决以正确的方式包含所有值的问题。

我尝试的第二种方法是使用 UPSET,但仍然存在包含值的问题。还有一个额外的当前问题,我需要知道有多少列,以便我可以设置“null”值。table_1

UPSERT {target_table}
VALUES({', '.join(f'{col}' for col in df.columns if col == 'X_ID')}, null, {', '.join(f'{col}' for col in df.columns if col == 'X_NAME')}, null, {', '.join(f'{col}' for col in df.columns if col != 'X_ID' and col != 'X_NAME')})
#WITH PRIMARY KEY; 
蟒蛇 SQL HANA

评论


答:

0赞 Mathias Kemeter 11/17/2023 #1

在使用 Pandas Dataframes 和 SAP HANA 时,我建议查看 hana-ml Python 包。它建立在 Pandas 的基础上,并显著改进了与 Pandas 的集成。查看 HANA 数据帧,特别是create_dataframe_from_pandas保存的方法hdbcli

但是,这还不是解决您最初问题的方法。您选择的数据模型似乎并不完全适合您的用例。如果每个新表确实都带有任意属性,则最终将在 HANA 上得到一个非常宽且稀疏的表。在关系世界中,您可以考虑使用一个带有 和 的表,以及另一个带有引用公共属性的键值对的表。IDNAME

使用 SAP HANA 的 JSON Document Store 会更容易,这是一个用于管理半结构化数据的原生引擎。在此方案中,您将在 Pandas 数据帧上使用 to_json,并在 中create_collection_from_elements。可以使用简单的 SQL 查询生成的 JSON 集合。hana-ml