是否可以用CTE启动和Oracle SQL过程?

问题描述 投票:0回答:1

我有一个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

知道为什么我不能在存储过程中使用这个吗?我对SQL Server比Oracle更熟悉,所以如果我忘记了什么,请告诉我。先谢谢你。

oracle stored-procedures common-table-expression
1个回答
0
投票

如果你想从这个存储过程中返回选择结果,你必须使用一个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;

然后在以后你可以使用这个 proc 来返回 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;

当你运行这个程序时,你会在控制台看到结果。如需了解更多信息,请点击 阅读:

© www.soinside.com 2019 - 2024. All rights reserved.