问题:oracle CLOB类型;结果:oracle中Blob和Clob类型的区别
BLOB和CLOB都是大字段类型,BLOB是按二进制来存储的,而CLOB是可以直接存储文字的。其实两个是可以互换的的,或者可以直接用LOB字段代替这两个。
但是为了更好的管理ORACLE数据库,通常像图片、文件、音乐等信息就用BLOB字段来存储,先将文件转为二进制再存储进去。而像文章或者是较长的文字,
就用CLOB存储,这样对以后的查询更新存储等操作都提供很大的方便。
Oracle中Clob类型处理解析
准备
系统环境 xp+.net2.0+oracle9i
表结构(由于是测试,表结构随便建了一张) XX
|
字段名 |
类型 |
|
ID |
VARCHAR2(70) |
|
TEST |
CLOB |
测试
方式1:直接将CLOB的值拼写在SQL语句中。
代码:
- string id = Guid.NewGuid().ToString();
- OracleCommand cmd = Conn.CreateCommand();
- cmd.CommandText = "insert into xx(id,test) values('" + id + "','" + data + "')";// data是一个变量,存储你要插入的字符串
- cmd.ExecuteNonQuery();
情况分析:
当data的长度大于4000时报错(ORA-01704:文字字符串过长),小于或等于4000时正常插入。
原因分析:
之所以会出现长度大于4000时报错,是因为Oracle中有SQL语句中两个单引号之间的字符数不能大于4000的限制。'" + data + "' data在sql语句之间,当data的值大于4000个字节时就会报错。
解决办法:
这种方式比较棘手,但有更好的方式,下边会讲到。
方式2:采用参数形式。
代码:
- string id = Guid.NewGuid().ToString();
- OracleCommand cmd = Conn.CreateCommand();
- cmd.CommandText = "insert into xx(id,test) values('" + id + "',:p1)";
- OracleParameter p1 = new OracleParameter("p1", OracleType.Clob);
- p1.Value = data; // data是一个变量,存储你要插入的字符串
- cmd.Parameters.Add(p1);
- cmd.ExecuteNonQuery();
情况分析:
采用这种方式能够正常插入。所以推荐用这种方式。
原因分析:
无
解决办法:
无
方式3:采用参数形式,但是参数类型写为OracleType. NVarChar
代码:
- string id = Guid.NewGuid().ToString();
- OracleCommand cmd = Conn.CreateCommand();
- cmd.CommandText = "insert into xx(id,test) values('" + id + "',:p1)";
- OracleParameter p1 = new OracleParameter("p1", OracleType. NVarChar);
- p1.Value = data; // data是一个变量,存储你要插入的字符串
- cmd.Parameters.Add(p1);
- 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
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace Test.Enties
- {
- [Serializable]
- public class Xx
- {
- public Xx()
- {
- }
- private string id;
- public virtual string Id
- {
- get { return id; }
- set { id = value; }
- }
- public virtual string Test
- {
- get { return test; }
- set { test = value; }
- }
- private string test;
- }
- }
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
代码:
- string id = Guid.NewGuid().ToString();
- Xx xx = new Xx();
- xx.Test = data; // data是一个变量,存储你要插入的字符串
- xx.Id = id;
- ISession session = SessionFactory.OpenSession();
- session.Save(xx);
- 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呢?看下边
- 找到NHibernate的源代码,把它加入你的工程。记得不要移动NHibernate位置直接加入工程,直接在NHibernate的安装目录引用进来。
2. 在Test解决方案中添加NHibernate的项目引用。
经过上边两个步骤我们就可以跟踪调试NHibernate了
- 跟踪代码session.Save(xx);看看它究竟做了啥。
当我们跟进CommandSetBatchingBatcher时,可以得到以下信息(如图中的调试信息)。CurrentBatch类型是OracleClientCommandSet,OracleClientCommandSet看源码得知是对微软的OracleCommandSet的封装,因为这个类internal sealed class,所以我们的程序里是找不到这个类的,不过NHibernate通过反射使用了它的功能。OracleCommandSet可能用作批处理的,就是一次处理多个SQL语句的,不是太了解,谁知道请指教。
CommandSetBatchingBatcher的源码
- internal class OracleClientCommandSet : DbCommandSet<OracleConnection, OracleCommand>
- {
- private static System.Type oracleCmdSetType;
- static OracleClientCommandSet()
- {
- Assembly sysDataOracleClient = Assembly.Load("System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
- oracleCmdSetType = sysDataOracleClient.GetType("System.Data.OracleClient.OracleCommandSet");
- Debug.Assert(oracleCmdSetType != null, "Could not find OracleCommandSet!");
- }
- protected override object CreateInternalCommandSet()
- {
- return Activator.CreateInstance(oracleCmdSetType, true);
- }
- }
跟踪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
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Text;
- using NHibernate;
- using NHibernate.SqlTypes;
- using NHibernate.UserTypes;
- namespace Test.type
- {
- public abstract class PatchForOracleLobField : IUserType
- {
- public PatchForOracleLobField()
- {
- }
- public bool IsMutable
- {
- get { return true; }
- }
- public System.Type ReturnedType
- {
- get { return typeof(String); }
- }
- public SqlType[] SqlTypes
- {
- get
- {
- return new SqlType[] { NHibernateUtil.String.SqlType };
- }
- }
- public object DeepCopy(object value)
- {
- return value;
- }
- public new bool Equals(object x, object y)
- {
- return x == y;
- }
- public int GetHashCode(object x)
- {
- return x.GetHashCode();
- }
- public object Assemble(object cached, object owner)
- {
- return DeepCopy(cached);
- }
- public object Disassemble(object value)
- {
- return DeepCopy(value);
- }
- public object NullSafeGet(IDataReader rs, string[] names, object owner)
- {
- return NHibernate.NHibernateUtil.StringClob.NullSafeGet(rs, names[0]);
- }
- public abstract void NullSafeSet(IDbCommand cmd, object value, int index);
- public object Replace(object original, object target, object owner)
- {
- return original;
- }
- }
- }
OracleClobField.cs
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Data.OracleClient;
- using System.Text;
- namespace Test.type
- {
- public class OracleClobField : PatchForOracleLobField
- {
- public override void NullSafeSet(IDbCommand cmd, object value, int index)
- {
- if (cmd is OracleCommand)
- {
- //CLob、NClob类型的字段,存入中文时参数的OracleDbType必须设置为OracleDbType.Clob
- //否则会变成乱码(Oracle 10g client环境)
- OracleParameter param = cmd.Parameters[index] as OracleParameter;
- if (param != null)
- {
- param.OracleType = OracleType.Clob;// 关键就这里啦
- param.IsNullable = true;
- }
- }
- NHibernate.NHibernateUtil.StringClob.NullSafeSet(cmd, value, index);
- }
- }
- }
然后在映射文件中修改类型即可。
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类型的区别的更多相关文章
- Oracle中Blob和Clob类型的区别与操作
Oracle中Blob和Clob类型 1.Oracle中Blob和Clob类型的区别 BLOB和CLOB都是大字段类型,BLOB是按二进制来存储的,而CLOB是可以直接存储文字的.其实两个是可以互换的 ...
- oracle中Blob、Clob、Varchar之间的互相转换
以下是oracle中Blob.Clob.Varchar之间的互相转换(都是百度找的,亲测可用) Blob转Varchar2: CREATE OR REPLACE FUNCTION blob_to_va ...
- Oracle列信息表 all_tab_columns中的data_length和data_precision字段区别
Oracle列信息表 all_tab_columns中的data_length和data_precision字段区别 区别: 这两个属性都属于user_tab_columns视图,他们的含义:1,da ...
- oracle中Blob和Clob类型的区别
BLOB和CLOB都是大字段类型,BLOB是按二进制来存储的,而CLOB是可以直接存储文字的.其实两个是可以互换的的,或者可以直接用LOB字段代替这两个.但是为了更好的管理ORACLE数据库,通常像图 ...
- Hibernate or JPA Annotation中BLOB、CLOB注解写法
BLOB和CLOB都是大字段类型,BLOB是按二进制字节码来存储的,而CLOB是可以直接存储字符串的. 在hibernate or JPA Annotation中,实体BLOB.CLOB类型的注解与普 ...
- SQL数据库中字段类型 与C#中的对应字段类型
数据库中的字段类型和对应的C#中的对应字段类型 数据库 C#程序int int32text stringbigint int64binary System.Byte[] ...
- Oracle中Blob和Clob
http://www.cnblogs.com/ztf2008/archive/2009/05/16/1458432.html Blob是指二进制大对象也就是英文Binary Large Object的 ...
- 向数据库中插入一个DateTime类型的数据到一个Date类型的字段中,需要转换类型。TO_DATE('{0}','YYYY-MM-DD'))
需要指出的是,C#中有datetime类型,但是这个类型是包括小时,分钟,秒的.这个格式与数据库中的Date类型不符,如果将now设为datetime类型插入数据会失败. 需要通过TO_DATE('字 ...
- Blob和Clob在JDBC中的简介
数据库在当今的应用越来越广泛了,同样伴随着领域的广泛,存储的内容也不在是只有数值.字符.boolean几种类型,而是越来越多样化.在这样的前提下就出现了Blob和Clob两个类型.下面我将对这个两个类 ...
随机推荐
- HDU 5925 离散化
东北赛的一道二等奖题 当时学长想了一个dfs的解法并且通过了 那时自己也有一个bfs的解法没有拿出来 一直没有机会和时ji间xing来验证对错 昨天和队友谈离散化的时候想到了 于是用当时的思路做了一下 ...
- Node.js初接触(一)
本来还在纠结着到底要学哪一种后台语言呢,突然发现node.js很火,既然能被这么多人推崇,自然是有他的优势的.去百度百科看了一眼,或许是我理解能力太差,并没有了解到很多关于node.js的东西,大概就 ...
- MVC3 ajax功能
微软mvc3框架的项目使用微软自带的ajax 必须引用下面 <script src="/Scripts/jquery.unobtrusive-ajax.js" type=&q ...
- C#下利用正则表达式实现字符串搜索功能的方法(转)
关键字:正则表达式.元字符.字符串.匹配: 1.正则表达式简介:正则表达式提供了功能强大.灵活而又高效的方法来处:.NET框架正则表达式并入了其他正则表达式实现的: 2.字符串搜索:正则表达式语言由两 ...
- 总结一下内核DEBUG中的dump_stack, BUG, BUG_ON以及panic
有点空闲时间,让我们来总结一下内核DEBUG中的各个语句吧.随便找个内核驱动,在init函数里面加入如下代码测试: u8 a = 1, b = 0; printk("----------du ...
- linux查看网卡速度
ethtool eth0 会包含速度模式等各项属性信息 lspci|grep -i ether 可以查看硬件设备具体型号,会包含硬件厂商及信息 dmesg |grep -i eth 会显示系统 ...
- Element 'beans' cannot have character [children], because the type's content type is element-only
这个小问题快搞死我了,找了大半个小时. Element 'beans' cannot have character [children], because the type's content typ ...
- SDK中常用的工具
Android SDK包含了各种各样的定制工具,简介如下: 一.Android模拟器(Android Emulator )它是在你的计算机上运行的一个虚拟移动设备.你可以使用模拟器来在一个实际的And ...
- 面试题42:翻转单词顺序VS左旋转字符串
题目一:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变.为简单起见,标点符号和普通字母一样处理. 例如输入字符串“I am a student.",则输出"stud ...
- redis有序集合的使用
Redis 有序集合(sorted set) Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过 ...