如何在Oracle中参数化包体内的列和表名

问题描述 投票:0回答:1

带有 min 聚合函数的子查询不起作用。它找不到该表。我不太清楚如何参数化列和表名称以使其工作。

CREATE OR REPLACE PACKAGE TEST_PKG IS

PROCEDURE SP_METRICS 
(
          p_ENVIRONMENT         IN  VARCHAR2,
          p_DATABASE            IN  VARCHAR2,
          p_SCHEMA              IN  VARCHAR2,
          p_TABLE_NAME          IN  VARCHAR2,
          p_DATE_COLUMN         IN  VARCHAR2,
          o_TABLE_BASELINE      OUT SYS_REFCURSOR
);
END TEST_PKG;

程序代码:

CREATE OR REPLACE PACKAGE BODY TEST_PKG AS

PROCEDURE SP_METRICS 
(
          p_ENVIRONMENT         IN  VARCHAR2,
          p_DATABASE            IN  VARCHAR2,
          p_SCHEMA              IN  VARCHAR2,
          p_TABLE_NAME          IN  VARCHAR2,
          p_DATE_COLUMN         IN  VARCHAR2,
          o_TABLE_BASELINE      OUT SYS_REFCURSOR
) AS

BEGIN

OPEN   o_TABLE_BASELINE FOR 

SELECT 
      t.num_rows BASELINE_ROW_COUNT,
        NVL(max( 
    (
        SELECT
            round( (nvl(SUM(e.bytes),0) / 1048576),2)
        FROM
            dba_extents e
        WHERE
            e.segment_type LIKE '%TABLE%'
            AND e.owner = t.owner
            AND e.segment_name = t.table_name
        GROUP BY
            e.owner,e.segment_name
    )
    ),0) BASELINE_TABLE_SIZE, 
   NVL( SUM( (
        SELECT
            round( (nvl(SUM(extd.bytes),0) / 1048576),2)
        FROM
            dba_extents extd
        WHERE
            extd.segment_type like ('%INDEX%')
            AND indx.owner = extd.owner
            AND indx.index_name = extd.segment_name
            AND indx.tablespace_name = extd.tablespace_name
        GROUP BY
            extd.owner,extd.segment_name
    ) ),0) BASELINE_INDEX_SIZE,
           (SELECT MIN(p_DATE_COLUMN)FROM p_TABLE_NAME)--THIS DOES NOT WORK- SAY UNDEFINED TABLE
FROM
   all_indexes indx RIGHT JOIN
    dba_all_tables t ON indx.table_owner = t.owner AND indx.table_name = t.table_name
WHERE t.owner      = p_SCHEMA
AND   t.table_name = p_TABLE_NAME
GROUP BY
    SYSDATE,
    'EDW',
    t.owner,
    t.table_name,
   t.num_rows;

END SP_METRICS;

END TEST_PKG;

这就是我传递值的方式:

var c refcursor;

execute USER.TEST_PKG.SP_METRICS('DEV', 'EDW', 'DW', 'SAIL_DIM','SAIL_DATE' :c);

print c;
oracle plsql oracle11g plsqldeveloper plsql-package
1个回答
0
投票

你说这行不通:

(SELECT MIN(p_DATE_COLUMN)FROM p_TABLE_NAME)

正确 - 您将需要动态 SQL。关于代码复杂性,我建议您动态执行此查询并在过程中使用结果。简化版:

SQL> create or replace procedure p_test (p_table_name in varchar2,
  2                                      p_date_column in varchar2)
  3  is
  4    l_min_date date;
  5  begin
  6    execute immediate 'select min(' || p_date_column || ') from ' ||
  7      dbms_assert.sql_object_name(p_table_name) into l_min_date;
  8
  9    dbms_output.put_line(l_min_date);
 10  end;
 11  /

Procedure created.

SQL> set serveroutput on
SQL>
SQL> exec p_test('emp', 'hiredate');
17.12.80

PL/SQL procedure successfully completed.

SQL>

您可以对代码执行相同的操作(

l_min_date
用于第31行):

SQL> CREATE OR REPLACE PROCEDURE sp_metrics(
  2    p_environment      IN                 VARCHAR2,
  3    p_database         IN                 VARCHAR2,
  4    p_schema           IN                 VARCHAR2,
  5    p_table_name       IN                 VARCHAR2,
  6    p_date_column      IN                 VARCHAR2,
  7    o_table_baseline   OUT                SYS_REFCURSOR
  8  )
  9  AS
 10    l_min_date date;
 11  BEGIN
 12    execute immediate 'select min(' || p_date_column || ') from ' ||
 13      dbms_assert.sql_object_name(p_table_name) into l_min_date;
 14
 15    OPEN o_table_baseline FOR SELECT t.num_rows   baseline_row_count,
 16                                     nvl(MAX((SELECT round((nvl(SUM(e.bytes),0)/ 1048576),2)
 17                                              FROM dba_extents e
 18                                              WHERE e.segment_type LIKE '%TABLE%'
 19                                                    AND e.owner = t.owner
 20                                                    AND e.segment_name = t.table_name
 21                                              GROUP BY e.owner,e.segment_name
 22                                             )),0)baseline_table_size,
 23                                     nvl(SUM((SELECT round((nvl(SUM(extd.bytes),0)/ 1048576),2)
 24                                              FROM dba_extents extd
 25                                              WHERE extd.segment_type LIKE('%INDEX%')
 26                                                    AND indx.owner = extd.owner
 27                                                    AND indx.index_name = extd.segment_name
 28                                                    AND indx.tablespace_name = extd.tablespace_name
 29                                              GROUP BY extd.owner,extd.segment_name
 30                                             )),0)baseline_index_size,
 31                                     l_min_date
 32                              FROM all_indexes indx
 33                              RIGHT JOIN dba_all_tables t ON indx.table_owner = t.owner
 34                                                             AND indx.table_name = t.table_name
 35                              WHERE t.owner = p_schema
 36                                    AND t.table_name = p_table_name
 37                              GROUP BY SYSDATE,
 38                                       'EDW',
 39                                       t.owner,
 40                                       t.table_name,
 41                                       t.num_rows;
 42
 43  END sp_metrics;
 44  /

Procedure created.

SQL>
© www.soinside.com 2019 - 2024. All rights reserved.