是否可以使用 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.