此代碼有效:
WITH
FUNCTION a (a IN INTEGER)
RETURN INTEGER
IS
BEGIN
RETURN a 1;
END;
b(v) AS (SELECT column_value FROM sys.ODCINUMBERLIST(1,2,3))
SELECT a (v) FROM b;
但我想在這個 with 陳述句中定義一個型別。稍后我想重用這種型別以使用流水線功能。因此,我需要一種型別,它是一個記錄表。并且型別必須在函式外部(而不是在函式內部)定義,因為型別將由函式回傳
我嘗試使用這種簡單的 w 型別。
WITH
type w is record(w1 integer);
FUNCTION f (a in integer)
RETURN INTEGER
IS
ret integer;
BEGIN
return 2;
END;
B(b1) as (select 1 from dual)
select f(3) from dual;
它不起作用:
[錯誤] 編譯 (3: 5): ORA-00900: 無效的 SQL 陳述句
是否可以在 with 陳述句中定義型別,我該怎么做?
uj5u.com熱心網友回復:
在 SQL 背景關系(與 PL/SQL 相對)中使用的函式的回傳資料型別必須是原生 SQL 型別或模式級別的用戶定義型別(使用陳述句自行定義的型別create type,而不是在包中定義)。
在 Oracle 12.1 中添加了對該子句中定義的函式的支持時,此限制并未解除with- 甚至對于如此定義的函式的資料型別也沒有。特別是,不能在withSQL 陳述句的子句中定義回傳資料型別。
然后,記錄僅在 PL/SQL 中支持;在模式級別,您將需要創建物件型別,而不是記錄型別。
注意:回傳記錄集合(記錄型別在包中定義)的流水線函式可以在 SQL 背景關系中使用;原因是 Oracle 在模式級別在幕后定義了相應的物件型別,并負責轉換。為什么甲骨文不對所有功能都做同樣的事情只有甲骨文才能解釋。當然,正如您在啟動的另一個執行緒中發現的那樣,with不支持子句中的流水線表函式(即使非流水線表函式支持!)
with我們不知道您要解決的實際問題,但您似乎不太可能在該子句中完成您嘗試做的所有事情。
uj5u.com熱心網友回復:
你不能。
如果您查看SELECT檔案,尤其是語法圖:
with_clause::=
plsql_declarations::=
可以看到只能宣告一個函式或一個程序。
如果你試試:
WITH FUNCTION f (a in integer)
RETURN w
IS
type w is record(w1 integer);
BEGIN
return w(2);
END;
SELECT f(3)
FROM DUAL;
你得到錯誤:
ORA-06553: PLS-313: 'F' not declared in this scope
ORA-06552: PL/SQL: Item ignored
ORA-06553: PLS-498: illegal use of a type before its declaration
您無法修復該錯誤,但是,如果您能神奇地修復該錯誤(不能僅使用本地宣告),您將收到第二個錯誤,因為 aRECORD是僅限 PL/SQL 的資料型別,然后您嘗試在 SQL 范圍內使用它。
例如,如果您在 PL/SQL 包中全域宣告型別:
CREATE PACKAGE pkg AS
type w is record(w1 integer);
END;
/
WITH FUNCTION f (a in integer)
RETURN pkg.w
IS
BEGIN
return pkg.w(2);
END;
SELECT f(3).w1
FROM DUAL;
查詢給出了錯誤:
ORA-00902: invalid datatype
在運行查詢之前,您需要使用 SQLOBJECT型別并在全域 SQL 范圍內宣告它。
例如:
CREATE TYPE w IS OBJECT(w1 INTEGER);
WITH FUNCTION f (a in integer)
RETURN w
IS
BEGIN
return w(2);
END;
SELECT f(3).w1
FROM DUAL;
輸出:
F(3).W1 2
要使用RECORD,您需要在 PL/SQL 包或 PL/SQL 匿名塊中宣告型別,然后僅在 PL/SQL 中使用它。
例如,如果您只想使用本地宣告的 PL/SQL 型別運行您的函式,那么您可以完全在 PL/SQL 匿名塊中執行它:
DECLARE
TYPE w IS record(w1 integer);
v_w w;
FUNCTION f (a in integer)
RETURN w
IS
BEGIN
return w(2);
END f;
BEGIN
v_w := f(3);
DBMS_OUTPUT.PUT_LINE(v_w.w1);
END;
/
輸出:
2
db<>在這里擺弄
uj5u.com熱心網友回復:
如果您在函式中定義型別,您的代碼將起作用,如下所示:
WITH
FUNCTION f (a in integer)
RETURN INTEGER
IS
ret integer;
type w is record(w1 integer);
BEGIN
return 2;
END;
B(b1) as (select 1 from dual)
select f(3) from dual;
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/455856.html


