从 sqlplus 显示 pl/sql 内的动态 EXECUTE 输出

发布于 2024-08-03 09:48:42 字数 1159 浏览 5 评论 0原文

如何从Oracle sqlplus获取PL/SQL中EXECUTE的动态选择结果?

我正在编写一个简单的 sqlplus 脚本来收集给定表的所有 NUMBER 列的总和:

SET SERVEROUTPUT ON

DECLARE
        CURSOR column_cur IS
                SELECT column_name FROM ALL_TAB_COLS
                WHERE owner = '&scheme_name' AND table_name = '&table_name'
                AND data_type = 'NUMBER';
        sql_query VARCHAR2(32767);
BEGIN
        sql_query := 'select ';
        FOR column_rec IN column_cur LOOP
                sql_query := sql_query || 'SUM(' || column_rec.column_name ||
                        ') "SUM(' || column_rec.column_name || ')", ';

        END LOOP;
        sql_query := substr(sql_query, 0, length(sql_query)-2) || -- remove trailing ', '
                ' from &scheme_name' || '.&table_name';
        EXECUTE IMMEDIATE sql_query;
END;
/

动态生成的 SQL 语句在执行时会给出类似以下内容:

SUM(X) | SUM(Y) | SUM(Z) |
--------------------------
111    | 222    | 333    |

但是,即使使用 SET SERVEROUTPUT ON,运行 sqlplus 脚本仅给出:

PL/SQL procedure successfully completed.

How to get the dynamic select results of EXECUTE within PL/SQL from Oracle sqlplus?

I'm writing a simple sqlplus script to collect the sum of all NUMBER columns of a given table:

SET SERVEROUTPUT ON

DECLARE
        CURSOR column_cur IS
                SELECT column_name FROM ALL_TAB_COLS
                WHERE owner = '&scheme_name' AND table_name = '&table_name'
                AND data_type = 'NUMBER';
        sql_query VARCHAR2(32767);
BEGIN
        sql_query := 'select ';
        FOR column_rec IN column_cur LOOP
                sql_query := sql_query || 'SUM(' || column_rec.column_name ||
                        ') "SUM(' || column_rec.column_name || ')", ';

        END LOOP;
        sql_query := substr(sql_query, 0, length(sql_query)-2) || -- remove trailing ', '
                ' from &scheme_name' || '.&table_name';
        EXECUTE IMMEDIATE sql_query;
END;
/

The dynamically generated SQL statement, when executed, gives something like:

SUM(X) | SUM(Y) | SUM(Z) |
--------------------------
111    | 222    | 333    |

However, even with SET SERVEROUTPUT ON, running the sqlplus script gives only:

PL/SQL procedure successfully completed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

羁客 2024-08-10 09:48:42

您需要从 SELECT 中检索结果才能显示它。您可以使用 Syntax EXECUTE IMMEDIATE sql_query INTO var1, var2.. varn。但是,在您的情况下,列数在编译时未知。

有多种方法可以处理这个问题:

  1. 您可以使用 DBMS_SQL 并在输出列上循环。
  2. 您可以使用可读格式(例如 CSV 或 XML)构建一个包含所有结果的列,

我将演示 1:

SQL> DEFINE scheme_name=SYS
SQL> DEFINE table_name=ALL_OBJECTS
SQL> DECLARE
  2     sql_query VARCHAR2(32767);
  3     l_cursor  NUMBER := dbms_sql.open_cursor;
  4     l_dummy NUMBER;
  5     l_columns dbms_sql.desc_tab;
  6     l_value NUMBER;
  7  BEGIN
  8     sql_query := 'select ';
  9     FOR column_rec IN (SELECT column_name
 10                          FROM ALL_TAB_COLS
 11                         WHERE owner = '&scheme_name'
 12                           AND table_name = '&table_name'
 13                           AND data_type = 'NUMBER') LOOP
 14        sql_query := sql_query || 'SUM(' || column_rec.column_name
 15                     || ') "SUM(' || column_rec.column_name || ')", ';
 16     END LOOP;
 17     sql_query := substr(sql_query, 0, length(sql_query) - 2)
 18                  || ' from &scheme_name' || '.&table_name';
 19     dbms_sql.parse(l_cursor, sql_query, dbms_sql.NATIVE);
 20     dbms_sql.describe_columns(l_cursor, l_dummy, l_columns);
 21     FOR i IN 1..l_columns.count LOOP
 22        dbms_sql.define_column(l_cursor, i, l_columns(i).col_type);
 23     END LOOP;
 24     l_dummy := dbms_sql.execute_and_fetch(l_cursor, TRUE);
 25     FOR i IN 1..l_columns.count LOOP
 26        dbms_sql.column_value(l_cursor, i, l_value);
 27        dbms_output.put_line(l_columns(i).col_name ||' = '||l_value);
 28     END LOOP;
 29  END;
 30  /

SUM(DATA_OBJECT_ID) = 260692975
SUM(OBJECT_ID) = 15242783244

you will need to retrieve the result from your SELECT in order to display it. You would use the synthax EXECUTE IMMEDIATE sql_query INTO var1, var2.. varn. However in your case the number of columns is unknown at compile time.

There are a number of ways you could deal with this:

  1. you could use DBMS_SQL and loop on the columns of the output.
  2. you could build a column with all the results with a readable format like CSV of XML

I will demo 1:

SQL> DEFINE scheme_name=SYS
SQL> DEFINE table_name=ALL_OBJECTS
SQL> DECLARE
  2     sql_query VARCHAR2(32767);
  3     l_cursor  NUMBER := dbms_sql.open_cursor;
  4     l_dummy NUMBER;
  5     l_columns dbms_sql.desc_tab;
  6     l_value NUMBER;
  7  BEGIN
  8     sql_query := 'select ';
  9     FOR column_rec IN (SELECT column_name
 10                          FROM ALL_TAB_COLS
 11                         WHERE owner = '&scheme_name'
 12                           AND table_name = '&table_name'
 13                           AND data_type = 'NUMBER') LOOP
 14        sql_query := sql_query || 'SUM(' || column_rec.column_name
 15                     || ') "SUM(' || column_rec.column_name || ')", ';
 16     END LOOP;
 17     sql_query := substr(sql_query, 0, length(sql_query) - 2)
 18                  || ' from &scheme_name' || '.&table_name';
 19     dbms_sql.parse(l_cursor, sql_query, dbms_sql.NATIVE);
 20     dbms_sql.describe_columns(l_cursor, l_dummy, l_columns);
 21     FOR i IN 1..l_columns.count LOOP
 22        dbms_sql.define_column(l_cursor, i, l_columns(i).col_type);
 23     END LOOP;
 24     l_dummy := dbms_sql.execute_and_fetch(l_cursor, TRUE);
 25     FOR i IN 1..l_columns.count LOOP
 26        dbms_sql.column_value(l_cursor, i, l_value);
 27        dbms_output.put_line(l_columns(i).col_name ||' = '||l_value);
 28     END LOOP;
 29  END;
 30  /

SUM(DATA_OBJECT_ID) = 260692975
SUM(OBJECT_ID) = 15242783244
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文