如何使用带有ODP(Oracle.DataAccess)的>> prepared query <<更新CLOB字段中的数据?

我正在尝试执行准备好的SQL查询,该查询更新Oracle 10g数据库(10.2.0.1)中的CLOB字段。

如果我从SQL Developer内部执行以下查询并提供占位符的值,则没有问题。 但是,如果我通过OracleCommand (Oracle.DataAccess.dll,版本1.102.0.1(我认为),.NET Framework 3.5)执行它,我会收到以下错误消息。 请注意,我们不使用默认的oracle客户端,因为我们需要批量插入。 不幸的是,给定的ODP版本和.NET Framework版本是一项艰难的要求,我们可能不会改变它。

查询:

 UPDATE master_table SET description = :description, modification_notes = :modification_notes WHERE master_id = :master_id; 

错误:

ORA-00932:不一致的数据类型:预期 – 获得CLOB

进一步的信息:

参数分配如下:

 var param_description = new OracleParameter(":description", OracleDbType.Clob); param_description.Value = "Test"; 

我尝试过以下的事情:

  • to_clob()插入SQL查询
  • Oracle.DataAccess.Types.OracleClob对象分配给参数。

我也找到了以下描述,但我真的希望能够保留准备好的查询。

如何使用C#在Oracle中插入CLOB字段

是否可以通过准备好的查询来完成此操作?

我附上了一个产生错误的完整示例。 DESCRIPTIONMODIFICATION_NOTES是数据库中CLOB类型的两列。


输入数据:

  • 连接: OracleConnection到数据库
  • master_id:要过滤的主键

码:
免责声明:我手动输入以下示例,可能存在实际代码中没有的错误

 var query = "UPDATE master_table " + "SET description = :description " + " modification_notes = :modification_notes " + "WHERE master_id = :master_id"; var param_master_id = new OracleParameter(":master_id", OracleDbType.Int64); param_master_id.Value = master_id; var param_description = new OracleParameter(":description", OracleDbType.Clob); param_description.Value = "Test1"; var param_master_id = new OracleParameter(":modification_notes", OracleDbType.Clob); param_description.Value = "Test2"; IDbCommand command = new OracleCommand(query, connection); command.parameters.Add(param_master_id); command.parameters.Add(param_description); command.parameters.Add(param_modification_notes); command.ExecuteNonQuery(); // this line throws an exception 

如果要按名称绑定,则需要将其设置为true。 默认值是按添加的参数的顺序绑定。

 cmd.BindByName = true; 

编辑:我的答案适用于尺寸大于32k的Clobs的典型用途(它们的设计目的)。 如果你知道你将永远绑定少于32k字节,或者通常情况下unicode的16k字符,你可以绑定为Varchar2,让你自己不必创建一个临时的高架。

请记住,oracle列中的LOB实际上是一个LOB定位器,一个指向实际数据的指针。 在使用该Lob Locator更新CLOB列之前,需要先创建并填充临时CLOB。

在Oracle Home的ODP.NET samples目录中应该有一个LOB目录,在那里看起来samples5.cs可能是一个好的起点。 这是一个片段:

  // Set the command OracleCommand cmd = new OracleCommand( "update multimedia_tab set story = :1 where thekey = 1"); cmd.Connection = con; cmd.CommandType = CommandType.Text; // Create an OracleClob object, specifying no caching and not a NCLOB OracleClob clob = new OracleClob(con, false, false); // Write data to the OracleClob object, clob, which is a temporary LOB string str = "this is a new story"; clob.Write(str.ToCharArray(), 0, str.Length); // Bind a parameter with OracleDbType.Clob cmd.Parameters.Add("clobdata", OracleDbType.Clob, clob, ParameterDirection.Input); try { // Execute command cmd.ExecuteNonQuery(); 

请参阅实际解决方案的已接受答案。

[编辑:前疑似答案]:
经过几天的测试和调试,我找到了远离我考虑的一切的解决方案:

显然,您需要在绑定任何其他内容之前先绑定所有Clob字段 – 即使使用实际占位符而不是使用:1:2等。

更改绑定顺序(即AddParameter调用的顺序)修复了它。

试试这个 :

  string Query3 = " DECLARE " + "str varchar2(32767); " + " BEGIN " + " str := '" + base64ImageRepresentationLogo + "'; " + " update map_general_settings set value=str where DESC_AR='LOGO_IMG' ; END; "; command.CommandText = Query3; command.ExecuteNonQuery();