问题:oracle CLOB类型;结果:oracle中Blob和Clob类型的区别

时间:2022-08-30 15:27:47
BLOBCLOB都是大字段类型,BLOB是按二进制来存储的,而CLOB是可以直接存储文字的。其实两个是可以互换的的,或者可以直接用LOB字段代替这两个。
但是为了更好的管理ORACLE数据库,通常像图片、文件、音乐等信息就用BLOB字段来存储,先将文件转为二进制再存储进去。而像文章或者是较长的文字,
就用CLOB存储,这样对以后的查询更新存储等操作都提供很大的方便。

Oracle中Clob类型处理解析

2008-08-09 08:52 18249人阅读 评论(1) 收藏 举报
   最近利用NHibernate映射类型为Clob字段在插入数据时发现当字符的字节数(一个半角字符一个字节,一个全角字符两个字节)在2000-4000之间时报错(ORA-01461:仅可以插入LONG列的LONG值赋值)。经过不断查找资料和自己的试验该问题终于得到解决,下边我将自己的心得给大家做一个分享。

准备

系统环境 xp+.net2.0+oracle9i

表结构(由于是测试,表结构随便建了一张) XX 

字段名

类型

ID

VARCHAR2(70)

TEST

CLOB

 

测试

 

方式1:直接将CLOB的值拼写在SQL语句中。

代码:

  1. string id = Guid.NewGuid().ToString();
  2. OracleCommand cmd = Conn.CreateCommand();
  3. cmd.CommandText = "insert into xx(id,test) values('" + id + "','" + data + "')";// data是一个变量,存储你要插入的字符串
  4. cmd.ExecuteNonQuery();

情况分析:

     当data的长度大于4000时报错(ORA-01704:文字字符串过长),小于或等于4000时正常插入。

原因分析:

   之所以会出现长度大于4000时报错,是因为Oracle中有SQL语句中两个单引号之间的字符数不能大于4000的限制。'" + data + "' data在sql语句之间,当data的值大于4000个字节时就会报错。

解决办法:

   这种方式比较棘手,但有更好的方式,下边会讲到。

方式2:采用参数形式。

代码:

  1. string id = Guid.NewGuid().ToString();
  2. OracleCommand cmd = Conn.CreateCommand();
  3. cmd.CommandText = "insert into xx(id,test) values('" + id + "',:p1)";
  4. OracleParameter p1 = new OracleParameter("p1", OracleType.Clob);
  5. p1.Value = data; // data是一个变量,存储你要插入的字符串
  6. cmd.Parameters.Add(p1);
  7. cmd.ExecuteNonQuery();

情况分析:

    采用这种方式能够正常插入。所以推荐用这种方式。

原因分析:

解决办法:

   无

方式3:采用参数形式,但是参数类型写为OracleType. NVarChar

代码:

  1. string id = Guid.NewGuid().ToString();
  2. OracleCommand cmd = Conn.CreateCommand();
  3. cmd.CommandText = "insert into xx(id,test) values('" + id + "',:p1)";
  4. OracleParameter p1 = new OracleParameter("p1", OracleType. NVarChar);
  5. p1.Value = data; // data是一个变量,存储你要插入的字符串
  6. cmd.Parameters.Add(p1);
  7. cmd.ExecuteNonQuery();

情况分析:

    为什么要写这种方式,因为这种方式和采用NHibernate的方式很相似,先看看在这种方式会产生什么情况。当data的字节数在0-2000之间时正常插入,大于4000时也正常插入,但在2000-4000时则失败,报错(ORA-01461:仅可以插入LONG列的LONG值赋值)

原因分析:

   没有采用对应的Oracle类型。

解决办法:

   采用OracleType.Clob

下边采用NHibernate插入数据,NHibernate具体怎用不在本次讨论范围。

NHibernate采用的版本为1.2.1.4000。

下边大至把简要配置写下。

App.config

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<configSections>

<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />

</configSections>

<nhibernate>

<add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />

<add key="hibernate.connection.driver_class" value="NHibernate.Driver.OracleClientDriver" />

<add key="hibernate.connection.isolation" value="ReadCommitted"/>

<add key="hibernate.dialect" value="NHibernate.Dialect.Oracle9Dialect" />

<add key="hibernate.connection.connection_string"

value="Data Source=Orcl_192.168.0.232;User ID =icqs_test;Password=icqs_test" />

<add key="show_sql" value="true" />

<add

key="hibernate.adonet.batch_size"

value="100"

/>

</nhibernate>

</configuration>

xx.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace Test.Enties
  5. {
  6.     [Serializable]
  7.     public class Xx
  8.     {
  9.         public Xx()
  10.         {
  11.         }
  12.         private string id;
  13.         public virtual string Id
  14.         {
  15.             get { return id; }
  16.             set { id = value; }
  17.         }
  18.         public virtual string Test
  19.         {
  20.             get { return test; }
  21.             set { test = value; }
  22.         }
  23.         private string test;
  24.     }
  25. }

xx.hbm.xml

<?xml version="1.0" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Test.Enties" assembly="Test">

<class name="Xx" table="xx" lazy="true">

<id name="Id" column="id" type="String">

<generator class="assigned"/>

</id>

<property column="test" type="StringClob" name="Test" length="2147483647" />

</class>

</hibernate-mapping>

说明:

<add key="hibernate.connection.driver_class" value="NHibernate.Driver.OracleClientDriver" />这里的驱动用的NHibernate.Driver.OracleClientDriver,其实是对微软的OracleClient的封装啦,其实内部还是调用微软的OracleClient的东东。引用System.Data.OracleClient.dll即可OracleClient。

做好上边的配置后,便有了以下的方式

方式4:采用NHibernate

代码:

  1. string id = Guid.NewGuid().ToString();
  2. Xx xx = new Xx();
  3. xx.Test = data; // data是一个变量,存储你要插入的字符串
  4. xx.Id = id;
  5. ISession session = SessionFactory.OpenSession();
  6. session.Save(xx);
  7. session.Flush();

情况分析:

   当data的字节数在0-2000之间时正常插入,大于4000时也正常插入,但在2000-4000时则失败,报错(ORA-01461:仅可以插入LONG列的LONG值赋值).情况和方式3的情况一样。

原因分析:

   NHibernate在用OracleClient映射StringClob时,设置参数类型为OracleType. NVarChar,导致插入有BUG。网上有人推测是OracleClient的BUG所致,理由是换用OracleDataAccess即可解决。

为什么说NHibernate将参数类型设置为OracleType.NVarChar呢?看下边

  1. 找到NHibernate的源代码,把它加入你的工程。记得不要移动NHibernate位置直接加入工程,直接在NHibernate的安装目录引用进来。

2. 在Test解决方案中添加NHibernate的项目引用。

经过上边两个步骤我们就可以跟踪调试NHibernate了

  1. 跟踪代码session.Save(xx);看看它究竟做了啥。

当我们跟进CommandSetBatchingBatcher时,可以得到以下信息(如图中的调试信息)。CurrentBatch类型是OracleClientCommandSet,OracleClientCommandSet看源码得知是对微软的OracleCommandSet的封装,因为这个类internal sealed class,所以我们的程序里是找不到这个类的,不过NHibernate通过反射使用了它的功能。OracleCommandSet可能用作批处理的,就是一次处理多个SQL语句的,不是太了解,谁知道请指教。

CommandSetBatchingBatcher的源码

  1. internal class OracleClientCommandSet : DbCommandSet<OracleConnection, OracleCommand>
  2. {
  3. private static System.Type oracleCmdSetType;
  4. static OracleClientCommandSet()
  5. {
  6. Assembly sysDataOracleClient = Assembly.Load("System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
  7. oracleCmdSetType = sysDataOracleClient.GetType("System.Data.OracleClient.OracleCommandSet");
  8. Debug.Assert(oracleCmdSetType != null, "Could not find OracleCommandSet!");
  9. }
  10. protected override object CreateInternalCommandSet()
  11. {
  12. return Activator.CreateInstance(oracleCmdSetType, true);
  13. }
  14. }

跟踪CurrentBatch可以看到

CommandText:

declare

type refcursortype is ref cursor;

begin

INSERT INTO z3 (test, id) VALUES (:p2, :p3);

:r1_4 := sql%rowcount;

end;

这里的p2就是我们的Clob类型字段的参数啦。

再看p2的OracleType是NVarChar,是不是有点明白啦,对了, 跟我们3一样,参数类型错掉了。

解决办法:

   使用NHibernate的自定义类型,不是太会,幸好网上有高人提供代码,在此想高人致谢。这样我们通过自定义类型来设置正确的OracleType即可。在项目中添加两个类。

   PatchForOracleLobField.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Text;
  5. using NHibernate;
  6. using NHibernate.SqlTypes;
  7. using NHibernate.UserTypes;
  8. namespace Test.type
  9. {
  10. public abstract class PatchForOracleLobField : IUserType
  11. {
  12. public PatchForOracleLobField()
  13. {
  14. }
  15. public bool IsMutable
  16. {
  17. get { return true; }
  18. }
  19. public System.Type ReturnedType
  20. {
  21. get { return typeof(String); }
  22. }
  23. public SqlType[] SqlTypes
  24. {
  25. get
  26. {
  27. return new SqlType[] { NHibernateUtil.String.SqlType };
  28. }
  29. }
  30. public object DeepCopy(object value)
  31. {
  32. return value;
  33. }
  34. public new bool Equals(object x, object y)
  35. {
  36. return x == y;
  37. }
  38. public int GetHashCode(object x)
  39. {
  40. return x.GetHashCode();
  41. }
  42. public object Assemble(object cached, object owner)
  43. {
  44. return DeepCopy(cached);
  45. }
  46. public object Disassemble(object value)
  47. {
  48. return DeepCopy(value);
  49. }
  50. public object NullSafeGet(IDataReader rs, string[] names, object owner)
  51. {
  52. return NHibernate.NHibernateUtil.StringClob.NullSafeGet(rs, names[0]);
  53. }
  54. public abstract void NullSafeSet(IDbCommand cmd, object value, int index);
  55. public object Replace(object original, object target, object owner)
  56. {
  57. return original;
  58. }
  59. }
  60. }

OracleClobField.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.OracleClient;
  5. using System.Text;
  6. namespace Test.type
  7. {
  8.     public class OracleClobField : PatchForOracleLobField
  9.     {
  10.         public override void NullSafeSet(IDbCommand cmd, object value, int index)
  11.         {
  12.             if (cmd is OracleCommand)
  13.             {
  14.                 //CLob、NClob类型的字段,存入中文时参数的OracleDbType必须设置为OracleDbType.Clob
  15.                 //否则会变成乱码(Oracle 10g client环境)
  16.                 OracleParameter param = cmd.Parameters[index] as OracleParameter;
  17.                 if (param != null)
  18.                 {
  19.                     param.OracleType = OracleType.Clob;// 关键就这里啦
  20.                     param.IsNullable = true;
  21.                 }
  22.             }
  23.             NHibernate.NHibernateUtil.StringClob.NullSafeSet(cmd, value, index);
  24.         }
  25.     }
  26. }

然后在映射文件中修改类型即可。

Com.Dic.Icqs.Entities.Type.OracleClobField,Com.Dic.Icqs.Entities

修改前:

<property column="test" type="StringClob" name="Test" length="2147483647" />

修改后:

<property column="test" type="Test.type.OracleClobField, Test " name="Test" length="2147483647" />

Test.type.OracleClobField是类的完整名,Test 即OracleClobField所在的程序集。

问题:oracle CLOB类型;结果:oracle中Blob和Clob类型的区别的更多相关文章

  1. Oracle中Blob和Clob类型的区别与操作

    Oracle中Blob和Clob类型 1.Oracle中Blob和Clob类型的区别 BLOB和CLOB都是大字段类型,BLOB是按二进制来存储的,而CLOB是可以直接存储文字的.其实两个是可以互换的 ...

  2. oracle中Blob、Clob、Varchar之间的互相转换

    以下是oracle中Blob.Clob.Varchar之间的互相转换(都是百度找的,亲测可用) Blob转Varchar2: CREATE OR REPLACE FUNCTION blob_to_va ...

  3. Oracle列信息表 all&lowbar;tab&lowbar;columns中的data&lowbar;length和data&lowbar;precision字段区别

    Oracle列信息表 all_tab_columns中的data_length和data_precision字段区别 区别: 这两个属性都属于user_tab_columns视图,他们的含义:1,da ...

  4. oracle中Blob和Clob类型的区别

    BLOB和CLOB都是大字段类型,BLOB是按二进制来存储的,而CLOB是可以直接存储文字的.其实两个是可以互换的的,或者可以直接用LOB字段代替这两个.但是为了更好的管理ORACLE数据库,通常像图 ...

  5. Hibernate or JPA Annotation中BLOB、CLOB注解写法

    BLOB和CLOB都是大字段类型,BLOB是按二进制字节码来存储的,而CLOB是可以直接存储字符串的. 在hibernate or JPA Annotation中,实体BLOB.CLOB类型的注解与普 ...

  6. SQL数据库中字段类型 与C&num;中的对应字段类型

    数据库中的字段类型和对应的C#中的对应字段类型 数据库                 C#程序int int32text stringbigint int64binary System.Byte[] ...

  7. Oracle中Blob和Clob

    http://www.cnblogs.com/ztf2008/archive/2009/05/16/1458432.html Blob是指二进制大对象也就是英文Binary Large Object的 ...

  8. 向数据库中插入一个DateTime类型的数据到一个Date类型的字段中,需要转换类型。TO&lowbar;DATE&lpar;&&num;39&semi;&lbrace;0&rcub;&&num;39&semi;&comma;&&num;39&semi;YYYY-MM-DD&&num;39&semi;&rpar;&rpar;

    需要指出的是,C#中有datetime类型,但是这个类型是包括小时,分钟,秒的.这个格式与数据库中的Date类型不符,如果将now设为datetime类型插入数据会失败. 需要通过TO_DATE('字 ...

  9. Blob和Clob在JDBC中的简介

    数据库在当今的应用越来越广泛了,同样伴随着领域的广泛,存储的内容也不在是只有数值.字符.boolean几种类型,而是越来越多样化.在这样的前提下就出现了Blob和Clob两个类型.下面我将对这个两个类 ...

随机推荐

  1. Scalaz(54)- scalaz-stream&colon; 函数式多线程编程模式-Free Streaming Programming Model

    长久以来,函数式编程模式都被认为是一种学术研究用或教学实验用的编程模式.直到近几年由于大数据和多核CPU的兴起造成了函数式编程模式在一些实际大型应用中的出现,这才逐渐改变了人们对函数式编程无用论的观点 ...

  2. 【JQGRID DOCUMENTATION】&period;学习笔记&period;1&period;安装jqGrid

    前面介绍了怎么使用其MVC方式,很好用.不过,觉得还是只使用前段比较好. 1.1 如何安装 到http://www.trirand.com/blog/?page_id=6 下载. </html& ...

  3. 33-Url辅助方法

    Url辅助方法与HTML辅助方法很类似,HTML辅助方法用来产生HTML标签,而Url辅助方法则负责用来产生Url网址. @Url.Action("About") 最后的输出网址如 ...

  4. 如何测量一个嵌入式Linux系统的功耗&sol;power dissipation&sol;power wastage&sol;consumption

    参考: 1.Linux Circuit Software To Calculate Power Dissipation

  5. HBase集群安装部署

    0x01 软件环境 OS: CentOS6.5 x64 java: jdk1.8.0_111 hadoop: hadoop-2.5.2 hbase: hbase-0.98.24 0x02 集群概况 I ...

  6. DAY13、迭代器,生成器,枚举

    一.迭代器 1.通过迭代器取值的优缺点 优点:不依赖索引取值,完成取值 缺点:不能计算长度,不能指定位取值(只能从前往后逐一取值) 2.可迭代对象 可迭代对象是有—iter—()方法的对象,调用该方法 ...

  7. mac 下安装ES 与 Head插件 以及安装Kibana

    一.安装Elasticsearch 在Mac上可以使用brew快速安装Elasticsearch brew install elasticsearch 安装完成后可使用elasticsearch -- ...

  8. 一个小框架,基于rx&lowbar;retrofit2&lowbar;mvp

    离职在即,也没什么事情做,就鼓捣了一下.任意搭建了一个小框架,看看以后能不能搞出自己的一个model,好了.不说别的,上代码 1,先上依赖库 compile 'io.reactivex:rxandro ...

  9. 笔试算法题(06):最大连续子数组和 &amp&semi; 二叉树路径和值

    出题:预先输入一个整型数组,数组中有正数也有负数:数组中连续一个或者多个整数组成一个子数组,每个子数组有一个和:求所有子数组中和的最大值,要求时间复杂度O(n): 分析: 时间复杂度为线性表明只允许一 ...

  10. c语言和c&plus;&plus;的交换函数

    #include<iostream> using namespace std; namespace LiuGang{//在命名空间中写函数 void swap(int&aa,int ...