【问题标题】:Error(9,1): PLS-00428: an INTO clause is expected in this SELECT statement while creating stored procedures错误(9,1):PLS-00428:在创建存储过程时,此 SELECT 语句中需要一个 INTO 子句
【发布时间】:2020-04-09 16:10:05
【问题描述】:

我创建了一个 SP,但是在编译时出现错误

错误(9,1):PLS-00428:此 SELECT 语句中应有一个 INTO 子句

下面是SP

CREATE OR REPLACE PROCEDURE FIP_VALID_TBL_TRANSMEDIA 
 (
   POUTMSG OUT VARCHAR2
  )

 AS 
BEGIN

 SELECT distinct  TO_CHAR(sp.RJ_SPAN_ID) AS SPAN_ID, TO_CHAR(sp.RJ_MAINTENANCE_ZONE_CODE) AS MAINT_ZONE_CODE
                                    from  APP_FTTX.span@SAT sp
                                    WHERE LENGTH(sp.RJ_SPAN_ID) = 21
                                    AND (sp.RJ_SPAN_ID LIKE ('%SPN%') OR sp.RJ_SPAN_ID LIKE ('%SPQ%') OR sp.RJ_SPAN_ID LIKE ('%SPR%')    
                                    OR sp.RJ_SPAN_ID LIKE ('%SPS%'))
                                    AND (sp.RJ_SPAN_ID LIKE ('%_BU') OR sp.RJ_SPAN_ID LIKE ('%_MP'))
                                    AND sp.INVENTORY_STATUS_CODE = 'IPL'
                                    AND sp.RJ_MAINTENANCE_ZONE_CODE = 'INMUNVMB01'
                                    AND (sp.RJ_INTRACITY_LINK_ID NOT LIKE ('%\_9%') ESCAPE '\' OR 
      sp.RJ_INTRACITY_LINK_ID IS NULL)                                        
             MINUS

    SELECT distinct  TO_CHAR(sp.RJ_SPAN_ID) AS SPAN_ID, TO_CHAR(sp.RJ_MAINTENANCE_ZONE_CODE) AS 
    MAINT_ZONE_CODE
                                    from  APP_FTTX.span@SAT sp
                                    INNER JOIN APP_FTTX.transmedia@SAT tm  -- transmedia added
                                    on sp.RJ_SPAN_ID = tm.RJ_SPAN_ID
                                    WHERE length(sp.RJ_SPAN_ID) = length(tm.RJ_SPAN_ID)
                                    and sp.RJ_MAINTENANCE_ZONE_CODE = tm.RJ_MAINTENANCE_ZONE_CODE
                                    and sp.INVENTORY_STATUS_CODE = tm.INVENTORY_STATUS_CODE
                                    AND LENGTH(sp.RJ_SPAN_ID) = 21
                                    AND (sp.RJ_SPAN_ID LIKE ('%SPN%') OR sp.RJ_SPAN_ID LIKE ('%SPQ%') 
OR sp.RJ_SPAN_ID LIKE ('%SPR%')    
                                    OR sp.RJ_SPAN_ID LIKE ('%SPS%'))
                                    AND (sp.RJ_SPAN_ID LIKE ('%_BU') OR sp.RJ_SPAN_ID LIKE ('%_MP'))
                                    AND sp.INVENTORY_STATUS_CODE = 'IPL'
                                    AND sp.RJ_MAINTENANCE_ZONE_CODE = 'INMUNVMB01'
                                    AND (sp.RJ_INTRACITY_LINK_ID NOT LIKE ('%\_9%') ESCAPE '\' OR 
sp.RJ_INTRACITY_LINK_ID IS NULL);

  NULL;
END FIP_VALID_TBL_TRANSMEDIA;

请指出这里有什么问题

更新

表格说明

           Name            Null Type           
           --------------- ---- -------------- 
           SPAN_ID              NVARCHAR2(100) 
           MAINT_ZONE_CODE      NVARCHAR2(100) 
           UPDATED_DATE         DATE           
           UPDATED_BY           NVARCHAR2(100)

【问题讨论】:

  • ALTER PROCEDURE 只能在您的过程已经存在时使用。作为一项规则,您应该使用CREATE OR REPLACE PROCEDURE,如果您的程序存在或不存在,它就会起作用。
  • 已经有很多问题涉及到这一点;但是您认为错误消息可能意味着什么?您目前预计查询结果会发生什么变化?
  • @BobJarvis-ReinstateMonica:好的,明白了。相应地更改了
  • 同意@AlexPoole。 FWIW,Steve Feuerstein 有一篇关于在 PLSQL 中使用 SELECT 语句和游标的好文章,blogs.oracle.com/oraclemagazine/working-with-cursors。这可能有助于理解如何在 PLSQL 中使用它们的细微差别。
  • 在存储过程中运行 sql...您必须告诉 db 如何处理结果,这不像 sql server 可以使用 sp 运行 sql 并返回结果查询

标签: oracle join stored-procedures


【解决方案1】:

我只想在这个过程中插入

您可以只使用insert ... select [语法]:

CREATE OR REPLACE PROCEDURE FIP_VALID_TBL_TRANSMEDIA 
 (
   POUTMSG OUT VARCHAR2
  )

 AS 
BEGIN

 INSERT INTO TBL_VLD_FIBERINV_DATA (SNAP_ID, MAINT_ZONE_CODE)
 SELECT TO_CHAR(sp.RJ_SPAN_ID), TO_CHAR(sp.RJ_MAINTENANCE_ZONE_CODE)
 ...
 MINUS
 SELECT TO_CHAR(sp.RJ_SPAN_ID), TO_CHAR(sp.RJ_MAINTENANCE_ZONE_CODE)
 ...

您不需要带有 MINUS 的 distinct;并且列别名没有用。

或者,如果您想设置其他列,并且它们还没有默认,您可以在查询部分包含这些值 - 这里使用系统时间和当前用户:

 INSERT INTO TBL_VLD_FIBERINV_DATA (SNAP_ID, MAINT_ZONE_CODE, UPDATED_DATE, UPDATED_BY)
 SELECT TO_CHAR(sp.RJ_SPAN_ID), TO_CHAR(sp.RJ_MAINTENANCE_ZONE_CODE), SYSDATE, USER
 ...
 MINUS
 SELECT TO_CHAR(sp.RJ_SPAN_ID), TO_CHAR(sp.RJ_MAINTENANCE_ZONE_CODE), SYSDATE, USER
 ...

你需要执行这个过程,它才能真正做任何事情;只是创建或编译它不会导致其中的代码(即插入)运行。您可以从一个简单的匿名块中做到这一点:

DECLARE
 OUTMSG VARCHAR2(4000);
BEGIN
 FIP_VALID_TBL_TRANSMEDIA (POUTMSG => OUTMSG);
END;
/

您必须声明并传递一个变量以匹配过程的形式参数,即使您当前没有填充它。 (希望您不打算捕获异常并将异常消息放入该变量中......)


在目标表中使用nvarchar2 似乎有点奇怪,即使用户ID 的大小也为100;并让to_char() 调用似乎已经是字符串的东西。你使用的是the to_char(char) function,它总是返回varchar2,所以把它放到nvarchar2中似乎很奇怪......

【讨论】:

  • 感谢 Alex 的回答,但由于Error(10,2): PL/SQL: ORA-01789: query block has incorrect number of result columns 尝试了您的第二个答案而出现错误
  • 您是否更改了 MINUS 的两个分支?
  • 不,对不起..我只更改了一个分支..让我更改第二个并检查
  • 程序已经编译成功,但是记录没有被插入到表中
  • 嗯,你有没有调用程序?还是直接编译?
【解决方案2】:

在此过程中,您正在执行一个查询,但您没有将该查询的结果放在任何地方。我建议重写为:

CREATE OR REPLACE PROCEDURE FIP_VALID_TBL_TRANSMEDIA(POUTMSG OUT VARCHAR2)
AS 
BEGIN
  SELECT SPAN_ID || MAINT_ZONE_CODE
    INTO POUTMSG  -- puts result of query into POUTMSG
    FROM (SELECT distinct TO_CHAR(sp.RJ_SPAN_ID) AS SPAN_ID,
                          TO_CHAR(sp.RJ_MAINTENANCE_ZONE_CODE) AS MAINT_ZONE_CODE
            from  APP_FTTX.span@SAT sp
            WHERE LENGTH(sp.RJ_SPAN_ID) = 21 AND
                  (sp.RJ_SPAN_ID LIKE ('%SPN%') OR
                   sp.RJ_SPAN_ID LIKE ('%SPQ%') OR
                   sp.RJ_SPAN_ID LIKE ('%SPR%') OR
                   sp.RJ_SPAN_ID LIKE ('%SPS%')) AND
                  (sp.RJ_SPAN_ID LIKE ('%_BU') OR
                   sp.RJ_SPAN_ID LIKE ('%_MP')) AND
                   sp.INVENTORY_STATUS_CODE = 'IPL' AND
                   sp.RJ_MAINTENANCE_ZONE_CODE = 'INMUNVMB01' AND
                  (sp.RJ_INTRACITY_LINK_ID NOT LIKE ('%\_9%') ESCAPE '\' OR 
                   sp.RJ_INTRACITY_LINK_ID IS NULL)                                        
          MINUS
          SELECT distinct TO_CHAR(sp.RJ_SPAN_ID) AS SPAN_ID,
                          TO_CHAR(sp.RJ_MAINTENANCE_ZONE_CODE) AS MAINT_ZONE_CODE
            from  APP_FTTX.span@SAT sp
            INNER JOIN APP_FTTX.transmedia@SAT tm  -- transmedia added
              on sp.RJ_SPAN_ID = tm.RJ_SPAN_ID
            WHERE length(sp.RJ_SPAN_ID) = length(tm.RJ_SPAN_ID) and
                  sp.RJ_MAINTENANCE_ZONE_CODE = tm.RJ_MAINTENANCE_ZONE_CODE and
                  sp.INVENTORY_STATUS_CODE = tm.INVENTORY_STATUS_CODE AND
                  LENGTH(sp.RJ_SPAN_ID) = 21 AND
                  (sp.RJ_SPAN_ID LIKE ('%SPN%') OR
                   sp.RJ_SPAN_ID LIKE ('%SPQ%') OR
                   sp.RJ_SPAN_ID LIKE ('%SPR%') OR
                   sp.RJ_SPAN_ID LIKE ('%SPS%')) AND
                  (sp.RJ_SPAN_ID LIKE ('%_BU') OR
                   sp.RJ_SPAN_ID LIKE ('%_MP')) AND
                   sp.INVENTORY_STATUS_CODE = 'IPL' AND
                   sp.RJ_MAINTENANCE_ZONE_CODE = 'INMUNVMB01' AND
                  (sp.RJ_INTRACITY_LINK_ID NOT LIKE ('%\_9%') ESCAPE '\' OR 
                   sp.RJ_INTRACITY_LINK_ID IS NULL);
END FIP_VALID_TBL_TRANSMEDIA;

【讨论】:

  • 程序看起来没问题,但我想将POUTMSG的数据插入到TBL_VLD_FIBERINV_DATA的表中。我已经更新了有问题的表格描述
  • 感谢您的 SP,但对如何将查询数据插入表中的任何想法。请建议
  • 请不要在评论中对当前问题提出其他问题或修改;相反,请提出一个新问题。谢谢。
  • 对此我真的很抱歉,但我是一步一步走的,这是我实现目标的最后一步。虽然赞成您编写查询的答案
猜你喜欢
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-24
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
相关资源
最近更新 更多