ORACLE中CLOB介绍及使用

article/2025/7/9 3:03:36

一、Oracle中的varchar2类型

我们在Oracle数据库存储的字符数据一般是用VARCHAR2。VARCHAR2既分PL/SQL Data Types中的变量类型,也分Oracle Database中的字段类型,不同场景的最大长度不同。

在Oracle Database中,VARCHAR2 字段类型,最大值为4000;PL/SQL中 VARCHAR2 变量类型,最大字节长度为32767。

当 VARCHAR2 容纳不下我们需要存储的信息时,就出来的Oracle的大数据类型LOB( Large Object,大型对象)。

二、Oarcle中的LOB类型

在Oracle中,LOB(Large Object,大型对象)类型的字段现在用得越来越多了。因为这种类型的字段,容量大(最多能容纳4GB的数据),且一个表中可以有多个这种类型的字段,很灵活,适用于数据量非常大的业务领域(如图象、档案等)。

LOB类型分为BLOB和CLOB两种:BLOB即二进制大型对象(Binary Large Object),适用于存贮非文本的字节流数据(如程序、图象、影音等)。

而CLOB,即字符型大型对象(Character Large Object),则与字符集相关,适于存贮文本型的数据(如历史档案、大部头著作等)。

三、DB中使用CLOB类型字段

(一)、创建表(使用sql或者直接在PL/SQL客户端创建),字段类型CLOB

-- Create table
create table TEMP
(name   VARCHAR2(200),age    NUMBER,temp_clob CLOB
)
tablespace INSIGHTDATA3_TSpctfree 10initrans 1maxtrans 255storage(initial 160Knext 1Mminextents 1maxextents unlimited);

(二)、增删改查

先看一下使用普通方式操作CLOB类型:

SELECT t.name, t.temp_clob FROM temp t; --普通查询 INSERT INTO temp t VALUES ('Grand.Jon', 22, '数据内容');

查询因为不是varchar2类型,所以普通查询看不到CLOB类型的字段内容,结果如下

 

而普通插入操作也会因为Oracle的隐式转换,默认把字符串转换成varchar2类型,一旦字符串内容超过varchar2的最大限度就会报会报ora-01704(字符串太长)错误。

正确操作

--使用PL/SQL语法,采取绑定变量的方式解决,而不是直接拼接SQL
DECLAREV_LANG CLOB := '待插入的海量字符串';V_UPDATE CLOB := '更新的海量字符串';
BEGININSERT INTO temp t VALUES ('Grand.Jon', 22, V_LANG);    --增加UPDATE temp t SET t.temp_clob = V_UPDATE WHERE rownum = 1; --修改SELECT t.NAME, dbms_lob.substr(t.temp_clob) FROM TEMP t;  --查询  将CLOB转成字符类型DELETE temp t WHERE rownum = 1;               --按列删除  COMMIT;
END;
/

对CLOB的操作我们在存储过程中基本上使用 dbms_lob 中 substr , append , write 等方法。

dbms_lob 方法总结

dbms_lob.createtemporary(V_SQL,true);   --创建一个临时clob,用来存储拼接的sql
dbms_lob.write(v_SQL,'写入信息');     --写入操作
dbms_lob.append(v_SQL,',');        --拼接clob
dbms_lob.substr(v_SQL);          --截取clob,不传参数就是全部读取
dbms_lob.freetemporary(v_SQL);      --释放clob

查询结果如下:

四、在存储过程中使用CLOB类型实例

  需求:以开发的存储过程为例,需要循环遍历时间范围拼接sql,将时间日期按列反转(pivot),如果时间太长(1年以上)sql语句(varchar2)就会超出范围报错,这时候就需要使用CLOB来存储拼接的sql。

PROCEDURE P_AND_CPT_RATIOOTH_APP_BAK2_N(V_APPIDS IN VARCHAR2,V_TYPE IN VARCHAR2,V_CHANNEL IN VARCHAR2,V_TABLE IN VARCHAR2,V_START IN VARCHAR2,V_END IN VARCHAR2,RESULT OUT mycursor
) IS
V_SQL CLOB;
V_SQLWHERE VARCHAR2(32767) default '';
V_SQLWHERE_CHANNEL VARCHAR2(32767) default '';
V_SQL_DATES CLOB;
V_Sdate DATE;
V_Edate DATE;
V_TABLE_DATE VARCHAR2(50);
V_TABLE_TYPE VARCHAR2(50);
V_START_DATE VARCHAR2(50);
V_END_DATE  VARCHAR2(50);
V_DAY VARCHAR2(50);
BEGINselect column_name into V_TABLE_DATE from user_tab_columns where table_name=''||V_TABLE||'' and column_id=1;select column_name into V_TABLE_TYPE from user_tab_columns where table_name=''||V_TABLE||'' and column_id=5;dbms_lob.createtemporary(V_SQL,true);--创建一个临时lobdbms_lob.createtemporary(V_SQL_DATES,true);--创建一个临时lobIF V_APPIDS is NOT NULL THENV_SQLWHERE := 'AND t.appid in ('||V_APPIDS||')';END IF;IF V_CHANNEL IS NOT NULL THENV_SQLWHERE_CHANNEL := 'AND t.channel = '''||V_CHANNEL||'''';END IF;IF V_TABLE_DATE = 'MON' THENV_START_DATE := SUBSTR(V_START,0,6);V_END_DATE := SUBSTR(V_END,0,6);v_sdate := to_date(V_START_DATE, 'yyyymm');v_edate := to_date(V_END_DATE, 'yyyymm');WHILE (v_sdate <= v_edate) LOOPdbms_lob.append(v_SQL_DATES,to_char(v_sdate, 'yyyymm'));--把临时字符串付给v_strIF v_sdate != v_edate THENdbms_lob.append(v_SQL_DATES,',');--把临时字符串付给v_strEND IF;v_sdate := add_months(v_sdate,1);END LOOP;ELSE --周和日 类型 都是 DAYv_sdate := to_date(V_START, 'yyyymmdd');v_edate := to_date(V_END, 'yyyymmdd');V_END_DATE := V_END;IF SUBSTR(V_TYPE,0,1)='d' THENV_START_DATE := to_char(v_sdate, 'yyyymmdd');WHILE (v_sdate <= v_edate) LOOPdbms_lob.append(v_SQL_DATES,to_char(v_sdate, 'yyyymmdd'));--把临时字符串付给v_strIF v_sdate != v_edate THENdbms_lob.append(v_SQL_DATES,',');--把临时字符串付给v_strEND IF;v_sdate := v_sdate+1;END LOOP;ELSIF SUBSTR(V_TYPE,0,1)='w' THENselect to_char(V_Sdate,'d') INTO V_DAY from dual;IF V_DAY!=2 THENV_Sdate:=V_Sdate-7;END IF;V_START_DATE := to_char(v_sdate, 'yyyymmdd');WHILE (v_sdate <= v_edate) LOOPselect to_char(V_Sdate,'d') INTO V_DAY from dual;IF V_DAY=2 THENdbms_lob.append(v_SQL_DATES,to_char(v_sdate, 'yyyymmdd'));--把临时字符串付给v_strIF V_Edate-v_sdate >7 THENdbms_lob.append(v_SQL_DATES,',');--把临时字符串付给v_strEND IF;END IF;v_sdate := v_sdate+1;END LOOP;END IF;END IF;dbms_lob.append(v_sql,'SELECT * FROM( SELECT *FROM '||V_TABLE||' tWHERE t.'||V_TABLE_TYPE||' = '''||V_TYPE||'''AND t.'||V_TABLE_DATE||' >= '''||V_START_DATE||'''AND t.'||V_TABLE_DATE||' <= '''||V_END_DATE||''''||V_SQLWHERE||'     '||V_SQLWHERE_CHANNEL||' ) t1pivot(sum(MARKETSHARE)for '||V_TABLE_DATE||' in(');dbms_lob.append(v_sql,v_SQL_DATES);dbms_lob.append(v_sql,'))');dbms_output.put_line(v_sql);   OPEN result FOR v_sql;  dbms_lob.freetemporary(v_sql);--释放lobdbms_lob.freetemporary(v_SQL_DATES);--释放lob--dbms_output.put_line(V_SQLDATE);-- dbms_output.put_line(v_SQL_DATES);
--记录操作日志及错误日志
END;

五、使用Java开发操作CLOB字段

(一)、原生JDBC处理CLOB类型

增加,一般会插入一个空的clob到数据库对应的字段,然后锁定该列,用Write将待插入字符串写入进去。

      重点:这两步操作要放在同一个事务里面。具体增加的方法如下:

public boolean save(Article article){boolean result = true;Connection conn = ConnectionUntils.getInstance();String sql = "insert into temp values(?,?,empty_clob())";//锁住该列,防止并发写入时候该字段同时被多次写入造成错误String sqlClob = "select temp_clob from temp t where t.name=? for update";PreparedStatement pst =null;ResultSet rs = null;Writer writer = null;try {conn.setAutoCommit(false);//设置不自动提交,开启事务pst = conn.prepareStatement(sql);pst.setString(1,article.getName());pst.setString(2,article.getAge());pst.executeUpdate();pst= conn.prepareStatement(sqlClob);pst.setInt(1, article.getId());rs = pst.executeQuery();CLOB clob = null;if(rs.next()){try {clob = (CLOB) rs.getClob(1);writer = clob.getCharacterOutputStream(); //拿到clob的字符输入流writer.write(article.getContent());writer.flush();writer.close();} catch (IOException e) {e.printStackTrace();}}conn.commit();} catch (SQLException e) {result = false;try {conn.rollback();//当commit或者rollback后会自动释放该列的锁定} catch (SQLException e1) {e1.printStackTrace();}e.printStackTrace();} finally {conn.setAutoCommit(true);//还原ConnectionUntils.close(rs, pst, conn);}return result;}

update操作,update时候主要利用PreparedStatement的setClob方法:

public boolean update(String name,String content){int result = 0;Connection conn = ConnectionUntils.getInstance();String sql = "update temp set temp_clob=? where name=?";PreparedStatement pst =null;try {CLOB clob  = oracle.sql.CLOB.createTemporary(conn, false,oracle.sql.CLOB.DURATION_SESSION);clob.setString(1L, content);pst = conn.prepareStatement(sql);pst.setClob(1, clob);pst.setString(2,name);result = pst.executeUpdate();} catch (SQLException e) {e.printStackTrace();}finally{ConnectionUntils.close(null, pst, conn);}if(result==0)return false;return true;}

查询就主要是从结果集ResultSet中定位到对应的字段后,往外读:

public Article select(String name){Article article = new Article();Connection conn = ConnectionUntils.getInstance();String sql = "select name,age,temp_clog from temp where name = ?";PreparedStatement pst =null;ResultSet rs = null;try {pst = conn.prepareStatement(sql);pst.setInt(1,id);rs = pst.executeQuery();StringBuilder builder = new StringBuilder();if(rs.next()){Clob clob = rs.getClob("temp_clog");Reader rd = clob.getCharacterStream();char [] str = new char[12];while(rd.read(str) != -1) {builder.append(new String(str));}article.setContent(builder.toString());article.setName(rs.getString("name"));article.setAge(rs.getInt("age"));}} catch (SQLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally{ConnectionUntils.close(rs, pst, conn);}return article;}

(二)、Hibernate、Mybatis框架操作

这个因为框架都封装集成好了,所以我们使用的时候直接配置变量的类型为CLOB就可以。

  譬如:Mybatis

<result column="temp_clob" property="content" jdbcType="Clob" typeHandler="org.apache.ibatis.type.ClobTypeHandler"/>

 貌似Hibernate5内部做了对应的处理,可以直接当string类型一样处理即可。


http://chatgpt.dhexx.cn/article/7DkhkySF.shtml

相关文章

clob类型(数据库clob类型)

如何获取clob类型的字节长度 blob和clob最大是多少&#xff1f;还是没有最大限制&#xff1f;它们的最大上限就是4G&#xff0c;Clob可以存储单字节字符数据&#xff0c;Blob可以存储无结构的二进制数据 Oracle中Clob类型如何处理&#xff1f; string id Guid。NewGuid()。ToS…

CRC校验方法的实现

1&#xff0c;确定收发双方所使用的校验位数(由收发双方自定义) 如1个字节的为CRC-8校验&#xff0c;2字节为CRC-16校验&#xff0c;4字节为CRC-32校验。 2&#xff0c;确定除数(生成多项式) 根据校验字节数&#xff0c;确定某个除数G(x)&#xff0c;这个除数一般以二进制形式…

【Verilog】CRC校验码生成器原理及verilog实现

目录 一、CRC的基本原理 二、CRC生成步骤 2.1举个栗子 三、Verilog实现 四、参考资料 4.1 CRC在线计算器 一、CRC的基本原理 CRC &#xff1a;Cyclic Redundancy Check循环冗余校验码 将被处理的报文比特序列当做一个二进制多项式A(x)的系数&#xff0c;任意一个由二进制…

CRC校验原理及其使用

目录 何为CRC 为什么需要校验 为什么是CRC CRC的缺点 目录 何为CRC 为什么需要校验 为什么是CRC CRC的缺点 如何进行CRC校验 校验标准式是什么玩意&#xff1f; 常见的CRC校验 CRC校验计算过程 CRC校验代码参考 代码解读 生成CRC8校验表的代码 CRC检验网站 如何…

FPGA校验(2):CRC校验

CRC:输入序列对某个表达式求余数&#xff0c;或者认为一系列数据求异或的过程。 CRC校验 CRC原理 CRC实现非常简单&#xff0c;但想要真正掌握CRC算法原理&#xff0c;就必须清楚地了解有限域的运算规则&#xff0c;知道CRC就是有限域中的除法余数&#xff0c;并且清楚如何将串…

crc校验c语言程序,C语言:CRC校验

一、CRC码 CRC:Cylic Reduancy check译作汉语就是循环冗余校验码。 二、XOR XOR:逻辑运算符异或,不知道用符号怎么写,总之其运算法则是,不同为1,相同为0。 三、用XOR代替算术运算上除法的两个例子。 1、10110010000/11001 第一次异或(相除),得到商为1,余数为1111,加入…

【Verilog】CRC 校验(二)用 Verilog 实现生成 CRC 校验码

目录 实验任务 CRC 生成 Verilog 实现 电路生成原理 模块设计图 CRC 生成时序图 具体代码实现 上板验证 实验任务 在上一篇介绍了 CRC 校验码的原理&#xff0c;如何计算 CRC 校验码&#xff0c;这篇介绍如何利用 Verilog 实现CRC 校验码的生成。 什么是 CRC 校验码&a…

CRC校验 - 基于FPGA的实现

CRC校验 - 基于FPGA的实现 0 背景 CRC即循环冗余校验&#xff1a;常用于数据通信领域中&#xff0c;通常由发送端添加校验码于单帧数据的尾部&#xff0c;并由接受方进行提取和校验该帧数据传输是否正确。 循环冗余检查&#xff08;CRC&#xff09;是一种数据传输检错功能&am…

CRC校验的原理及实现方法

一、CRC校验介绍 循环冗余校验码&#xff08;CRC&#xff09;&#xff0c;是一种常用的、具有检错、纠错能力的校验码&#xff0c;在早期的通信中运用广泛。循环冗余校验码常用于外存储器和计算机同步通信的数据校验。循环冗余校验是通过某种数学运算来建立数据位和校验位的约定…

C#编程,CRC校验原理

1.CRC简介 CRC全称循环冗余校验(Cyclic Redundancy Check&#xff0c; CRC)&#xff0c;是通信领域数据传输技术中常用的检错方法&#xff0c;用于保证数据传输的可靠性。网上有关这方面的博客和资料很多&#xff0c;本文尽量简洁的梳理一下它的原理。后面还会结合自己的实践经…

LabVIEW实现CRC校验

目录 1、内部控件计算CRC校验 2、公式节点计算CRC校验 CRC&#xff08;循环冗余校验&#xff09;&#xff0c;是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术&#xff0c;主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除…

CRC校验及C语言实现

摘自&#xff1a;CRC校验原理及其C语言实现 地址&#xff1a;https://blog.csdn.net/whik1194/article/details/108837493?spm1001.2014.3001.5502 目录 什么是校验算法CRC算法简介CRC参数模型CRC计算CRC校验CRC计算的C语言实现CRC计算工具总结 什么是校验算法 最近的工作中&…

SwitchHosts

SwitchHosts 官网&#xff1a;https://oldj.github.io/SwitchHosts/ 客户端支持 WindowsLinuxMac 功能支持 快速切换Hosts在线 hosts 方案Chrome浏览器Hosts实时生效 v3.3.12后将被支持&#xff0c;可暂时下载 https://github.com/CloverNet/SwitchHosts

Host服务

这也是看网上的例子自己跟着配置做的一个小demo&#xff0c;这里记录一下。 一、创建一个空的控制台应用程序 二、安装所需dll  1.Quartz     Install-Package Quartz -Version 2.3.3  2.Owin    Install-Package Owin -Version 1.0.0&#xff08;这个暂时装上&…

Go get http 服务

阅读目录 package mainimport ("encoding/json""fmt""net/http" )type MirageIPResponse struct {Code string json:"code"MirageIP string json:"MirageIp" }func main() {// 定义处理函数handler : func(w http.Respo…

google host地址

2019独角兽企业重金招聘Python工程师标准>>> http://git.oschina.net/AlexKing/host 保持更新中。。。 亲测通过&#xff0c;如果无法使用可以联系我&#xff0c;再做更新调整。 转载于:https://my.oschina.net/u/260921/blog/506286

virtio,vhost 和vhost-user

virtio 在虚拟机中&#xff0c;可以通过qemu模拟e1000网卡&#xff0c;这样的经典网卡一般各种客户操作系统都会提供inbox驱动&#xff0c;所以从兼容性上来看&#xff0c;使用类似e1000的模拟网卡是非常一个不错的选择。 但是&#xff0c;e1000网卡上也包含了复杂的io端口&a…

GO的服务

1.go的安装 1.1 确认版本go version go version go1.20.4 darwin/amd64 可以看到是macos10.14版本。如果是m1 需要安装对应的版本 1.2 用vscode 进行编写go的简单例子 先进入vscode的界面&#xff0c;新建一个目录为godemo&#xff0c;里面就是go的例子的工作目录&#xff0…

Go Registry

实现微服务的服务注册中心&#xff0c;支持服务服务注册、接收心跳等。客户端实现基于注册中心的服务发现机制 微服务 微服务是一些协同工作的小而自治的服务 微服务主要分为六个部分组成 服务描述&#xff1a;类似服务的文档说明&#xff0c;简单但不可或缺。 比如&#xff1a…

Gogs私服搭建

1. Gogs介绍 官网地址&#xff1a;https://gogs.io 文档地址&#xff1a;https://gogs.io/docs Gogs&#xff0c;全称为Go Git Service&#xff0c;是一个基于 Go 语言开发的Git服务。它提供了一个类似于GitHub的界面和功能&#xff0c;允许您在自己的服务器上搭建私有的Git仓库…