当前位置: 首页 > 科技观察

Oracle的CLOB大数据字段类型

时间:2023-03-13 12:25:41 科技观察

1、Oracle中的varchar2类型我们在Oracle数据库中存储的字符数据一般使用VARCHAR2。VARCHAR2在PL/SQLDataTypes中分为变量类型和OracleDatabase中的字段类型,不同场景最大长度不同。在Oracle数据库中,VARCHAR2字段类型,最大值为4000;PL/SQL中的VARCHAR2变量类型,最大字节长度为32767。当VARCHAR2不能容纳我们需要存储的信息时,Oracle的大数据类型LOB(LargeObject,大对象)就会出来。二、Oracle中的LOB类型在Oracle中,LOB(LargeObject,大对象)类型的字段现在使用的越来越多。由于该类型字段容量大(最多4GB数据),且一张表中可以有多个该类型字段,非常灵活,适用于数据量非常大的业务领域(如图片、文件等)等)等等)。LOB类型分为BLOB和CLOB两种:BLOB是二进制大对象(BinaryLargeObject),适用于存储非文本字节流数据(如程序、图像、音视频等).CLOB,即CharacterLargeObject,与字符集有关,适用于存储文本类型的数据(如历史文件、大部头等)。3.在DB中使用CLOB类型的字段(一),建表(使用sql或者直接在PL/SQL客户端创建),字段类型CLOB--CreatetablecreatetableTEMP(nameVARCHAR2(200),ageNUMBER,temp_clobCLOB)tablespaceINSIGHTDATA3_TSpctfree10initrans1maxtrans255storage(initial160Knext1Mminextents1maxextentsstorage(unlimited)2)增删改查首先看一下常见的操作CLOB类型的方式:SELECTt.name,t.temp_clobFROMtempt;--普通查询INSERTINTOtemptVALUES('Grand.Jon',22,'加入博客园The***day');因为查询的不是varchar2类型,所以普通查询看不到CLOB类型的字段内容,结果如下。由于Oracle的隐式转换,普通的insert操作也会默认将string转换为varchar2类型。一旦字符串内容超过了varchar2的最大限制,就会报ora-01704(字符串太长)错误。正确操作--使用PL/SQL语法,通过绑定变量解决,而不是直接拼接SQLDECLAREV_LANGCLOB:='待插入的海量字符串';V_UPDATECLOB:='待更新的海量字符串';BEGININSERTINTOtemptVALUES('Grand.Jon',22,V_LANG);--添加UPDATEtemptSETt.temp_clob=V_UPDATEWHERErownum=1;--修改SELECTt.NAME,dbms_lob.substr(t.temp_clob)FROMTEMPt;--查询  将CLOB转为字符类型DELETEtemptWHERErownum=1;--删除bycolumn  COMMIT;END;/对CLOB的操作我们在存储过程中基本使用dbms_lob中的substr、append、write等方法。dbms_lob方法总结dbms_lob.createtemporary(V_SQL,true);--创建临时clob存储拼接后的sqldbms_lob.write(v_SQL,'writeinformation');--写操作dbms_lob.append(v_SQL,',');--拼接clobdbms_lob.substr(v_SQL);--拦截clob,读取所有dbms_lob.freetemporary(v_SQL),不传参;--释放clob查询结果如下:4.在存储过程中使用CLOB类型实例要求:以以开发的存储过程为例,需要循环遍历时间范围拼接sql,按列(pivot)反转时间和日期。如果时间过长(超过1年),sql语句(varchar2)会超出范围,报错。有时需要使用CLOB来存储拼接后的sql。PROCEDUREP_AND_CPT_RATIOOTH_APP_BAK2_N(V_APPIDSINVARCHAR2,V_TYPEINVARCHAR2,V_CHANNELINVARCHAR2,V_TABLEINVARCHAR2,V_STARTINVARCHAR2,V_ENDINVARCHAR2,RESULTOUTmycursor)ISV_SQLCLOB;V_SQLWHEREVARCHAR2(32767)default'';V_SQLWHERE_CHANNELVARCHAR2(32767)default'';V_SQL_DATESCLOB;V_SdateDATE;V_EdateDATE;V_TABLE_DATEVARCHAR2(50);V_TABLE_TYPEVARCHAR2(50);V_START_DATEVARCHAR2(50);V_END_DATEVARCHAR2(50);V_DAYVARCHAR2(50);BEGINselectcolumn_nameintoV_TABLE_DATEfromuser_tab_columnswheretable_name=''||V_TABLE||''andcolumn_id=1;selectcolumn_nameintoV_TABLE_TYPEfromuser_tab_columnswheretable_name=''||V_TABLE||''andcolumn_id=5;dbms_lob.createtemporary(V_SQL,true);--创建一个临时lobdbms_lob.createtemporary(V_SQL_DATES,true);--创建一个临时lobIFV_APPIDSisNOTNULLTHENV_SQLWHERE:='ANDt.appidin('||V_APPIDS||')';ENDIF;IFV_CHANNELISNOTWHERE=CHENV_THENV='''||V_CHANNEL||'''';ENDIF;IFV_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'));--Paythetemporarystringtov_strIFv_sdate!=v_edateTHENdbms_lob.append(v_SQL_DATES,',');--Paythetemporarystringtov_strENDIF;v_sdate:=add_months(v_sdate,1);ENDLOOP;ELSE--星期和日类型都是DAYv_sdate:=to_date(V_START,'yyyymmdd');v_edate:=to_date(V_END,'yyyymmdd');V_END_DATE:=V_END;IFSUBSTR(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_strIFv_sdate!=v_edateTHENDdbms_lob.append(v_SQL_DATES,',');--支付临时字符串v_strENDIF;v_sdate:=v_sdate+1;ENDLOOP;ELSIFSUBSTR(V_TYPE,0,1)='w'THEN选择to_char(V_Sdate,'d')INTOV_DAYfromdual;IFV_DAY!=2THENV_Sdate:=V_Sdate-7;ENDIF;V_START_DATE:=to_char(v_sdate,'yyyymmdd');WHILE(v_sdate<=v_edate)LOOPselectto_char(V_Sdate,'d')INTOV_DAYfromdual;IFV_DAY=2THENDdbms_lob.append(v_SQL_DATES,to_char(v_sdate,'yyyymmdd'));--支付临时字符串到v_strIFV_Edate-v_sdate>7THENdbms_lob.append(v_SQL_DATES,',');--支付临时字符串到v_strENDIF;ENDIF;v_sdate:=v_sdate+1;ENDLOOP;ENDIF;ENDIF;dbms_lob.append(v_sql,'SELECT*FROM(SELECT*FROM'||V_TABLE||'tWHEREt.'||V_TABLE_TYPE||'='''||V_TYPE||'''ANDt.'||V_TABLE_DATE||'>='''||V_START_DATE||'''ANDt.'||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);OPENresultFORv_sql;dbms_lob.freetemporary(v_sql);--releaselobdbms_lob.freetemporary(v_SQL_DATES);--releaselob--dbms_output.put_line(V_SQLDATE);--dbms_output.put_line(v_SQL_DATES);--记录操作日志和错误日志END;5、使用Java开发和操作CLOB字段(一)。本机JDBC处理CLOB类型的添加。一般会在数据库的相应字段中插入一个空的clob,然后锁住该列,写入要插入的字符串,用Write回车关键点:这两步操作要放在同样的交易。具体增加方法如下:publicbooleansave(Articlearticle){booleanresult=true;Connectionconn=ConnectionUntils.getInstance();Stringsql="insertintotempvalues(?,?,empty_clob())";//锁定列,防止并发写入该字段同时写入多次导致报错自动提交,开启事务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();CLOBclob=null;if(rs.next()){try{clob=(CLOB)rs.getClob(1);writer=clob.getCharacterOutputStream();//获取clob的字符输入流writer.write(article.getContent());writer.flush();writer.close();}catch(IOExceptione){e.printStackTrace();}}conn.commit();}catch(SQLExceptione){result=false;try{conn.rollback();//commit或rollback后自动释放该列的锁}catch(SQLExceptione1){e1.printStackTrace();}e.printStackTrace();}finally{conn.setAutoCommit(true);//恢复ConnectionUntils.close(rs,pst,conn);}returnresult;}更新操作,更新时主要使用PreparedStatement的setClob方法:publicbooleanupdate(Stringname,Stringcontent){intresult=0;Connectionconn=ConnectionUntils.getInstance();Stringsql="updatetempsettemp_clob=?wherename=?";PreparedStatementpst=null;try{CLOBclob=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(SQLExceptione){e.printStackTrace();}finally{ConnectionUntils.close(null,pst,conn);}if(result==0)returnfalse;returntrue;}查询主要是从结果中定位到对应的字段setResultSet之后,读出:publicArticleselect(Stringname){Articlearticle=newArticle();Connectionconn=ConnectionUntils.getInstance();Stringsql="selectname,age,temp_clogfromtempwherename=?";PreparedStatementpst=null;ResultSetrs=null;尝试{pst=conn。准备状态nt(sql);pst.setInt(1,id);rs=pst.executeQuery();StringBuilderbuilder=newStringBuilder();if(rs.next()){Clobclob=rs.getClob("temp_clog");Readerrd=clob.getCharacterStream();char[]str=newchar[12];while(rd.read(str)!=-1){builder.append(newString(str));}article.setContent(builder.toString());article.setName(rs.getString("name"));article.setAge(rs.getInt("age"));}}catch(SQLExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}finally{ConnectionUntils.close(rs,pst,conn);}returnarticle;}(2)、Hibernate、Mybatis框架运行这是因为框架是封装集成的,所以我们直接配置变量的时候使用它的类型是CLOB。例如:Mybatis看来Hibernate5内部已经做了相应的处理,你直接可以处理方式与字符串类型相同。6.总结虽然CLOB可以解决VARCHAR2字符大小的限制,但是我们的DBA们不推荐使用这些来处理。这可能是效率问题。大文件应该放在服务器上,然后响应地址可以存储在数据库中。