oracle - 是否可以使用 CTE 启动 Oracle SQL 过程?
问题描述
我有一个我知道有效的 CTE,但我想将它用作一个过程,以便我可以参数化其中的一些查询。这是我尝试运行以创建过程的代码
CREATE OR REPLACE PROCEDURE VATIS_OWNER.getEnvVariables(PF IN VARCHAR, SN IN VARCHAR) AS
BEGIN
--Joins environemt variables from TESTCASES and ENVIRONMENTS tables and transposes result into columns 'ColumnName' and 'ColumnValue' and the ProfileId
--Is used by getAllDynamicData and unioned with results from sp_getProfileDetails
with
cte as (
SELECT
T.TestcaseID,
T.ProfileID,
T.TrustID,
T.DNIS,
T.TESTID,
T.ACDID,
--Must be 8 digits long, so leading 0's are added
SUBSTR(CONCAT('00000000',T.testcaseid),-8, 8) as TestCaseNo,
T.HostId,
E.TFN
FROM TESTCASES T
FULL JOIN ENVIRONMENTS E ON T.ENV_NAME = E.ENV_NAME
--Only returns env vars associated with testcase @SN
where T.TestcaseID = SN
),
cte2 as (
Select A.ProfileID
,B.*
From cte A
--Transpose happens here
Cross Apply ( SELECT 'TestcaseID' AS ColumnName,A.TestcaseID AS ColumnValue FROM DUAL UNION ALL
SELECT 'ProfileID' AS ColumnName,A.ProfileID AS ColumnValue FROM DUAL UNION ALL
SELECT 'TrustID' AS ColumnName,A.TrustID AS ColumnValue FROM DUAL UNION ALL
SELECT 'DNIS' AS ColumnName,SUBSTR(A.DNIS,-7,7) AS ColumnValue FROM DUAL UNION ALL
SELECT 'TESTID' AS ColumnName,A.TESTID AS ColumnValue FROM DUAL UNION ALL
SELECT 'ACDID' AS ColumnName,A.ACDID AS ColumnValue FROM DUAL UNION ALL
SELECT 'TestCaseNo' AS ColumnName,A.TestCaseNo AS ColumnValue FROM DUAL UNION ALL
SELECT 'HostId' AS ColumnName,A.HostId AS ColumnValue FROM DUAL UNION ALL
SELECT 'TFN' AS ColumnName,A.TFN AS ColumnValue FROM DUAL UNION ALL
SELECT 'INVALIDANI' AS ColumnName,SUBSTR(CONCAT(A.TestcaseID ,A.TESTID),-10,10) AS ColumnValue FROM DUAL
) B
)
select distinct * from cte2 where profileID = PF;
END getEnvVariables;
如果我用字符串值替换 SN 和 PF 并只运行 CTE 和查询,它就可以工作。等效版本在 SQL Server 中用作存储过程,但是当我尝试在 Oracle 中创建此过程时,出现以下编译错误:
PLS-00428: an INTO clause is expected in this SELECT statement
知道为什么我不能在程序中使用它吗?我比 Oracle 更熟悉 SQL Server,所以如果我忘记了什么,请告诉我。提前致谢。
解决方案
如果要从此过程返回选择结果,则必须使用 SYS_REFCURSOR,如下所示 -
CREATE OR replace PROCEDURE vatis_owner.Getenvvariables(pf IN VARCHAR,
sn IN VARCHAR,
res OUT SYS_REFCURSOR) AS
BEGIN
--Joins environemt variables from TESTCASES and ENVIRONMENTS tables and transposes result into columns 'ColumnName' and 'ColumnValue' and the ProfileId
--Is used by getAllDynamicData and unioned with results from sp_getProfileDetails
OPEN res FOR
WITH cte AS
(
SELECT t.testcaseid,
t.profileid,
t.trustid,
t.dnis,
t.testid,
t.acdid,
--Must be 8 digits long, so leading 0's are added
Substr(Concat('00000000',t.testcaseid),-8, 8) AS testcaseno,
t.hostid,
e.tfn
FROM testcases t
full join environments e
ON t.env_name = e.env_name
--Only returns env vars associated with testcase @SN
WHERE t.testcaseid = sn ), cte2 AS
(
SELECT a.profileid ,
b.*
FROM cte a
--Transpose happens here
cross apply
(
SELECT 'TestcaseID' AS columnname,
a.testcaseid AS columnvalue
FROM dual
UNION ALL
SELECT 'ProfileID' AS columnname,
a.profileid AS columnvalue
FROM dual
UNION ALL
SELECT 'TrustID' AS columnname,
a.trustid AS columnvalue
FROM dual
UNION ALL
SELECT 'DNIS' AS columnname,
substr(a.dnis,-7,7) AS columnvalue
FROM dual
UNION ALL
SELECT 'TESTID' AS columnname,
a.testid AS columnvalue
FROM dual
UNION ALL
SELECT 'ACDID' AS columnname,
a.acdid AS columnvalue
FROM dual
UNION ALL
SELECT 'TestCaseNo' AS columnname,
a.testcaseno AS columnvalue
FROM dual
UNION ALL
SELECT 'HostId' AS columnname,
a.hostid AS columnvalue
FROM dual
UNION ALL
SELECT 'TFN' AS columnname,
a.tfn AS columnvalue
FROM dual
UNION ALL
SELECT 'INVALIDANI' AS columnname,
substr(concat(a.testcaseid ,a.testid),-10,10) AS columnvalue
FROM dual ) b )
SELECT DISTINCT *
FROM cte2
WHERE profileid = pf;
END getenvvariables;
然后稍后您可以使用此过程在 ref_cursor 变量中返回结果。
DECALRE
RES SYS_REFCURSOR;
BEGIN
vatis_owner.Getenvvariables(pf,
sn,
RES);
FOR I IN 1..RES.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(I.YOUR_DESIRED_COLUMNS);
END LOOP;
END;
我可以看到您在查询中使用了 CROSS APPLY,这意味着您必须使用 12C 或更高版本。所以你可以使用 DBMS_SQL.RETURN_RESULT 函数 -
CREATE OR replace PROCEDURE vatis_owner.Getenvvariables(pf IN VARCHAR,
sn IN VARCHAR) AS
RES SYS_REFCURSOR;
BEGIN
--Joins environemt variables from TESTCASES and ENVIRONMENTS tables and transposes result into columns 'ColumnName' and 'ColumnValue' and the ProfileId
--Is used by getAllDynamicData and unioned with results from sp_getProfileDetails
OPEN RES FOR
WITH cte AS
(
SELECT t.testcaseid,
t.profileid,
t.trustid,
t.dnis,
t.testid,
t.acdid,
--Must be 8 digits long, so leading 0's are added
Substr(Concat('00000000',t.testcaseid),-8, 8) AS testcaseno,
t.hostid,
e.tfn
FROM testcases t
full join environments e
ON t.env_name = e.env_name
--Only returns env vars associated with testcase @SN
WHERE t.testcaseid = sn ), cte2 AS
(
SELECT a.profileid ,
b.*
FROM cte a
--Transpose happens here
cross apply
(
SELECT 'TestcaseID' AS columnname,
a.testcaseid AS columnvalue
FROM dual
UNION ALL
SELECT 'ProfileID' AS columnname,
a.profileid AS columnvalue
FROM dual
UNION ALL
SELECT 'TrustID' AS columnname,
a.trustid AS columnvalue
FROM dual
UNION ALL
SELECT 'DNIS' AS columnname,
substr(a.dnis,-7,7) AS columnvalue
FROM dual
UNION ALL
SELECT 'TESTID' AS columnname,
a.testid AS columnvalue
FROM dual
UNION ALL
SELECT 'ACDID' AS columnname,
a.acdid AS columnvalue
FROM dual
UNION ALL
SELECT 'TestCaseNo' AS columnname,
a.testcaseno AS columnvalue
FROM dual
UNION ALL
SELECT 'HostId' AS columnname,
a.hostid AS columnvalue
FROM dual
UNION ALL
SELECT 'TFN' AS columnname,
a.tfn AS columnvalue
FROM dual
UNION ALL
SELECT 'INVALIDANI' AS columnname,
substr(concat(a.testcaseid ,a.testid),-10,10) AS columnvalue
FROM dual ) b )
SELECT DISTINCT *
FROM cte2
WHERE profileid = pf;
DBMS_SQL.RETURN_RESULT(RES);
END getenvvariables;
当您运行此过程时,您将在控制台上看到结果。如需更多信息,请阅读。
推荐阅读
- amazon-s3 - apache nifi S3 PutObject stuck
- java - 空for循环的复杂度是多少?
- firefox - Firefox 是否有内置的降价功能?
- javascript - Twilio 视频参与者轨道未加载到 dom
- java - 将 Akka PoisonPill 连接到 Actor 系统和 JVM 关闭挂钩
- python - How many ways are there to change a variable's value?
- java - AWS Lambda 上的“连接尝试失败”Postgres
- json - Postgresql count data based on group data of another table resulting to JSON
- javascript - How can I extract (read + delete) from a textfile in NodeJS?
- rx-java - flatMap 运算符导致编译错误