Pandas拼接WHERE IN查SAP零件号时跳过无效值SQL报错方案
核心结论
SQL本身没有自动跳过语法错误的机制。SQL执行前会先做全句语法解析,只要拼接出来的语句有任何语法不符合规范,整个查询会直接终止抛错,根本不会进入数据匹配阶段,不可能实现类似Python里if syntaxError: continue的容错逻辑。
你现在遇到的问题本质是SQL拼接方式错误导致的,不是"无效值匹配不到"的问题:
- 你直接把读取到的零件号裸拼到IN子句里,没有给字符串类型的值加单引号,本身就不符合SQL语法
- 输入内容里的
to、特殊字符会被SQL解析器当成SQL语法的一部分(比如你报错的62219-01 to -04,解析器会把to当成SQL关键字,自然抛出语法错误) - 这种裸拼SQL的写法还存在严重的SQL注入风险
你不需要逐个枚举异常场景做过滤,只要换用参数化查询,就能一次性解决所有语法问题,同时自动实现"不存在的值直接忽略"的效果。
修正后实现代码
参数化查询会把所有传入的值当做纯字符串参数处理,不会解析值里的任何内容为SQL语法,从根源上避免特殊字符、关键字导致的报错;对于不在PART_NO列里的无效值,IN匹配时自然不会命中,结果里不会返回对应记录,完全符合你的需求。
import pandas as pd from hdbcli import dbapi userFile = r'T:\H01 Cell\Projects\Part Breakdown Update Spreadsheet Improvements\2022.03.21 Part Breakdown update - VK.xlsm' # 读取Excel中零件号列 partNums = pd.read_excel( io=userFile, sheet_name='Inputs', usecols=lambda x: 'Unnamed' not in x, skiprows=1, dtype={'Part List': str} ) # 建立SAP HANA连接 conn = dbapi.connect(address="server", port=####, user="XXXXX", password="XXXXXXX") # 预处理候选零件号:去重、去空值即可,不需要额外过滤特殊字符 part_candidates = partNums['Part List'].dropna().drop_duplicates().tolist() # 生成参数占位符,几个零件号就生成几个? placeholders = ', '.join(['?'] * len(part_candidates)) query_columns = [ "PART_NO", "PLANT", "LOCATION_DESCRIPTION", "VALUATION_TYPE" ] query_col_str = ', '.join(query_columns) # 构造参数化SQL语句,值的位置用?占位 queryInvOnHand = f""" SELECT DISTINCT {query_col_str} FROM ZWILLIAMS.ZV_WI_GU_INVENTORY_ON_HAND_IM_THIN INV WHERE PART_NO IN ({placeholders}) """ # 传入参数执行查询,不会触发语法错误,不存在的零件号自动不返回 inventoryOnHand = pd.read_sql(queryInvOnHand, conn, params=part_candidates) conn.close()
补充说明
- 该方案不需要你提前判断哪些零件号是"无效"的,不管输入里带
<、>、!还是to这类关键字,都会被当做普通字符串处理,不会触发语法错误 - 如果后续需要剔除明显不符合零件号规则的输入,只需要加一层宽松的正则校验即可(比如限制允许的字符范围、字符串长度),但这步不是必须的,参数化已经能保证查询正常执行
- 禁止继续使用手动字符串拼接的方式写SQL,除了语法问题外还存在SQL注入的安全隐患
内容的提问来源于stack exchange,提问作者smichael_44
相关产品推荐
相关产品推荐

