12
返回列表 发新帖
楼主: zqm3351533

[讨论] 一个关于游标的难题

[复制链接]
论坛徽章:
0
11#
 楼主| 发表于 2010-12-14 14:07 | 只看该作者
/*
根据传进来的TABLE_NAME参数,
获取表TABLE_NAME中的基础数据对应的insert语句,
格式如下:
insert into TABLE_NAME(字段1,字段2,...) values(值1,值2,...);
insert into TABLE_NAME(字段1,字段2,...) values(值3,值4,...);
...
...
*/

CREATE   OR   REPLACE   PROCEDURE   GET_BASEDATE_BY_TABLENAME(TABLE_NAME   IN   VARCHAR2)   IS
  TYPE   CUR   IS   REF   CURSOR;
  REC_CUR   CUR; --定义一个游标,存放着表TABLE_NAME中的每条记录
  COL_CUR   CUR; --定义一个游标,存放着表TABLE_NAME中每个字段的名称
BEGIN
  --打开游标,记录集为表TABLE_NAME中所有的记录
  OPEN   REC_CUR   FOR   'SELECT   *   FROM '   ||   TABLE_NAME;
  --打开游标,记录集为表TABLE_NAME中所有字段的名称
  OPEN   COL_CUR   FOR   'SELECT   T.COLUMN_NAME   FROM   USER_TAB_COLUMNS   T   WHERE   T.TABLE_NAME   =   '''   ||   TABLE_NAME   ||   '''';

  /*
  第一层循环
  开始遍历REC_CUR结果集中的每条记录,
  REC_CUR中每一条记录对应一条insert语句
  */
  LOOP
    EXIT   WHEN   REC_CUR%NOTFOUND; --如果没有记录了,则退出循环
   
    这里我不知道该怎样才能拿到REC_CUR的每条记录!!
   
    /*
    第二层循环
    针对REC_CUR中的每条记录,
    还要做一次循环,有几个字段就循环几次
    */
    LOOP
      EXIT   WHEN   COL_CUR%NOTFOUND;--如果没有记录了,则退出循环
      
      这里我也不知道该怎样才能拿到一条记录中每个字段的值!!
      难道像这样吗:
      REC_CUR.(COL_CUR.COLUMN_NAME) !!!
      我试过了好像不行,难搞啊。。。
      
    END   LOOP;--第二层循环结束
  END   LOOP;--第一层循环结束

END   GET_BASEDATE_BY_TABLENAME;

[ 本帖最后由 zqm3351533 于 2010-12-14 15:01 编辑 ]

使用道具 举报

回复
论坛徽章:
0
12#
 楼主| 发表于 2010-12-15 13:35 | 只看该作者
UP!

使用道具 举报

回复
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
13#
发表于 2010-12-15 23:51 | 只看该作者
动态列,用dbms_sql

使用道具 举报

回复
论坛徽章:
0
14#
 楼主| 发表于 2010-12-16 15:09 | 只看该作者

回复 #13 dingjun123 的帖子

呵呵,多谢你的帮助!以前不知道oracle中有dbms_sql这么个包,我去查了下,果然功能很强大嘎!
所以我按照你的意思又重新写了一个存储过程,不过在中间还是遇到了点问题,我把我写的存储过程发下,
希望你有时间的时候看看,给点意见哈!
CREATE OR REPLACE PROCEDURE GET_BASEDATE_BY_TABLENAME(TABLE_NAME IN VARCHAR2) IS
  TYPE CUR IS REF CURSOR;
  
  COL_CUR     CUR; --定义一个游标,存放着表TABLE_NAME中每个字段的名称
  CURSOR_NAME INTEGER;
  CHAR_VALUE VARCHAR2(4000);
  ICOUNT INTEGER;
  
  TYPE COL_RECORD IS RECORD(
    COLUMN_NAME USER_TAB_COLUMNS.TABLE_NAME%TYPE,--列名
    DATA_TYPE   USER_TAB_COLUMNS.DATA_TYPE%TYPE,--数据类型
    DATA_LENGTH USER_TAB_COLUMNS.DATA_LENGTH%TYPE);--数据长度
  MYRECORD COL_RECORD;
  
BEGIN
  --打开游标,记录集为表TABLE_NAME中所有字段的名称
  OPEN COL_CUR FOR 'SELECT T.COLUMN_NAME,T.DATA_TYPE,T.DATA_LENGTH FROM USER_TAB_COLUMNS T WHERE T.TABLE_NAME = ''' || TABLE_NAME || '''';
  
  --打开一个动态游标
  CURSOR_NAME := DBMS_SQL.OPEN_CURSOR;
  
  --解析要执行的SQL,(SELECT * FROM 表名参数)
  DBMS_SQL.PARSE(CURSOR_NAME, 'SELECT * FROM :T_NAME', DBMS_SQL.NATIVE);
  
  --要执行的SQL中需要TABLE_NAME参数.
  DBMS_SQL.BIND_VARIABLE(CURSOR_NAME, 'T_NAME', TABLE_NAME);
END GET_BASEDATE_BY_TABLENAME;

上面的存储过程没有写完,写到最后第2行的时候不知道该怎么写了,按照dbms_sql中的写法,
因为我要拿到CURSOR_NAME这个动态游标查询的返回结果,所以我应该要继续写类似下面的代码:

/*使用define_column函数定义返回字段,即用变量v_b来接收查询结果集中处于第n列的的值*/
dbms_sql.define_column(cursor_name, n, v_b);

并且返回的查询结果集中有几个字段,就应该对应有几句dbms_sql.define_column

既然这样,我的想法就是做一个循环,循环次数就是表TABLE_NAME列的数量,表TABLE_NAME列的数量是可以从
USER_TAB_COLUMNS中得到,这个没有问题,所以我写了类似下面的一段代码:

for  i  in  1 .. col_count  loop
      dbms_sql.define_column(cursor_name,   i,   xxx);
end  loop;
问题出现了,注意看,在loop循环中的dbms_sql.define_column(cursor_name,   i,   xxx)语句,
有3个参数,前面2个都没有问题,问题出在了第三个参数上。
我真是想破脑袋都不知道这个XXX该怎么确定啊!
因为首先,xxx是一个变量,是用来接收查询结果中第i列的值的。问题是我申明变量的时候又不知道传进来的表到底有多少列,
那我到底该申明多少个这样的变量呢?并且变量取什么数据类型也不知道啊?

唉,做这么个小小的应用,都搞不定,我真怀疑自己的能力,没办法了,实在是小弟不才,
不知道朋友们哪位知道,希望给的意见,感激不尽!!

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表