【问题标题】:Retrieve Oracle Metadata with Internal Data使用内部数据检索 Oracle 元数据
【发布时间】:2017-04-04 06:09:10
【问题描述】:

我正在尝试编写一个 PL/SL 程序,它同时使用表的元数据和内部数据。就像:

table1 (ABC varchar2(50),wsx varchar2(50));
table2 (ABC number(50),dv varchar2(50));
table3 (ABC varchar2(10),wsds varchar2(50));
table4 (ABC varchar2(20),wfsdg varchar2(50));
table5 (ABC number(50),wsxsfd varchar2(50));

所有五个表都有一列同名'ABC'

假设 table1 有 3 行 ('JOHN.TEDA','avdv'),('MARK.LEE','fesf'),('JOHN.DEA','fwfd')等表也有这样的数据。

现在使用列名作为输入('ABC')我应该得到输出 附上。

我们可以从user_tab_columns获取列信息。

最大长度是指列中现有数据的最大长度::

select max(length(ABC)) from table1

我在加入两者时遇到问题 表格不具有参考意义。

【问题讨论】:

  • 那你的问题是什么:你想检索他们的数据,还是他们的元数据?
  • 试图获得一个组合。附表的前五列是元数据,最大长度是从数据中检索的

标签: sql plsql oracle11g database-metadata


【解决方案1】:

我尝试使用 Oracle 中的 PIPELINED 函数复制您提到的场景。希望这会有所帮助。

CREATE OR REPLACE TYPE fun_obj
IS
  OBJECT
  (
    tab_name VARCHAR2(100),
    colname  VARCHAR2(100),
    datatyp  VARCHAR2(100),
    datlen   NUMBER,
    nullable VARCHAR2(1),
    LEN      NUMBER );
  /

CREATE OR REPLACE
  FUNCTION test_max_count(
      colname IN VARCHAR2)
    RETURN fun_tab PIPELINED
  AS
    tab fun_obj:=fun_obj(NULL,NULL,NULL,NULL,NULL,NULL);
    lvlen NUMBER;
  BEGIN
    FOR I IN
    (SELECT DISTINCT table_name,
      OWNER,
      COLUMN_NAME,
      DATA_TYPE,
      DATA_LENGTH,
      NULLABLE,
      NULL AS MAX_LEN
    FROM all_tab_columns
    WHERE column_name = colname
    )
    LOOP
      tab.tab_name:=i.table_name;
      tab.colname :=i.COLUMN_NAME;
      tab.datatyp :=i.DATA_TYPE;
      tab.datlen  :=i.DATA_LENGTH;
      tab.nullable:=i.NULLABLE;
      EXECUTE IMMEDIATE 'SELECT MAX(LENGTH('||i.column_name||')) FROM '||I.OWNER||'.'||I.TABLE_NAME INTO lvlen;
      tab.len:=lvlen;
      PIPE ROW(tab);
    END LOOP;
  END;
  /

------------------------------------To Execute----------------------------------

SELECT * FROM TABLE(test_max_count('abc'));

【讨论】:

    【解决方案2】:
    CREATE OR REPLACE PROCEDURE test2 ( p_column_name IN  varchar  ) 
        IS
    
        CURSOR GET_DATA (COL  VARCHAR )IS 
    
        SELECT TABLE_NAME ,COLUMN_NAME,DATA_TYPE,DATA_LENGTH,NULLABLE 
        FROM 
        user_tab_columns where COLUMN_NAME = COL; 
    
        a_table varchar2(50);
        B_COL varchar2(50);
        a_max  varchar2(50);
    
        BEGIN  
    
        FOR C IN GET_DATA(p_column_name) LOOP 
    
        a_table := c.table_name;  
        B_COL  :=  C.COLUMN_NAME;         
    
        EXECUTE IMMEDIATE 'SELECT MAX(LENGTH('||B_COL||')) FROM '||a_table into a_max ;            
    
        insert into received_Data values  (c.table_name,C.COLUMN_NAME,C.DATA_TYPE,C.DATA_LENGTH,C.NULLABLE,a_max);
    
        END LOOP;
    
    
        EXCEPTION 
                WHEN OTHERS THEN 
                     RAISE_APPLICATION_ERROR (-20001, 
                                              p_column_name || ':$:' || SQLERRM, TRUE) ; 
        END test2;
    
        /
    
        CREATE TABLE RECEIVED_DATA
        ( TABLE_NAME   VARCHAR2(50 BYTE), 
          COLUMN_NAME  VARCHAR2(50 BYTE),    
          DATA_TYPE    VARCHAR2(50 BYTE),
          DATA_LENGTH  VARCHAR2(50 BYTE),
          IS_NULL      VARCHAR2(50 BYTE),
          MAX_LENGTH   VARCHAR2(50 BYTE));
    

    【讨论】:

    • 逐行插入肯定会产生影响。始终避免逐行,也就是缓慢的方法。
    【解决方案3】:

    您无法直接使用 SQL 实现此目的。您需要 PL/SQL + Execute Immediate 来完成这项工作。

    • 创建一个包含预期列的表
    • 然后使用for each 循环计算每列的最大长度。

    【讨论】:

    • 是的..这就是我最终所做的。另外,我创建了一个表来存储结果。
    猜你喜欢
    • 2014-12-12
    • 2015-08-14
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多