简体   繁体   English

PL/SQL:在脚本中创建和使用临时表

[英]PL/SQL: Creation and usage of a temporary table in script

On an Oracle 19c DB I need to sample on customers whilst keeping a uniorm distribution to model the moving of customers.在 Oracle 19c DB 上,我需要对客户进行抽样,同时保持对 model 的统一分布,以便客户移动。 There are (on purpose) multiple rows with the same customers but changeing adderssses to model moving.有(故意)多行具有相同的客户,但将地址更改为 model 移动。 Thus, for the sampling i need to group first.因此,对于采样,我需要先分组。

Now what I got is that for the SAMPLE clause the source has to be materialized.现在我得到的是,对于 SAMPLE 子句,必须具体化源。 So in the PL/SQL script I generate a temporary table that i want to use afterwards with SAMPLE.因此,在 PL/SQL 脚本中,我生成了一个临时表,之后我想将其与 SAMPLE 一起使用。 But even a simple SELECT INTO afterwards doens't work.但即使是一个简单的 SELECT INTO 之后也不起作用。

set SERVEROUT on;
DECLARE
    v_cust_name VARCHAR2(100);
    cmd_creation VARCHAR2(500):='CREATE PRIVATE TEMPORARY TABLE ORA$PTT_temp_cust AS(
        SELECT cust_id, MIN(name) as name
        FROM customers
        GROUP BY cust_id)';
BEGIN
    
    EXECUTE IMMEDIATE cmd_creation;
    dbms_output.put_line('temp created');
    
    SELECT name 
    INTO v_cust_name
    FROM (SELECT * 
        FROM ORA$PTT_temp_cust SAMPLE(5))
    WHERE ROWNUM =1;
        
    EXECUTE IMMEDIATE 'DROP TABLE ORA$PTT_temp_cust';
    dbms_output.put_line('temp dropped');
END;

What I get is this我得到的是这个

ORA-06550: line 15, column 18:
PL/SQL: ORA-00942: table or view does not exist

The table gets created.表被创建。 That far I got when I only executed the String for the creation and nothing else.当我只为创建执行 String 而没有其他内容时,我已经走到了这一步。 Then I can access the table in a desired script from a different point.然后我可以从不同的点访问所需脚本中的表。 Does this have to do with the compiling?这和编译有关系吗? Is there some different way to solve this?有什么不同的方法可以解决这个问题吗?

Dynamic SQL is evil .动态 SQL 是邪恶的。 The fact that you created the table using dynamic SQL (your 1st execute immediate ) doesn't mean that Oracle "predicts" you'll actually succeed with that and "presume" that statements that follow are correct.您使用动态 SQL (您的第一次execute immediate )创建表的事实并不意味着 Oracle “预测”您实际上会成功并“假设”以下陈述是正确的。 Nope - that table doesn't exist yet, so everything has to be moved to dynamic SQL.不——那个表还不存在,所以一切都必须移动到动态 SQL。

Something like this (disregard changes in table and column names I used and global vs. private temporary table; this is 11gXE):像这样的东西(忽略我使用的表和列名以及全局与私有临时表的更改;这是 11gXE):

SQL> DECLARE
  2     v_cust_name   VARCHAR2 (100);
  3     cmd_creation  VARCHAR2 (500)
  4                      := 'CREATE global TEMPORARY TABLE PTT_temp_cust AS
  5          SELECT empno, MIN(ename) as name
  6          FROM emp
  7          GROUP BY empno';
  8  BEGIN
  9     EXECUTE IMMEDIATE cmd_creation;
 10
 11     EXECUTE IMMEDIATE '
 12      SELECT max(name)
 13      FROM (SELECT *
 14          FROM PTT_temp_cust SAMPLE(5))
 15      WHERE ROWNUM = 1'
 16        INTO v_cust_name;
 17
 18     EXECUTE IMMEDIATE 'DROP TABLE PTT_temp_cust';
 19
 20     DBMS_OUTPUT.put_line ('Result = ' || v_cust_name);
 21  END;
 22  /
Result =

PL/SQL procedure successfully completed.

SQL>

I got no result, though - but you should (at least, I hope so).不过,我没有得到任何结果——但你应该(至少,我希望如此)。

Your PL/SQL Block simple does not compile as the table you query does not exists at the time of compilation.您的 PL/SQL Block simple无法编译,因为您查询的表在编译时不存在

You must perform event the query with execute immediate您必须execute immediate执行查询事件

Simplified Example简化示例

DECLARE
    v_cust_name VARCHAR2(100);
    cmd_creation VARCHAR2(500):='CREATE PRIVATE TEMPORARY TABLE ORA$PTT_temp_cust  AS select * from dual';

BEGIN
    
    EXECUTE IMMEDIATE cmd_creation;
    dbms_output.put_line('temp created');
    
    EXECUTE IMMEDIATE 'SELECT DUMMY  FROM ORA$PTT_temp_cust' INTO v_cust_name;
    dbms_output.put_line('name' || v_cust_name);
        
    EXECUTE IMMEDIATE 'DROP TABLE ORA$PTT_temp_cust';
    dbms_output.put_line('temp dropped');
END;
/

An other caveat the can lead to ORA-00942: table or view does not exist in your setup is that you performs commit in your script.另一个可能导致ORA-00942: table or view does not exist的警告是您在脚本中执行commit

The default definition of the ON COMMIT clause is DROP DEFINITION so you must use ON COMMIT子句的默认定义是DROP DEFINITION所以你必须使用

CREATE PRIVATE TEMPORARY TABLE ORA$PTT_temp_cust 
ON COMMIT PRESERVE DEFINITION 
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM