【问题标题】:How do I get the data from the column_name? Oracle PL/SQL如何从 column_name 获取数据?甲骨文 PL/SQL
【发布时间】:2018-03-23 16:57:29
【问题描述】:

如何从我从 SQL 语句中检索到的 column_name 中获取数据(即行)? (对于 PL/SQL 来说是全新的)。 这是我的代码:

create or replace procedure com_coll_cur
as
    type comColcur is ref cursor;
    com_col_cur comColcur;
    sql_stmt varchar2(4000);
    type newtab_field is table of comColcur%TYPE;
begin
    sql_stmt :=
        'select column_name from all_tab_cols where table_name in (''TAB1'', ''TAB2'') ' ||
        'group by column_name having count(*)>1';

    open com_col_cur for sql_stmt;
    loop
        fetch com_col_cur into newtab_field;
        exit when com_col_cur%NOTFOUND;
    end loop;

    close com_col_cur;
end;

我在这里要做的是首先找到两个表之间的公共列。这部分只抓取 column_name 但我也想要那些公共列中的数据。因此,我使用光标“指向”该公共 column_name 并使用 loop(fetch) 来获取该公共 column_name 内的数据。最后,我想只用这些公共列的数据创建新表。

我对这里的一切都很陌生,任何帮助将不胜感激。

【问题讨论】:

  • “制作”新表是什么意思?你想创建一个新表吗?您只能在代码中使用动态 SQL 来做到这一点;这是一个高级主题(无论如何一般都不推荐);如果您对 PL/SQL “完全陌生”,则绝对不推荐。那么:“包含此列名+其数据”是什么意思?你的意思是在同一列吗?列名是 VARCHAR2;如果“内部数据”是 NUMBER、DATE 或 TIMESTAMP 怎么办?您想如何将字符串和 TIMESTAMP 数据“包含”在一起?
  • @mathguy 这也是我遇到的问题。我想根据游标的数据类型定义表的列数据类型。因此,如果游标抓取两个表之间的公共列并且数据类型恰好是日期,varchar2,数字,对于 col1,col2,col3 我想将这些公共列存储到新创建的表中,其中日期,varchar2,col1 的数字, col2,col3 数据类型。
  • 正如您所写,光标不需要是动态的。您有一个返回列名列表的报告。我不知道“指向”是什么意思。

标签: oracle plsql


【解决方案1】:

您不了解游标和获取的工作原理。 Fetch 从游标中获取数据,因此在您的过程示例中,您只获取列名,而不是列中的数据。要获取数据,您需要另一个游标 - 从目标表中选择或使用动态 sql。

这是一个执行您描述的代码。我不清楚您想如何存储两个表中的数据 - 随后或以另一种方式。假设我们随后存储它们。此代码还建议具有相同名称的列具有相同的数据类型。这段代码的一部分(用于制作数据类型)我从另一个 stackoverflow 帖子中获得,以节省编写它的时间: How do I get column datatype in Oracle with PL-SQL with low privileges?

dbms_output.put_line - 用于打印我们创建的 sql 语句

declare
   cSql          varchar2(4000);
   cCols         varchar2(4000);
   cNewTableName varchar2(30) := 'AABBCC';
   cTb1          varchar2(30) := 'TAB1';
   cTb2          varchar2(30) := 'TAB2';
begin 
   for hc in (
           select T.column_name, T.typ
           from
           (
           select column_name,
                  data_type||
                  case when data_precision is not null and nvl(data_scale,0)>0 then '('||data_precision||','||data_scale||')'
                       when data_precision is not null and nvl(data_scale,0)=0 then '('||data_precision||')'
                       when data_precision is null and data_scale is not null then '(*,'||data_scale||')'
                       when char_length>0 then '('||char_length|| case char_used 
                                                                  when 'B' then ' Byte'
                                                                  when 'C' then ' Char'
                                                                  else null 
                                                                  end||')'
                  end||decode(nullable, 'N', ' NOT NULL')  typ
        from all_tab_cols 
       where table_name in (cTb1, cTb2) ) T
             group by T.column_name, T.typ having count(*) > 1)
   loop
      cSql := cSql || case when cSql is null then null else ',' end || hc.column_name || ' ' || hc.typ;
      cCols := cCols || case when cCols is null then null else ',' end || hc.column_name;
   end loop;

   if (cSql is not null) then
      -- First drop table if it exists
      for hc in (select * from all_objects where object_type = 'TABLE' and object_name = cNewTableName)
      loop
         execute immediate 'drop table ' || hc.object_name;
      end loop;

      -- create table
      cSql := 'create table ' || cNewTableName || '(' || cSql || ')';
      dbms_output.put_line(cSql);
      execute immediate cSql;

      -- insert data
      cSql := 'insert into ' || cNewTableName || '(' || cCols || ') select ' || cCols || ' from ' || cTb1;
      dbms_output.put_line(cSql);
      execute immediate cSql;

      cSql := 'insert into ' || cNewTableName || '(' || cCols || ') select ' || cCols || ' from ' || cTb2;
      dbms_output.put_line (cSql);
      execute immediate cSql;

   end if;
end;

【讨论】:

  • 啊,是的,刚刚意识到我的光标得到了 column_names.. 仍然是新的仍在学习中,感谢您提供的代码,我会从中学到很多东西
  • @kys92 欢迎您。很高兴它对您有所帮助。
猜你喜欢
  • 1970-01-01
  • 2017-03-21
  • 1970-01-01
  • 2010-09-11
  • 2022-01-21
  • 2017-01-24
  • 1970-01-01
  • 1970-01-01
  • 2010-10-18
相关资源
最近更新 更多