当我们将 table 名称作为输入时,需要使用存储过程获取 table 详细信息

Need to fetch the table details using stored procedure when we give table name as input

CREATE TABLE test_table 
(
    col1  NUMBER(10),
    col2  NUMBER(10)
);

INSERT INTO test_table 
VALUES (1, 2);

我正在编写一个存储过程,其中如果我将 table 名称作为输入,那应该会给我 table 数据和列详细信息。

例如:

SELECT *   
FROM <input_table_name>;

但这会导致错误,即 SQL 命令没有正确结束,即使我已经处理了这个问题。

我的尝试:

CREATE OR REPLACE PROCEDURE sp_test(iv_table_name IN VARCHAR2,
p_out_cur OUT SYS_REFCURSOR)
AS
lv_str VARCHAR2(400);
lv_count NUMBER(1);
lv_table_name VARCHAR2(255):=UPPER(iv_table_name);
BEGIN

    lv_str := 'SELECT * FROM '||lv_table_name;
    
    SELECT COUNT(1) INTO lv_count FROM all_tables WHERE table_name = lv_table_name;
    IF lv_count = 0 THEN
        dbms_output.put_line('Table does not exist');
    ELSE
        OPEN p_out_cur FOR lv_str;
    END IF;
END sp_test;

使用的工具:SQL 开发人员(18c)

在动态 SQL 中,不要用分号终止语句。

EXECUTE IMMEDIATE 'SELECT * FROM '||lv_table_name||';';
                                                 -----
                                                 remove this

无论如何,当您 运行 那段代码时,您不会得到任何结果。如果你真的想看到 table 的内容,你必须切换到其他东西,例如创建一个 returns 引用光标的函数。


示例数据:

SQL> SELECT * FROM test_table;

      COL1       COL2
---------- ----------
         1          2
         3          4

您编写的程序现已正确:

SQL> CREATE OR REPLACE PROCEDURE sp_test (iv_table_name  IN     VARCHAR2,
  2                                       p_out_cur         OUT SYS_REFCURSOR)
  3  AS
  4     lv_str         VARCHAR2 (400);
  5     lv_count       NUMBER (1);
  6     lv_table_name  VARCHAR2 (255) := UPPER (iv_table_name);
  7  BEGIN
  8     lv_str := 'SELECT * FROM ' || lv_table_name;
  9
 10     SELECT COUNT (1)
 11       INTO lv_count
 12       FROM all_tables
 13      WHERE table_name = lv_table_name;
 14
 15     IF lv_count = 0
 16     THEN
 17        DBMS_OUTPUT.put_line ('Table does not exist');
 18     ELSE
 19        OPEN p_out_cur FOR lv_str;
 20     END IF;
 21  END sp_test;
 22  /

Procedure created.

测试:

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
  2     l_rc    SYS_REFCURSOR;
  3     l_col1  NUMBER (10);
  4     l_col2  NUMBER (10);
  5  BEGIN
  6     sp_test ('TEST_TABLE', l_rc);
  7
  8     LOOP
  9        FETCH l_rc INTO l_col1, l_col2;
 10
 11        EXIT WHEN l_rc%NOTFOUND;
 12
 13        DBMS_OUTPUT.put_line (l_col1 || ', ' || l_col2);
 14     END LOOP;
 15  END;
 16  /
1, 2              --> contents of the
3, 4              --> TEST_TABLE

PL/SQL procedure successfully completed.

SQL>

函数(而不是带有 OUT 参数的过程):

SQL> CREATE OR REPLACE FUNCTION sf_test (iv_table_name IN VARCHAR2)
  2     RETURN SYS_REFCURSOR
  3  AS
  4     lv_str         VARCHAR2 (400);
  5     lv_count       NUMBER (1);
  6     lv_table_name  VARCHAR2 (255) := UPPER (iv_table_name);
  7     l_rc           SYS_REFCURSOR;
  8  BEGIN
  9     lv_str := 'SELECT * FROM ' || lv_table_name;
 10
 11     SELECT COUNT (1)
 12       INTO lv_count
 13       FROM all_tables
 14      WHERE table_name = lv_table_name;
 15
 16     IF lv_count = 0
 17     THEN
 18        raise_application_error (-20000, 'Table does not exist');
 19     ELSE
 20        OPEN l_rc FOR lv_str;
 21     END IF;
 22
 23     RETURN l_rc;
 24  END sf_test;
 25  /

Function created.

测试:

SQL> SELECT sf_test ('liksajfla') FROM DUAL;
SELECT sf_test ('liksajfla') FROM DUAL
       *
ERROR at line 1:
ORA-20000: Table does not exist
ORA-06512: at "SCOTT.SF_TEST", line 18


SQL> SELECT sf_test ('TEST_TABLE') FROM DUAL;

SF_TEST('TEST_TABLE'
--------------------
CURSOR STATEMENT : 1

CURSOR STATEMENT : 1

      COL1       COL2
---------- ----------
         1          2
         3          4


SQL>