Python连接SAP BW Cube调用RFC_READ_TABLE报错的原因排查
问题:通过pyrfc访问SAP BW Cube时出现TABLE_NOT_AVAILABLE错误
我有一个SAP BW Cube,可通过Power BI的“SAP Business Warehouse Message Server”连接器及以下Power M代码访问:
let Source = SapBusinessWarehouse.Cubes("My BW Ip", "00", "001", [Implementation="2.0"]), ZCOP = Source{[Name="ZCOP"]}[Data], #"ZCOP/ZQ_COP_2" = ZCOP{[Id="ZCOP/ZQ_COP_2"]}[Data], #"Added Items" = Cube.Transform(#"ZCOP/ZQ_COP_2", { {Cube.AddAndExpandDimensionColumn, "[0CALMONTH]", {"[0CALMONTH].[LEVEL01]"}, {"Año/Mes natural.Año/Mes natural Nivel 01"}}, {Cube.AddAndExpandDimensionColumn, "[0PLANT]", {"[0PLANT].[LEVEL01]"}, {"Centro.Centro Nivel 01"}}, {Cube.AddAndExpandDimensionColumn, "[0COSTDATE]", {"[0COSTDATE].[LEVEL01]"}, {"Fecha cálculo coste.Fecha cálculo coste Nivel 01"}}, {Cube.AddAndExpandDimensionColumn, "[0MATERIAL]", {"[0MATERIAL].[LEVEL01]"}, {"Material.Material Nivel 01"}}, {Cube.AddAndExpandDimensionColumn, "[0COMP_CODE]", {"[0COMP_CODE].[LEVEL01]"}, {"Sociedad.Sociedad Nivel 01"}}, {Cube.AddAndExpandDimensionColumn, "[0COSTSTATUS]", {"[0COSTSTATUS].[LEVEL01]"}, {"Status cálculo coste.Status cálculo coste Nivel 01"}}, {Cube.AddAndExpandDimensionColumn, "[0CURTYPE]", {"[0CURTYPE].[LEVEL01]"}, {"Tipo de moneda.Tipo de moneda Nivel 01"}}, {Cube.AddAndExpandDimensionColumn, "[0VALUATION]", {"[0VALUATION].[LEVEL01]"}, {"Vista valoración.Vista valoración Nivel 01"}}, {Cube.AddMeasureColumn, " Análisis Calidad", "[Measures].[00O2TS3ZGQX4VVAT463GW2O53]"}, {Cube.AddMeasureColumn, " Costos Ind. Fabricación", "[Measures].[00O2TS3ZGQX4VVAT463GW2HTJ]"}, {Cube.AddMeasureColumn, " Gastos Admin", "[Measures].[00O2TS3ZGQX4VVAT8TY9H77HZ]"}, {Cube.AddMeasureColumn, " Mano de Obra Directa", "[Measures].[00O2TS3ZGQX4VVAT0KHEJIEUV]"}, {Cube.AddMeasureColumn, "Materia Prima", "[Measures].[00O2TS3ZGQX4VVASYNHA84OTZ]"}, {Cube.AddMeasureColumn, "Material de Empaque", "[Measures].[00O2TS3ZGQX4VVASYNHA84V5J]"}, {Cube.AddMeasureColumn, "Subcontratación", "[Measures].[00O2TS3ZGQX4VVAT8TY9H716F]"} }) in #"Added Items"
尝试用Python的pyrfc库实现相同操作,代码如下:
from pyrfc import Connection import pandas as pd # Define connection parameters conn_params = { 'user': 'user', 'passwd': 'pass', 'ashost': 'My IP', 'sysnr': '00', 'client': '001', 'lang': 'EN' } # Establish connection conn = Connection(**conn_params) # Read data from SAP BW cube cube_name = 'ZCOP/ZQ_COP_2' result = conn.call('RFC_READ_TABLE', QUERY_TABLE=cube_name) # Close connection conn.close() # Convert result to DataFrame df = pd.DataFrame(result['DATA']) # Extract column names from result columns = [col['FIELDNAME'] for col in result['FIELDS']] # Set DataFrame column names df.columns = columns # Perform transformations similar to Power Query # Add dimension columns df['Año/Mes natural.Año/Mes natural Nivel 01'] = df['[0CALMONTH].[LEVEL01]'] df['Centro.Centro Nivel 01'] = df['[0PLANT].[LEVEL01]'] df['Fecha cálculo coste.Fecha cálculo coste Nivel 01'] = df['[0COSTDATE].[LEVEL01]'] df['Material.Material Nivel 01'] = df['[0MATERIAL].[LEVEL01]'] df['Sociedad.Sociedad Nivel 01'] = df['[0COMP_CODE].[LEVEL01]'] df['Status cálculo coste.Status cálculo coste Nivel 01'] = df['[0COSTSTATUS].[LEVEL01]'] df['Tipo de moneda.Tipo de moneda Nivel 01'] = df['[0CURTYPE].[LEVEL01]'] df['Vista valoración.Vista valoración Nivel 01'] = df['[0VALUATION].[LEVEL01]'] # Add measure columns df['Análisis Calidad'] = df['[Measures].[00O2TS3ZGQX4VVAT463GW2O53]'] df['Costos Ind. Fabricación'] = df['[Measures].[00O2TS3ZGQX4VVAT463GW2HTJ]'] df['Gastos Admin'] = df['[Measures].[00O2TS3ZGQX4VVAT8TY9H77HZ]'] df['Mano de Obra Directa'] = df['[Measures].[00O2TS3ZGQX4VVAT0KHEJIEUV]'] df['Materia Prima'] = df['[Measures].[00O2TS3ZGQX4VVASYNHA84OTZ]'] df['Material de Empaque'] = df['[Measures].[00O2TS3ZGQX4VVASYNHA84V5J]'] df['Subcontratación'] = df['[Measures].[00O2TS3ZGQX4VVAT8TY9H716F]'] # Drop unnecessary columns df.drop(columns=['[0CALMONTH].[LEVEL01]', '[0PLANT].[LEVEL01]', '[0COSTDATE].[LEVEL01]', '[0MATERIAL].[LEVEL01]', '[0COMP_CODE].[LEVEL01]', '[0COSTSTATUS].[LEVEL01]', '[0CURTYPE].[LEVEL01]', '[0VALUATION].[LEVEL01]', '[Measures].[00O2TS3ZGQX4VVAT463GW2O53]', '[Measures].[00O2TS3ZGQX4VVAT463GW2HTJ]', '[Measures].[00O2TS3ZGQX4VVAT8TY9H77HZ]', '[Measures].[00O2TS3ZGQX4VVAT0KHEJIEUV]', '[Measures].[00O2TS3ZGQX4VVASYNHA84OTZ]', '[Measures].[00O2TS3ZGQX4VVASYNHA84V5J]', '[Measures].[00O2TS3ZGQX4VVAT8TY9H716F]'], inplace=True) # Display DataFrame print(df)
执行result = conn.call('RFC_READ_TABLE', QUERY_TABLE=cube_name)时,出现错误:
ABAPApplicationError: 5 (rc=5): key=TABLE_NOT_AVAILABLE, message=ID:SV Type:E Number:029 ZCOP/ZQ_COP_2 [MSG: class=SV, type=E, number=029, v1-4:=ZCOP/ZQ_COP_2;;;]
错误原因
RFC_READ_TABLE是SAP官方标准RFC,仅支持读取ABAP字典中的透明表、簇表等数据库表对象,无法识别SAP BW的Cube或Query。- 你要访问的
ZCOP/ZQ_COP_2是BW查询对象,并非传统ABAP数据库表,因此RFC抛出"表不存在"的错误。 - Power BI的BW连接器通过BW专用的BICS(Business Intelligence Consumer Service)接口访问Cube和查询,与
RFC_READ_TABLE的底层逻辑完全不同。
解决方案
方案1:使用专用BW访问库pysapbw
pysapbw是Python专属的SAP BW访问库,直接支持BICS接口,可直接读取Cube或Query数据:
- 安装库:
pip install pysapbw
- 适配需求的代码示例:
from pysapbw import SAPBW import pandas as pd # 建立BW连接 bw = SAPBW( host="My BW Ip", system_number="00", client="001", username="user", password="pass", language="EN" ) # 加载目标查询并转换为DataFrame query = bw.get_query("ZCOP/ZQ_COP_2") df = query.to_dataframe() # 关闭连接 bw.close() # 调整列名以匹配Power M的结果 column_mapping = { "[0CALMONTH].[LEVEL01]": "Año/Mes natural.Año/Mes natural Nivel 01", "[0PLANT].[LEVEL01]": "Centro.Centro Nivel 01", "[0COSTDATE].[LEVEL01]": "Fecha cálculo coste.Fecha cálculo coste Nivel 01", "[0MATERIAL].[LEVEL01]": "Material.Material Nivel 01", "[0COMP_CODE].[LEVEL01]": "Sociedad.Sociedad Nivel 01", "[0COSTSTATUS].[LEVEL01]": "Status cálculo coste.Status cálculo coste Nivel 01", "[0CURTYPE].[LEVEL01]": "Tipo de moneda.Tipo de moneda Nivel 01", "[0VALUATION].[LEVEL01]": "Vista valoración.Vista valoración Nivel 01", "[Measures].[00O2TS3ZGQX4VVAT463GW2O53]": "Análisis Calidad", "[Measures].[00O2TS3ZGQX4VVAT463GW2HTJ]": "Costos Ind. Fabricación", "[Measures].[00O2TS3ZGQX4VVAT8TY9H77HZ]": "Gastos Admin", "[Measures].[00O2TS3ZGQX4VVAT0KHEJIEUV]": "Mano de Obra Directa", "[Measures].[00O2TS3ZGQX4VVASYNHA84OTZ]": "Materia Prima", "[Measures].[00O2TS3ZGQX4VVASYNHA84V5J]": "Material de Empaque", "[Measures].[00O2TS3ZGQX4VVAT8TY9H716F]": "Subcontratación" } df = df.rename(columns=column_mapping) # 移除原始列(可选) df = df.drop(columns=list(column_mapping.keys()), errors="ignore") print(df)
方案2:自定义ABAP RFC函数
如果无法使用第三方库,可联系SAP ABAP开发人员创建自定义RFC函数,内部通过BW API(如RSDRI_INFOPROV_READ)读取查询数据:
- 开发自定义RFC:函数输入参数为查询名称,输出为包含所需维度和指标的结构化数据表。
- Python端调用示例:
from pyrfc import Connection import pandas as pd conn_params = { 'user': 'user', 'passwd': 'pass', 'ashost': 'My BW Ip', 'sysnr': '00', 'client': '001', 'lang': 'EN' } conn = Connection(**conn_params) # 调用自定义RFC,假设函数名为Z_BW_QUERY_READ result = conn.call('Z_BW_QUERY_READ', QUERY_NAME='ZCOP/ZQ_COP_2') conn.close() # 转换为DataFrame df = pd.DataFrame(result['QUERY_DATA']) # 根据自定义RFC的输出结构调整列名 print(df)
内容的提问来源于stack exchange,提问作者Gustavo A. Marín Acevedo
相关产品推荐
相关产品推荐

