存儲過程存儲BLOB數據

工做中遇到一個問題,須要將外網數據庫的數據同步到內網數據庫。在同步過程當中BLOB字段的處理費了很大功夫,在此把實現過程記錄下來,但願對你們有所幫助。java

1.建一個表,爲了簡單,表中只有兩個字段,主鍵id和BLOB字段img。 sql

create table a(id number primary key,img blob);

2.建立存儲過程,輸入參數p_id爲要插入blob或修改的blob的記錄ID、p_blob_data爲實際要插入的BLOB字段值、p_msg爲存儲過程返回的信息數據庫

create or replace procedure write2blob(p_id        in number, --id
                                       p_blob_data in blob,
                                       p_msg       out varchar2) --數據
 is
  v_lobloc     blob; --目標blob字段
  v_blob_data  blob; --做爲接受參數的字段,參數變量不能直接拿來賦值
  v_amount     binary_integer; --總長度
  v_sub_length binary_integer; --一次讀取的最大長度,不超過32766
  v_sub_blob   blob; --一次讀取的子串
  v_offset     binary_integer; --遊標
  v_err_msg    varchar2(1000); --測試用
  v_id         binary_integer; --要修改或新增的記錄ID
  v_temp       binary_integer; --臨時變量用於判斷是否有v_id對應的記錄
begin
  v_amount     := length(p_blob_data);
  v_blob_data  := p_blob_data;
  v_sub_length := 32767;
  v_offset     := 1;
  v_id         := p_id;
  v_temp       := 0;
  --execute immediate v_query_string into v_lobloc;
  select count(1) into v_temp from a where id = v_id;  --查詢是否有v_id對應的記錄,而且賦值給v_temp
  /*注意:不管是修改仍是新增,blob字段都須要用empty_blob()進行初始化,不然後邊的blob內容,不能寫進表裏*/
  if v_temp = 0 then
    insert into a (id, img) values (v_id, empty_blob()); --若是v_temp爲0新增
  else
    update a set img = empty_blob() where id = v_id; --若是v_temp爲1修改
  end if;
  commit;
  select img into v_lobloc from a where id = v_id for update;
  if v_amount > v_sub_length then
    dbms_lob.open(v_lobloc, dbms_lob.lob_readwrite);
    while v_offset < v_amount loop
      dbms_lob.read(v_blob_data, v_sub_length, v_offset, v_sub_blob); --把讀到的內容放到v_sub_blob中
      dbms_lob.writeappend(v_lobloc,
                           --DBMS_LOB.GETLENGTH(v_sub_blob),
                           length(v_sub_blob),
                           v_sub_blob); --寫入v_lobloc,該變量已經在以前和sql語句綁定
      v_offset  := length(v_sub_blob) + v_offset; --遊標移動
      v_err_msg := length(v_lobloc);--返回blob的長度
    end loop;
  else
    dbms_lob.writeappend(v_lobloc, v_amount, v_blob_data); --如果小魚32766直接寫入
  end if;
  commit;
  dbms_lob.close(v_lobloc);
  p_msg := v_err_msg;
exception
  when others then
    p_msg := '出現異常信息';
    p_msg := v_err_msg;
    rollback;
end;

3.java調用存儲過程保存blob字段c#

public static void main(String[] args) {
		final Connection srcConn = DbUtil.getOracleConnection("c##sjzjy", "sjzjy", "192.168.23.60", "orcl");
		final QueryRunner srcOracle = new QueryRunner();
		final Connection wsConn = DbUtil.getOracleConnection("c##sjzjy", "sjzjy", "192.168.23.60", "orcl");
		try {
			srcOracle.query(srcConn, " select img from a where id = 1 ", new ResultSetHandler<Img>(){
				@Override
				public Img handle(ResultSet rs) throws SQLException {
					while(rs.next()) {
						Blob blob = rs.getBlob("IMG");
						try {
							String img = new String(blob.getBytes((long)1, (int)blob.length()), "ISO8859-1");//BASE64
//							String sql = "insert into a(img) values(?) ";
//							PreparedStatement stmt = wsConn.prepareStatement(sql);
//							stmt.setBytes(1, img.getBytes("ISO8859-1"));
//							stmt.executeUpdate();
							String sql = "call write2blob(?,?,?)";
							CallableStatement ps = wsConn.prepareCall(sql);
							ps.setInt(1, 8);
							//ps.setBlob(2, blob);
							ps.setBytes(2, img.getBytes("ISO8859-1"));
							ps.registerOutParameter(3, Types.VARCHAR);
							ps.execute();
							String str = ps.getString(3);
							System.out.println(str);
						} catch (Exception e) {
							e.printStackTrace();
						} 
					}
					return null;
				}});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
相關文章
相關標籤/搜索