【问题标题】:Run query dynamically in stored procedure in Oracle在 Oracle 的存储过程中动态运行查询
【发布时间】:2019-01-19 10:50:31
【问题描述】:

选择所有列匹配的数据库表,而不是使用循环将表名传递给下一个查询。如果列名和列值匹配,则返回 true 并且使用存储过程存在 for 循环:

CREATE OR REPLACE PROCEDURE TEST 
(
NAME IN VARCHAR2 ,
ID IN NUMBER,
RE OUT SYS_REFCURSOR 
) AS

BEGIN
OPEN  RE FOR SELECT A.TABLE_NAME FROM
user_tables A JOIN user_tab_columns C
ON C.TABLE_NAME = A.TABLE_NAME
WHERE C.COLUMN_NAME = NAME;

FOR RE IN LOOP

v_Sql := 'SELECT COUNT(*) FROM '|| LOOP.TABLE_NAME || 'WHERE COLUMN_NAME = 
ID';
EXECUTE IMMEDIATE v_Sql
IF v_Sql%ROWCOUNT > 0 THEN
return true; 
EXIT

END LOOP;

END TEST;

为了更好地理解问题

//Get all the tables of database where campus_id is exist in any table of 
 database
 Campus, Class, Section (3 tables found)
 Apply forloop on the records
 Select count(campus_id) as total from (table name using loop) where campus_id = 1(value 
 pass)
 if(total > 0){

 Exist for loop and return true
 }
 else{
 Again iterate the loop to next value
 } 

【问题讨论】:

    标签: oracle stored-procedures


    【解决方案1】:

    你所描述的没有多大意义。如果有多个表包含您要检查的列,并且您在找到第一个表后立即退出循环,那么其余表呢?

    这就是我要做的,看看它是否有帮助。我将创建一个返回函数(不是过程)。为此,我将首先创建类型:

    SQL> create or replace type t_record as object (tn varchar2(30), cnt number);
      2  /
    
    Type created.
    
    SQL> create or replace type t_table as table of t_record;
      2  /
    
    Type created.
    
    SQL>
    

    功能:

    • 在光标FOR 循环中,我正在选择包含该列的表
    • L_STR 用于编写SELECT 语句
    • DBMS_OUTPUT.PUT_LINE 用于先显示它,以便我可以直观地检查它是否设置正确。
    • 如果是,我将使用EXECUTE IMMEDIATE 运行它
    • 结果存储到表类型中并返回给调用者

    SQL> create or replace function f_colname
      2    (par_column_name  in varchar2,
      3     par_column_value in varchar2
      4    )
      5    return t_table
      6  is
      7    retval t_table := t_table();
      8    l_str  varchar2(200);
      9    l_cnt  number;
     10  begin
     11    for cur_r in (select table_name
     12                  from user_tab_columns
     13                  where column_name = par_column_name
     14                 )
     15    loop
     16      l_str := 'select count(*) from ' || cur_r.table_name ||
     17               ' where ' || par_column_name || ' = ' ||
     18               chr(39) || par_column_value || chr(39);
     19      -- Display l_str first, to make sure that it is OK:
     20      -- dbms_output.put_line(l_str);
     21      execute immediate l_str into l_cnt;
     22      retval.extend;
     23      retval(retval.count) := t_record(cur_r.table_name, l_cnt);
     24    end loop;
     25    return retval;
     26  end;
     27  /
    
    Function created.
    

    测试:

    SQL> select * from table (f_colname('DEPTNO', '10'));
    
    TN                                    CNT
    ------------------------------ ----------
    TEST_201812                             1
    DEPT                                    1
    EMP                                     3
    
    SQL> select * from table (f_colname('ENAME', 'KING'));
    
    TN                                    CNT
    ------------------------------ ----------
    EMP                                     1
    BONUS                                   1
    
    SQL>
    

    这对于某些数据类型(例如DATE)将无法正常工作,并且必须在必要时进行调整。


    [编辑:编辑问题后]

    好吧,那就更简单了。它仍然应该是一个函数(返回一个布尔值,正如你所说的那样 - 如果发现某些东西 - 你想返回 TRUE)。代码与之前的函数非常相似。

    SQL> create or replace function f_colname
      2    (par_column_name  in varchar2,
      3     par_column_value in varchar2
      4    )
      5    return boolean
      6  is
      7    l_str  varchar2(200);
      8    l_cnt  number;
      9    retval boolean := false;
     10  begin
     11    for cur_r in (select table_name
     12                  from user_tab_columns
     13                  where column_name = par_column_name
     14                 )
     15    loop
     16      l_str := 'select count(*) from ' || cur_r.table_name ||
     17               ' where ' || par_column_name || ' = ' ||
     18               chr(39) || par_column_value || chr(39);
     19      -- Display l_str first, to make sure that it is OK:
     20      -- dbms_output.put_line(l_str);
     21      execute immediate l_str into l_cnt;
     22      if l_cnt > 0 then
     23         retval := true;
     24         exit;
     25      end if;
     26    end loop;
     27    return retval;
     28  end;
     29  /
    
    Function created.
    

    测试:由于不能在 SQL 层返回布尔值,所以必须使用匿名 PL/SQL 块,如下所示:

    SQL> declare
      2    l_ret boolean;
      3  begin
      4    if f_colname('DEPTNO', '15') then
      5       dbms_output.put_line('It exists');
      6    else
      7       dbms_output.put_line('It does not exist');
      8    end if;
      9  end;
     10  /
    It does not exist
    
    PL/SQL procedure successfully completed.
    
    SQL>
    

    【讨论】:

    • 感谢您的努力 (Y)。如果您看到您的测试示例。任何行中的 DEPTNO 10 计数大于零,然后退出 for 循环并显示结果返回 true。我不想知道它出现了多少次。
    • 好吧,我在答案中添加了更多代码(一个新函数)。请看一下。
    • 你能告诉我一件事,我是如何返回 1 或 0 而不是它存在或它不存在使用 return 语句。
    • 因为我可以在存储过程中调用此函数需要返回 1 或 0,而不是从 php 调用存储过程
    • 不返回布尔值,而是返回 NUMBER。 RETVAL 也可以是 NUMBER,其默认值为 0(零)。在第 23 行,设置retval := 1;。其余部分保持原样
    猜你喜欢
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 2017-04-03
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2014-06-04
    相关资源
    最近更新 更多