是否可以使用 CTE 启动 Oracle SQL 程序?
Is is possible to start and Oracle SQL Procedure with a CTE?
我有一个我知道有效的 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 服务器中用作存储过程,但是当我尝试在 Oracle 中创建此过程时,出现此编译错误:
PLS-00428: an INTO clause is expected in this SELECT statement
知道为什么我不能在程序中使用它吗?我对 SQL Server 比 Oracle 更熟悉,所以如果我忘记了什么,请告诉我。提前致谢。
如果你想 return 这个过程的 select 结果,你必须使用如下的 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;
之后您可以使用此过程 return 生成 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;
当你运行这个过程时,你会在控制台上看到结果。如需更多信息,请read.
我有一个我知道有效的 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 服务器中用作存储过程,但是当我尝试在 Oracle 中创建此过程时,出现此编译错误:
PLS-00428: an INTO clause is expected in this SELECT statement
知道为什么我不能在程序中使用它吗?我对 SQL Server 比 Oracle 更熟悉,所以如果我忘记了什么,请告诉我。提前致谢。
如果你想 return 这个过程的 select 结果,你必须使用如下的 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;
之后您可以使用此过程 return 生成 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;
当你运行这个过程时,你会在控制台上看到结果。如需更多信息,请read.