oracle - 通过 CLOB 参数将巨大的 XML 从 C#/.Net 传递到 Oracle 存储过程 - ORA-01008 : not all variables bound

标签 oracle ora-01008

环境:

服务器: 64位windows 2008上的Oracle 11.2g服务器

客户: Windows XP SP3、ASP.Net 4.0、Visual Studio 2010、C# 上的 Oracle 11g 客户端

XML 的输入大小 ~ 1,206,500 个字符 (根据我拥有的最大数据计算)。

设想:

Web 应用程序生成 Oracle 存储过程用于更新数据库中的表的 XML。由于 XML 非常大,因此选择的存储过程参数类型是 CLOB 而不是 LONG,因为 LONG 有 32760 个字符的限制。

问题:

使用 CLOB 作为参数类型会引发错误“ORA-01008:并非所有变量都绑定(bind)”对于相同的存储过程代码,该代码非常适用于 LONG 参数类型(并且 XML 长度 < 32760)

用于调用存储过程的 C# 代码:

OracleCommand DbUpdateCommand = null;
OracleLob tempLOB = null;

DbUpdateCommand.CommandText = "declare xx clob; begin dbms_lob.createtemporary(xx, false, 0); :tempclob := xx; end;";
DbUpdateCommand.Parameters.Add(new OracleParameter("tempclob", OracleType.Clob)).Direction = ParameterDirection.Output;
DbUpdateCommand.ExecuteNonQuery();

//Assign the value to the LOB
tempLOB = (OracleLob)DbUpdateCommand.Parameters[0].Value;
tempLOB.BeginBatch(OracleLobOpenMode.ReadWrite);

//Convert the string to byte array to write to LOB
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] renewalDetailXMLBytes = encoding.GetBytes(renewalDetailXML);
tempLOB.Write(renewalDetailXMLBytes, 0, renewalDetailXMLBytes.Length);
tempLOB.EndBatch();

DbUpdateCommand.CommandText = "P_WEB_PRDCR_RNEW_UPDT";
DbUpdateCommand.CommandType = System.Data.CommandType.StoredProcedure;
DbUpdateCommand.Parameters.Add("PN_KEY_AGNT_RNEW_HDR", 
System.Data.OracleClient.OracleType.Number, 12).Value = agentRenewalHeader;
DbUpdateCommand.Parameters.Add("PN_KEY_CO", 
System.Data.OracleClient.OracleType.Number, 12).Value = companyCode;
DbUpdateCommand.Parameters.Add("PC_RNWL_DETL_XML", 
    System.Data.OracleClient.OracleType.Clob).Value = tempLOB;
DbUpdateCommand.Parameters.Add("PS_USR_NM",
System.Data.OracleClient.OracleType.VarChar,255).Value = userName;

DbUpdateCommand.ExecuteNonQuery();

Oracle 存储过程代码:
CREATE OR REPLACE PROCEDURE DOIADMIN.P_WEB_PRDCR_RNEW_UPDT (
    PN_KEY_AGNT_RNEW_HDR IN NUMBER,
    PN_KEY_CO            IN NUMBER,
    PC_RNWL_DETL_XML     IN CLOB,
    PS_USR_NM            IN VARCHAR2
)
AS
        lx_rnew_detl_xml    XMLTYPE;
    lct_rnew_detl_cntx  DBMS_XMLSAVE.ctxtype;

    --Construct the complete xml for financial data
    lx_rnew_detl_xml := XMLTYPE(PC_RNWL_DETL_XML);

    --table to be updated with the xml
    lct_rnew_detl_cntx := DBMS_XMLSAVE.newcontext('IL_AGNT_RNEW_DETL');

    --Set the key column list
    DBMS_XMLSAVE.SETKEYCOLUMN(lct_rnew_detl_cntx, 'KEY_AGNT_RNEW_HDR');
    DBMS_XMLSAVE.SETKEYCOLUMN(lct_rnew_detl_cntx, 'KEY_CO');
    DBMS_XMLSAVE.SETKEYCOLUMN(lct_rnew_detl_cntx, 'KEY_INDVDL_LIC');

    --Set the udpate column
    DBMS_XMLSAVE.SETUPDATECOLUMN(lct_rnew_detl_cntx, 'FLG_MARKED_FOR_CANCEL');

    --update the table from the rows
    ln_cntr := DBMS_XMLSAVE.UPDATEXML(lct_rnew_detl_cntx, lx_rnew_detl_xml.getCLOBVal());

    DBMS_XMLSAVE.closecontext(lct_rnew_detl_cntx);
END p_web_prdcr_rnew_updt;

任何曾通过 CLOB 参数传递大型 XML 并在存储过程中将该 CLOB 转换为 XML 的人可以帮忙吗?对此问题的任何替代方法也将受到高度赞赏。

提前致谢。

最佳答案

这是解决此问题的 C# 代码。在重用相同的命令对象之前,我错过了清除参数。

C# 代码

OracleCommand DbUpdateCommand = null;
OracleLob tempLOB = null;

DbUpdateCommand.CommandText = "declare xx clob; begin dbms_lob.createtemporary(xx, false, 0); :tempclob := xx; end;";
DbUpdateCommand.Parameters.Add(new OracleParameter("tempclob", OracleType.Clob)).Direction = ParameterDirection.Output;
DbUpdateCommand.ExecuteNonQuery();

//Assign the value to the LOB
tempLOB = (OracleLob)DbUpdateCommand.Parameters[0].Value;
tempLOB.BeginBatch(OracleLobOpenMode.ReadWrite);

//Convert the string to byte array to write to LOB
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] renewalDetailXMLBytes = encoding.GetBytes(renewalDetailXML);
tempLOB.Write(renewalDetailXMLBytes, 0, renewalDetailXMLBytes.Length);
tempLOB.EndBatch();

DbUpdateCommand.CommandText = "P_WEB_PRDCR_RNEW_UPDT";
DbUpdateCommand.CommandType = System.Data.CommandType.StoredProcedure;

//Missing line - start
DbUpdateCommand.Parameters.Clear();
//Missing line - end

DbUpdateCommand.Parameters.Add("PN_KEY_AGNT_RNEW_HDR", 
    System.Data.OracleClient.OracleType.Number, 12).Value = 
        agentRenewalHeader;
DbUpdateCommand.Parameters.Add("PN_KEY_CO", 
    System.Data.OracleClient.OracleType.Number, 12).Value = 
        companyCode;
DbUpdateCommand.Parameters.Add("PC_RNWL_DETL_XML", 
    System.Data.OracleClient.OracleType.Clob).Value =
        tempLOB;
DbUpdateCommand.Parameters.Add("PS_USR_NM",
    System.Data.OracleClient.OracleType.VarChar,255).Value = 
        userName;

DbUpdateCommand.ExecuteNonQuery();

关于oracle - 通过 CLOB 参数将巨大的 XML 从 C#/.Net 传递到 Oracle 存储过程 - ORA-01008 : not all variables bound,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3375206/

相关文章:

database - Oracle 中表行的创建日期时间是多少?

sql - Oracle - 每日分区方法适合具有数百万行的表

oracle - 为什么 SET DEFINE OFF 不适用于冒号 ( :) character?

sql - 我只需要找到每个城市薪酬最高的员工

java - "ORA-01008: not all variables bound"错误

c# - ORA-01008: 并非所有变量都绑定(bind)。他们被束缚

c# - ORA-01008 与所有变量绑定(bind)

oracle - 从 PL/SQL 返回错误