在 Oracle 19c DB 上,我需要對客戶進行抽樣,同時保持統一分布以模擬客戶的移動。有(故意)具有相同客戶的多行,但將 adderssses 更改為模型移動。因此,對于采樣,我需要先分組。
現在我得到的是,對于 SAMPLE 子句,源必須被具體化。因此,在 PL/SQL 腳本中,我生成了一個臨時表,之后我想將其與 SAMPLE 一起使用。但即使是一個簡單的 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;
我得到的是這個
ORA-06550: line 15, column 18:
PL/SQL: ORA-00942: table or view does not exist
表被創建。當我只執行用于創建的字串而不執行其他任何操作時,我得到了那么遠。然后我可以從不同的點訪問所需腳本中的表。這和編譯有關系嗎?有什么不同的方法可以解決這個問題嗎?
uj5u.com熱心網友回復:
您的 PL/SQL Block simple無法編譯,因為您查詢的表在編譯時不存在。
您必須執行事件查詢 execute immediate
簡化示例
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;
/
ORA-00942: table or view does not exist在您的設定中可能導致的另一個警告是您commit在腳本中執行。
ON COMMIT子句的默認定義是DROP DEFINITION這樣你必須使用
CREATE PRIVATE TEMPORARY TABLE ORA$PTT_temp_cust
ON COMMIT PRESERVE DEFINITION
...
uj5u.com熱心網友回復:
動態 SQL 是邪惡的。您使用動態 SQL(您的第一個execute immediate)創建表的事實并不意味著 Oracle“預測”您實際上會成功并“假定”后面的陳述句是正確的。不 - 該表尚不存在,因此所有內容都必須移動到動態 SQL。
像這樣(忽略我使用的表名和列名以及全域與私有臨時表的更改;這是 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>
不過,我沒有得到任何結果 - 但你應該(至少,我希望如此)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/376665.html
