【问题标题】:Run Time error: -2147217887(80040e21) The system cannot find a message text for the message number 0x80040e21 in the message file for OraOLEDB运行时错误:-2147217887(80040e21) 系统在 OraOLEDB 的消息文件中找不到消息号 0x80040e21 的消息文本
【发布时间】:2020-08-04 06:20:26
【问题描述】:

我正在使用 Excel 宏将 Excel 工作表中的数据上传到包含 167 列的 Oracle 数据库。我在执行语句中收到此错误。

我在调试此错误时遇到了困难。

运行时错误:-2147217887(80040e21) 系统在 OraOLEDB 的消息文件中找不到消息号 0x80040e21 的消息文本

strSQL = "Update T_SAP_ZSSTABL_NEW set TSZ_CHARG = ?, TSZ_MATNR = ?, TSZ_MAKTX = ?, TSZ_MATKL = ?, TSZ_SEC1_MAX = ?, TSZ_SEC2_MAX = ?, TSZ_THICKNESS = ?, TSZ_TDCNO = ?," _
& "TSZ_LENGTH = ?, TSZ_OUT_DIA = ?, TSZ_IN_DIA = ?, TSZ_FKDAT = ?, TSZ_WERKS = ?, TSZ_CUSCD = ?, TSZ_FTRAMT = ?, TSZ_VRKME = ?, TSZ_FKIMG = ?, TSZ_RECDATE1 = ?," _
& "TSZ_QCODE = ?, TSZ_ZWERKS = ?, TSZ_AUART1 = ?, TSZ_MRK_CUST_NM = ?, TSZ_SHTO = ?, TSZ_CHARG1 = ?, TSZ_MATNR1 = ?, TSZ_TOTVAL = ?, TSZ_SPART = ?, TSZ_MANDT = ?," _
& "TSZ_LZONE = ?, TSZ_ZSSCAMT = ?, TSZ_PROD_DATE = ?, TSZ_PROD_ITEM = ?, TSZ_POEDAT = ?, TSZ_ERDAT = ?, TSZ_REFSO = ?, TSZ_AR4DAT = ?, TSZ_AR4NO = ?, TSZ_AR4_TYPE = ?," _
& "TSZ_SECHECESS = ?, TSZ_LIFNR = ?, TSZ_SHIPMD = ?, TSZ_MRK_DEST = ?, TSZ_ZTILAMT = ?, TSZ_ZFC1AMT = ?, TSZ_ZFMCAMT = ?, TSZ_ZINAAMT = ?, TSZ_ZEF0AMT = ?, TSZ_ZWF0AMT = ?," _
& "TSZ_ZCHAAMT = ?, TSZ_ZDCAMT = ?, TSZ_KZWI4 = ?, TSZ_KZWI3 = ?, TSZ_LISTPRICE = ?, TSZ_GROSSWT = ?, TSZ_LAND1 = ?, TSZ_NIELS = ?, TSZ_MVGR1 = ?, TSZ_KONDM = ?, TSZ_AUART = ?," _
& "TSZ_KURRF = ?, TSZ_PGROUP = ?, TSZ_DRAW_TYPE = ?, TSZ_AESKD = ?, TSZ_LOADCHRG = ?, TSZ_LGORT = ?, TSZ_NAME2 = ?, TSZ_SHTNAME = ?, TSZ_TOCIND = ?, TSZ_MARK_CUST_DESC = ?, TSZ_TARE_WEIGHT = ?," _
& "TSZ_GROSS_WEIGHT = ?, TSZ_NET_WEIGHT = ?, TSZ_VKBUR = ?, TSZ_MVGR2 = ?, TSZ_VTWEG = ?, TSZ_SPEC = ?, TSZ_LEN2 = ?, TSZ_LEN1 = ?, TSZ_CLASS = ?, TSZ_END_FINISH = ?, TSZ_SUR_FINISH = ?," _
& "TSZ_CATEGORY = ?, TSZ_MILL = ?, TSZ_RUNDATE = ?, TSZ_CESSVAL = ?, TSZ_WAERK = ?, TSZ_IDLEFRT = ?, TSZ_FRTACCR2 = ?, TSZ_FRTACCR1 = ?, TSZ_STPRS = ?, TSZ_BSTDK = ?, TSZ_POSEX = ?," _
& "TSZ_BSTNK = ?, TSZ_WCAINV = ?, TSZ_J_1ICHID = ?, TSZ_LENGTH_CR = ?, TSZ_PCODE = ?, TSZ_EIKTO = ?, TSZ_KDMAT = ?, TSZ_CPUDT = ?, TSZ_TRGRP = ?, TSZ_DRCPT = ?, TSZ_TRTIME = ?," _
& "TSZ_GRQTY = ?, TSZ_GRNO = ?, TSZ_KDKG2 = ?, TSZ_WAGON_RLY = ?, TSZ_HUBLIFNR = ?, TSZ_TNAME1 = ?, TSZ_LLIEF = ?, TSZ_TRNSIND = ?, TSZ_REGIO = ?, TSZ_DESTDESC = ?, TSZ_DESTCD = ?," _
& "TSZ_VGBEL = ?, TSZ_POSNV = ?, TSZ_VBELV = ?, TSZ_AUPOS = ?, TSZ_AUBEL = ?, TSZ_MRP = ?, TSZ_DISCLP = ?, TSZ_LSTPRC = ?, TSZ_CAMNO = ?, TSZ_KZWI1 = ?, TSZ_DUEDT = ?," _
& "TSZ_ZTERM = ?, TSZ_NETWR = ?, TSZ_OTHERS = ?, TSZ_KWERT = ?, TSZ_SERIAL = ?, TSZ_STCEG = ?, TSZ_TOTAX = ?, TSZ_SRTAX = ?,TSZ_ADDSTAMT = ?, TSZ_STAMT = ?," _
& "TSZ_BSTCSTVAL = ?, TSZ_BSTCSTPERCENT = ?, TSZ_IND = ?, TSZ_EDAMT = ?, TSZ_MATLVAL = ?, TSZ_MATLRATE = ?, TSZ_QTY_METER = ?, TSZ_QTY_NO = ?, TSZ_KUNRG = ?," _
& "TSZ_CUSNAME = ?, TSZ_TYPE = ?, TSZ_PERIOD = ?, TSZ_VKORG = ?, TSZ_FKART = ?, TSZ_ETOIND = ?, TSZ_ZCHARG = ?, TSZ_ZMATNR = ?, TSZ_VTEXT = ?, TSZ_KALKS = ?," _
& "TSZ_VPRS_COST = ?, TSZ_WBS_ELEMENT = ?, TSZ_PRODCTN_ORDER_NO = ?, TSZ_SHOPPING_CART_NO = ?, TSZ_WOODEN_PALLET_WT = ?, TSZ_ZFINCHRG = ?, TSZ_ZATXAMT = ?, TSZ_VBELP1 = ?, TSZ_VBELN1 = ?, TSZ_VBELN_M = ? where TSZ_VBELN = ? and TSZ_POSNR = ?"


cmd.CommandText = strSQL

Set MyParameter = cmd.CreateParameter("CHARG", adVarChar, adParamInput, 10, VBELN)
cmd.Parameters.Append MyParameter

Set MyParameter = cmd.CreateParameter("MATNR", adVarChar, adParamInput, 6, POSNR)
cmd.Parameters.Append MyParameter

Set MyParameter = cmd.CreateParameter("MAKTX", adVarChar, adParamInput, 10, CHARG)
cmd.Parameters.Append MyParameter
.
.
.
.
.

对每个参数都这样做

最后

 cmd.Execute

【问题讨论】:

  • 是的,我注意到了。这里忘记改了。问题依然存在。

标签: sql excel vba oracle


【解决方案1】:

有了这么多参数,问题可能是任何一项,包括不匹配的数据类型、数据长度等。这就是必须运用调试技术的地方。

  1. 仔细检查表(T_SAP_ZSSTABL_NEW)的数据类型。 Oracle 可能具有无法立即转换为ADO types 的数据类型,例如BLOBCLOBBFILE、高精度数字类型、最大字符类型或扩展类型(XML、媒体等)。

  2. 尝试扩展数据长度(或在参数赋值中留空):

    Set MyParameter = cmd.CreateParameter("MATNR", adVarChar, adParamInput, 100, POSNR)
    
    Set MyParameter = cmd.CreateParameter("MATNR", adVarChar, adParamInput, , POSNR)
    

    如果需要,请使用 VBA 的 Len() 检查可变长度,以在附加参数之前引发用户警告。

  3. 尝试使用相同的参数运行SELECT 版本的查询以返回单行结果。如果发生同样的错误,从第一个参数开始,然后依次添加第二个或批次 10 以隔离有问题的项目。

    SELECT ? AS TSZ_CHARG_PARAM, ? AS TSZ_MATNR_PARAM, ? AS TSZ_MAKTX_PARAM,
           ...
    FROM T_SAP_ZSSTABL_NEW
    WHERE TSZ_VBELN = ? AND TSZ_POSNR = ?
    
  4. 重构代码以保持一致性,因为您可能遗漏了一个或未对齐的一个,这可能会出现许多重复行。始终以 DRY(不要重复自己)代码为目标。一种选择是使用带有键/值对的dictionary,而不是 160 多个变量或命名范围:

    Dim key As Variant
    Dim paramDict As Object
    Set paramDict = CreateObject("Scripting.Dictionary")
    
    For ...
        paramDict.Add "KeyX", "ValueX"
    Next ...
    
    ...
    
    With cmd
      .ActiveConnection = myOracleConn
      .CommandText = strSQL
      .CommandType = adCmdText
    
      For Each key In  paramDict.Keys
         .Parameters.Append .CreateParameter(key, adVarChar, adParamInput, , paramDict(key))
      Next key
    
      .Execute
    End With
    

    如果您有混合类型,请尝试为每种类型创建不同的字典并按顺序迭代它们以附加参数。并调整UPDATE 使所有相同类型彼此靠近。回想UPDATE 不需要遵循表定义中的列顺序。

  5. 如果可能(或长期解决方案),请考虑将 TSZ 列的宽格式表重新设计为长格式的规范化形式。

    ID   POSNR   VBELN   Indicator   Value
     #     XXX     XXX       CHARG     XXX
     #     XXX     XXX       MATNR     XXX
     #     XXX     XXX       MAKTX     XXX
    ...
    

    虽然这将为每个唯一标识符添加 167 行,但在数据库设计中,行比列便宜得多,因此查询会更容易,数据存储更具可扩展性,维护也更高效。例如,新指标不需要包含所有元信息的新定义列,而只需一个新行。使用 Oracle 的 PIVOT,您可以轻松地重新渲染宽格式。

总而言之,没有一种单一、清晰的方法可以调试像数据库连接这样的 API 扩展产生的运行时错误。 SQL 语法或 VBA 对象引用可以轻松处理,但特定于数据的问题需要创造性地挖掘整个过程。

【讨论】:

  • 感谢您的宝贵意见。我一定会在我的代码中使用它们。
【解决方案2】:

伙计们,错误是因为我试图附加比实际存在更多的参数。有这么多列,我失去了附加块数量的计数。我应该按照 Parfait 的建议更加努力地遵循最佳实践。让我们给他一个赞成票。 :D

【讨论】:

    猜你喜欢
    • 2022-10-04
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多