首页 »数据库 » 数据库的可串行化:Oracle使用ANYDATA列对数据串行化思路方法 »正文
数据库的可串行化:Oracle使用ANYDATA列对数据串行化思路方法
来源: 发布时间:星期二, 2009年1月13日 浏览:6次 评论:0
="t18">
Oracle版本9提供了 种有趣 新 数据类型 开发人员借助此类型可以声明包括任何类型数据 变量 对于单个数据来说 此数据类型即ANYDATA 对于TABLE或者VARRAY数据来说 则为ANYDATASET ANYTYPE用于描述存储在ANYDATA或者ANYDATASET变量以及栏中 数据类型 这些数据类型对于处理存储在数据库中 XML数据或高级序列(Advanced Queues)具有非常重要 意义 介绍说明文档中提到了ANYDATA数据类型可以用于对对象进行串行化(serialize) 但和的相关 举例较少
串行化首先将数据值和其他结构(strUCture)组成为另外 些结构 然后将生成 结构 所有构成成分输出为流 流可以被结构返回读取 并且将覆盖前 个会话 信息 通常而言 在应用 中进行 保存和打开文件 操作即不过是串行化 种形式
个Oracle数据库或许需要使用串行化功能来存储 些表格数据 某个版本备份 这样可以在不使用数据库提交(commits)、回滚(rollbacks)、回闪(flashback)查询 情况下对数据进行查看和其他操作 许多应用 都会用到类似 对数据源 控制功能 诸如可以在应用级对当前和以前 数据版本进行比较 或对合并操作(merge)和撤销操作(undo)所产生数据改变进行比较 很多此类应用 都被设计为对每个表格创建 个备份表格 而对于数据库性能和开发进度来说 要维护这些众多 备份表格以及的间 各种关系 成为了生产数据(production data)以外 沉重负担
而通过ANYDATA数据类型以及动态SQL功能 使得通过单 串行化存储进程来把许多需要备份 表格串行输入到 个单独 备份表格成为可能 ANYDATA 个优势在于 区别于类似VARCHAR2 简单 转换数据类型 使用ANYDATA思路方法原始 数据类型并不会丢失 数据可以被存储在ANYDATA栏或者变量中而不会丢失任何细节(或根据在DATA和VARCHAR2的间进行转换 当前NLS语义而定) 这些存储 数据在转化过程中不会有任何损失
个ANYDATA对象可以通过使用任何Convert*思路方法构造简单值 思路方法来实现 或者通过“piecewise”构造思路方法创建诸如对象和数据库 类 更为复杂 变量 对于本例而言 我将集中解释如何使用Convert*思路方法
为了创建 个串行化进程 我使用了动态SQL来产生 个对表格中所有数据 查询命令 其中包括ROWID 然后我将查询命令进行分解并描述 从而得到 个有关栏和数据类型 列表 再定义提取(fetch)出栏 将每 栏从各行中提取出来 然后将其插入到串行化表格中 在本例中我使用了DBMS_SQL “自身动态SQL(native dynamic SQL)”现在还不能支持描述动态查询 绝大多数 工作都是对从DBMS_SQL数据类型代码到合适 数据类型思路方法以及 转换过程进行处理 要得到这些代码 列表 可以查看OCI包含文件ocidfn.h 或者是诸如USER_TAB_COLUMNS这样 对查看(view) 定义 在本例中 我使用了简单 数据类型(可以在EMP和DEPT表格中找到) 这样可以直接对其进行转换
drop table serialized_data;
create table serialized_data
(
tablename varchar2(30) not null,
row_id rowid not null,
colseq eger not null,
item anydata
);
create or replace procedure serialize(p_tablename varchar2)
is
l_tablename varchar2(30) := upper(p_tablename);
c pls_eger; -- cursor
x pls_eger; -- dummy
col_cnt pls_eger;
dtab dbms_sql.desc_tab;
l_rowid char(18);
l_anydata anydata;
l_vc2 varchar2(32767);
l_number number;
l_vc varchar(32767);
l_date date;
l_raw raw(32767);
l_ch char;
l_clob clob;
l_blob blob;
l_bfile bfile;
begin
c := dbms_sql.open_cursor;
dbms_sql.parse(c,'select rowid,'p_tablename'.* from 'p_tablename,
dbms_sql.native);
dbms_sql.describe_columns(c,col_cnt,dtab);
dbms_sql._column(c,1,l_rowid,18);
for i in 2 .. col_cnt loop
dtab(i).col_type
when 1 then
dbms_sql._column(c,i,l_vc2,dtab(i).col_max_len);
when 2 then
dbms_sql._column(c,i,l_number);
when 9 then
dbms_sql._column(c,i,l_vc,dtab(i).col_max_len);
when 12 then
dbms_sql._column(c,i,l_date);
when 23 then
dbms_sql._column_raw(c,i,l_raw,dtab(i).col_max_len);
when 96 then
dbms_sql._column_char(c,i,l_ch,dtab(i).col_max_len);
when 112 then
dbms_sql._column(c,i,l_clob);
when 113 then
dbms_sql._column(c,i,l_blob);
when 114 then
dbms_sql._column(c,i,l_bfile);
end ;
end loop;
x := dbms_sql.execute(c);
while dbms_sql.fetch_rows(c) != 0 loop
dbms_sql.column_value(c,1,l_rowid);
for i in 2 .. col_cnt loop
dtab(i).col_type
when 1 then
dbms_sql.column_value(c,i,l_vc2);
l_anydata := ANYDATA.ConvertVarchar2(l_vc2);
when 2 then
dbms_sql.column_value(c,i,l_number);
l_anydata := ANYDATA.ConvertNumber(l_number);
when 9 then
dbms_sql.column_value(c,i,l_vc);
l_anydata := ANYDATA.ConvertVarchar(l_vc);
when 12 then
dbms_sql.column_value(c,i,l_date);
l_anydata := ANYDATA.ConvertDate(l_date);
when 23 then
dbms_sql.column_value(c,i,l_raw);
l_anydata := ANYDATA.ConvertRaw(l_raw);
when 96 then
dbms_sql.column_value(c,i,l_ch);
l_anydata := ANYDATA.ConvertChar(l_ch);
when 112 then
dbms_sql.column_value(c,i,l_clob);
l_anydata := ANYDATA.ConvertClob(l_clob);
when 113 then
dbms_sql.column_value(c,i,l_blob);
l_anydata := ANYDATA.ConvertBlob(l_blob);
when 114 then
dbms_sql.column_value(c,i,l_bfile);
l_anydata := ANYDATA.ConvertBFile(l_bfile);
end ;
insert o serialized_data (tablename,row_id,colseq,item)
values (l_tablename,l_rowid,i,l_anydata);
end loop;
end loop;
dbms_sql.close_cursor(c);
end;
/
show errors;
假如我希望对“EMP”和“DEPT”表格串行化 我可以按照以下代码通过SQL*Plus来完成:
exec serialize('emp');
exec serialize('dept');
select t.item.gettypename from serialized_data t;
使用ANYDATA中 个问题是 假如是对象 则只有很少 信息可以通过直接SQL恢复过来 表格数据必须使用PL/SQL过程进行访问
相关文章
读者评论
发表评论
|
|