【问题标题】:PL SQL Oracle Store Dynamic SQL result (Dynamic in a loop)PL SQL Oracle 存储动态 SQL 结果(循环中的动态)
【发布时间】:2022-02-12 18:17:30
【问题描述】:

我是 Oracle 上 PL/SQL 的新手(必须为此做一些工作,但它显然不是我的领域)。

所以我必须对我们的数据库进行“审核”,其中包括为我们模式的每个表的每一列提供其最大长度(我们如何声明它(例如 VARCHAR2(15))和当前的最大值此列(例如 ID 15000)(可能会发展并希望我的结果中有更多数据,但目前我只需要这个)。

我会用一个例子来解释我的问题 说清楚:

我有一个包含 3 列的表 EMPLOYEE: VARCHAR2(50) 中的 NAME,我拥有的最长(长度)是 48 VARCHAR2(100)中的CITY,我拥有的最长(长度)是95 AGE in NUMBER,最长的(长度)是 2

因此,对于我的架构的这个表,我希望将其作为脚本的输出(在 excel 中处理它),必须考虑到这里的员工表只是由返回的许多其他表中的一个第一个请求:

TABLE_NAME COLUMN_NAME MAX_LENGTH_DATA MAX_LENGTH_COLUMN
EMPLOYEE NAME 48 50
EMPLOYEE CITY 95 100
EMPLOYEE AGE 2 () (don't need)

所以我们每列和表将有 1 行,如果我的表有 5 列,我将有 5 行。 我用 LOOP、CURSOR 和现在的 TYPE OBJECT 尝试了许多解决方案,但我做错了我知道但无法弄清楚它是什么。

CREATE OR REPLACE TYPE t_output_allColumns FORCE AS OBJECT
           (maxLengthColumn  NUMBER,
            COLUMN_NAME     VARCHAR2(80),
            TABLE_NAME    VARCHAR2(80));
/
CREATE OR REPLACE TYPE output_allColumns FORCE AS TABLE OF t_output_allColumns;


DECLARE

    maxlengthTab  output_allColumns;
    v_requete_maxLength varchar2(4000);
    TYPE MyCurTyp  IS REF CURSOR;
    c1 MyCurTyp;
    v_column_name VARCHAR2(400);
    v_table_name VARCHAR2(400);
 
begin
 maxlengthTab:= output_allColumns();
 OPEN c1 FOR 'select TABLE_NAME, COLUMN_NAME from ALL_TAB_COLUMNS';
    
    FETCH c1 INTO v_column_name , v_table_name;
    v_requete_maxLength := 'SELECT MAX( LENGTH(' || v_column_name ||'), ' || v_column_name ||',' || v_table_name ||'  FROM ' ||v_table_name;
    EXECUTE IMMEDIATE v_requete_maxLength BULK COLLECT INTO maxlengthTab;
    dbms_output.put_line(output_allColumns);
  CLOSE c1;
END;

这是我尝试过的一个脚本,我要做的第一件事是从我的架构中选择所有列(这没问题,我已经将它们打印出来进行测试,这很好) 但主要问题是当我尝试对我的结果使用动态 SQL 时

我尝试 SELECT MAX( LENGTH(' || 我从第一个请求获得的列名||'),' || 我从第一个请求获得的列名| |',' || 我从第一个请求获得的表名||' FROM' ||我从第一个请求获得的表名;这就是我卡住的地方,我无法存储每个结果并显示它。

【问题讨论】:

  • 使用代码会更容易,但在 PL/SQL 中我会争取最轻微的修改。 不确定你的意思。 PL/SQL 是一种编程语言,您正在用它编写代码。这怎么不是代码?
  • 您希望数字、日期、时间戳、间隔列的长度是多少?
  • open 和 close 之间的代码缩进,好像有一个循环,但没有循环。 (从逻辑上讲,它不应该在那里缩进。)如果你想遍历多个列,那么你应该使用loop。
  • 我的意思是我用来喜欢Java或JS的语言,语法真的不一样。对于数字,日期我真的不需要知道它,因为你不能选择长度,我的审计目标是知道增加的 id 是否会达到我们设置的最大长度(例如:我们声明 Varchar2(10) 和我们的 id达到 10000000000 或接近)。
  • 我知道循环,但是当我尝试了很多方法时,我喜欢 7 个文件以不同的方式达到我的目标,包括这个带有循环的文件(在这种情况下复制并粘贴它删除循环,这就是为什么它在那里缩进)

标签: sql oracle plsql dynamic-sql database-cursor


【解决方案1】:

您可以使用流水线函数。


给定类型:

CREATE TYPE t_output_allColumns AS OBJECT(
  OWNER           VARCHAR2(80),
  TABLE_NAME      VARCHAR2(80),
  COLUMN_NAME     VARCHAR2(80),
  maxLengthData   NUMBER,
  maxLengthColumn NUMBER
);

CREATE TYPE output_allColumns AS TABLE OF t_output_allColumns;

然后是函数:

CREATE FUNCTION column_details(
  i_owner IN VARCHAR2
)
RETURN output_allcolumns PIPELINED
IS
  v_data_length NUMBER;
BEGIN
  FOR r IN (
    SELECT owner,
           table_name,
           column_name,
           data_length
    FROM   all_tab_columns
    WHERE  owner = i_owner
  )
  LOOP
    EXECUTE IMMEDIATE
      'SELECT MAX(LENGTH("'||r.column_name||'")) FROM "'||r.owner||'"."'||r.table_name||'"'
      INTO v_data_length;
    PIPE ROW (
      t_output_allcolumns(
        r.owner,
        r.table_name,
        r.column_name,
        v_data_length,
        r.data_length
      )
    );
  END LOOP;
END;
/

那么你可以使用:

SELECT * FROM TABLE(column_details('SCHEMA_NAME'));

哪些输出:

OWNER TABLE_NAME COLUMN_NAME MAXLENGTHDATA MAXLENGTHCOLUMN
SCHEMA_NAME EMPLOYEES NAME 48 50
SCHEMA_NAME EMPLOYEES AGE 2 22
SCHEMA_NAME EMPLOYEES CITY 95 100

db小提琴here

【讨论】:

  • 谢谢它真的很好用!那么 PIPELINE 像临时表一样工作吗?您声明一个返回对象(您之前创建它)的函数,您可以像表格一样随时使用。如果我想要另一列像 v_data_length 怎么办? (例如:列 v_min_data_length 的最小值)。我应该像这样让它返回函数吗? CREATE FUNCTION column_details( i_owner IN VARCHAR2 ) RETURN output_allcolumns PIPELINED IS v_data_length NUMBER, v_min_data_length NUMBER;
  • @Thomas 返回声明是RETURN output_allcolumns PIPELINED,所以如果你想返回一个额外的列,那么你需要编辑t_output_allcolumns 数据类型来添加它。但是,是的,如果您想存储临时值,您可能需要在 IS 和 BEGIN 关键字之间声明额外的局部变量。像这样db<>fiddle
猜你喜欢
  • 2010-10-21
  • 1970-01-01
  • 2012-04-03
  • 2020-12-04
  • 1970-01-01
  • 2018-08-09
  • 1970-01-01
  • 2020-06-02
  • 1970-01-01
相关资源
最近更新 更多