Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 需要帮助从光标中进行选择,就像它是一个工作台一样吗_Sql_Oracle_Stored Procedures_Plsql - Fatal编程技术网

Sql 需要帮助从光标中进行选择,就像它是一个工作台一样吗

Sql 需要帮助从光标中进行选择,就像它是一个工作台一样吗,sql,oracle,stored-procedures,plsql,Sql,Oracle,Stored Procedures,Plsql,我有一个正在尝试编写的存储过程,我想使用游标作为工作表,以便可以使用结果更新表。它抛出了一些错误。有谁能帮我解决这些问题吗 create or replace PROCEDURE SP_POPULATE_STUDENT_STOPTEMPID AS CURSOR c_workTable IS SELECT stdnt.STUDENT_ID, stdnt.route_code, stdnt.DISPATCH_TYPE, stdnt.RUN_CODE,

我有一个正在尝试编写的存储过程,我想使用游标作为工作表,以便可以使用结果更新表。它抛出了一些错误。有谁能帮我解决这些问题吗

create or replace PROCEDURE SP_POPULATE_STUDENT_STOPTEMPID

AS

CURSOR c_workTable IS
SELECT  
    stdnt.STUDENT_ID, 
    stdnt.route_code, 
    stdnt.DISPATCH_TYPE, 
    stdnt.RUN_CODE, 
    stdnt.STOP_ADDRESS, 
    stdnt.STOP_TIME, 
    ST.STOP_TEMPLATE_ID 
FROM  
    STOP_TEMPLATE ST 
    JOIN TASK_TEMPLATE TT 
        ON ST.TASK_TEMPLATE_ID = TT.TASK_TEMPLATE_ID 
    JOIN RUN_TEMPLATE RT 
        ON ST.RUN_TEMPLATE_ID = RT.RUN_TEMPLATE_ID,  
    STUDENT stdnt
WHERE 
    TT.TASK_NAME = stdnt.route_code 
    AND TT.DISPATCH_TYPE = stdnt.DISPATCH_TYPE 
    AND RT.RUN_CODE = stdnt.RUN_CODE 
    AND ST.STOP_DESCRIPTION = stdnt.STOP_ADDRESS 
    AND CAST(ST.EXPECTED_ARRIVAL_TIME AS TIME(7)) = stdnt.STOP_TIME ;

BEGIN

UPDATE STUDENT stdnt  
SET stdnt.STOP_TEMPLATE_ID = c_workTable .STOP_TEMPLATE_ID 
FROM  
    c_workTable 
WHERE  
    stdnt.STUDENT_ID = c_workTable .STUDENT_ID 
    AND stdnt.route_code = c_workTable .route_code 
    AND stdnt.DISPATCH_TYPE = c_workTable .DISPATCH_TYPE 
    AND stdnt.RUN_CODE = c_workTable .RUN_CODE 
    AND stdnt.STOP_ADDRESS = c_workTable .STOP_ADDRESS     
    AND stdnt.STOP_TIME = c_workTable .STOP_TIME 


END SP_POPULATE_STUDENT_STOPTEMPID;
ETA:更改了查询中的一些变量名称

我是基于sql server存储过程编写的,但是在update语句中出现了一些错误

关于更新学生stdnt

错误(30,5):PL/SQL:SQL语句被忽略

然后在from子句中,我得到了这个错误

错误(32,5):PL/SQL:ORA-00933:SQL命令未正确结束

最后,我得到了最后一条

错误(42,35):PLS-00103:在 应为以下情况之一:(begin case declare end exception 如果循环mod null pragma raise return选择update,则退出goto 而与

您可以通过使用一个利用
JOIN
UPDATE
语句来实现它:

UPDATE(
    SELECT  
        stdnt.STOP_TEMPLATE_ID as old_val 
      , ST.STOP_TEMPLATE_ID as new_val
    FROM  
        STOP_TEMPLATE ST 
        JOIN TASK_TEMPLATE TT 
            ON ST.TASK_TEMPLATE_ID = TT.TASK_TEMPLATE_ID 
        JOIN RUN_TEMPLATE RT 
            ON ST.RUN_TEMPLATE_ID = RT.RUN_TEMPLATE_ID
        JOIN STUDENT stdnt
            ON (    TT.TASK_NAME = stdnt.route_code 
                AND TT.DISPATCH_TYPE = stdnt.DISPATCH_TYPE 
                AND RT.RUN_CODE = stdnt.RUN_CODE 
                AND ST.STOP_DESCRIPTION = stdnt.STOP_ADDRESS 
                AND CAST(ST.EXPECTED_ARRIVAL_TIME AS TIME(7)) = stdnt.STOP_TIME)
) t
SET t.old_val = t.new_val;
链接到另一个可能有帮助的问题和答案:

替代但类似的解决方案是从子查询中获取更新值:

UPDATE STUDENT stdnt
   SET stdnt.STOP_TEMPLATE_ID = (
    SELECT  
        ST.STOP_TEMPLATE_ID
    FROM  
        STOP_TEMPLATE ST 
        JOIN TASK_TEMPLATE TT 
            ON (ST.TASK_TEMPLATE_ID = TT.TASK_TEMPLATE_ID 
                AND TT.TASK_NAME = stdnt.route_code 
                AND TT.DISPATCH_TYPE = stdnt.DISPATCH_TYPE)
        JOIN RUN_TEMPLATE RT 
            ON (ST.RUN_TEMPLATE_ID = RT.RUN_TEMPLATE_ID
                AND RT.RUN_CODE = stdnt.RUN_CODE)
    WHERE ST.STOP_DESCRIPTION = stdnt.STOP_ADDRESS 
      AND CAST(ST.EXPECTED_ARRIVAL_TIME AS TIME(7)) = stdnt.STOP_TIME
);

链接到具有类似解决方案的相关问题的答案:

另一个更好的方法是使用ORACLE中的MERGE语句从2个或多个表更新表-

MERGE INTO STUDENT stdnt
USING (SELECT  SRM.STUDENT_ID, 
               SRM.route_code, 
               SRM.DISPATCH_TYPE, 
               SRM.RUN_CODE, 
               SRM.STOP_ADDRESS, 
               SRM.STOP_TIME, 
               ST.STOP_TEMPLATE_ID 
       FROM STOP_TEMPLATE ST 
       JOIN TASK_TEMPLATE TT ON ST.TASK_TEMPLATE_ID = TT.TASK_TEMPLATE_ID 
       JOIN RUN_TEMPLATE RT ON ST.RUN_TEMPLATE_ID = RT.RUN_TEMPLATE_ID,  
       STUDENT_ROUTE_MAPPING SRM 
       WHERE TT.TASK_NAME = SRM.route_code 
       AND TT.DISPATCH_TYPE = SRM.DISPATCH_TYPE 
       AND RT.RUN_CODE = SRM.RUN_CODE 
       AND ST.STOP_DESCRIPTION = SRM.STOP_ADDRESS 
       AND CAST(ST.EXPECTED_ARRIVAL_TIME AS TIME(7)) = SRM.STOP_TIME) I
ON (stdnt.STUDENT_ID = I.STUDENT_ID 
    AND stdnt.route_code = I.route_code 
    AND stdnt.DISPATCH_TYPE = I.DISPATCH_TYPE 
    AND stdnt.RUN_CODE = I.RUN_CODE 
    AND stdnt.STOP_ADDRESS = I.STOP_ADDRESS     
    AND stdnt.STOP_TIME = I.STOP_TIME)
WHEN MATCHED THEN UPDATE
                  SET stdnt.STOP_TEMPLATE_ID = I.STOP_TEMPLATE_ID

您需要这样做有什么原因吗?在单个SQL语句(可能是合并语句)中进行更新会更快、更容易、更易于维护。没有什么真正的原因,除了我对sql的总体经验不足之外……快速查看表明文件末尾缺少结尾。它包含在我的qorkspace中,我只是不擅长复制。我调整了原始帖子。我收到一个错误,使用你的第二个建议,在子标题别名前的结尾括号之间缺少关键字ry已设置。在阅读了您发布的链接后,我仍然无法解决此问题。您是否知道可能有什么问题?忽略我以前的评论。我刚刚意识到我复制了一个旧版本,但我尚未完成从旧模式的转换。我编辑了我的问题以更准确。我的bad@KevinLordofSpaghettiCode我编辑了我的a现在回答。上一个错误技术上是因为在连接的第一部分忽略了连接子句。实际上是因为错误地保留了
STUDENT
表,尽管它后来在
join
中的最后一步被连接。我的编辑现在纠正了错误,并且不包括
STUDENT\u ROUTE\u MAPPING
表您已将其从问题中删除。感谢您的澄清。我非常感谢您的帮助。很抱歉,这让我很痛苦,但我仍然收到错误“SQL命令未正确结束”在别名t分配给子查询之前的括号中。我尝试了一些不同的方法,但无法解决这个问题。我的经验是mysql,所以我不完全确定它可能是什么。我需要添加AS或其他关键字来完成它吗?@KevinLordofSpaghettiCode我通过添加alterna编辑了我的答案为什么你认为<代码>合并> /代码>从2个或多个表中更新表是更好的选择?我认为使用<代码>更新>代码>对于唯一的更新目的总是更好的。<代码>合并< /Cord>当然提供了同时更新和插入表的可能性(这里不需要)。,但我不认为它是一个比
UPDATE
本身更好的仅用于更新的解决方案?@GoranKutlaca
MERGE
语句可以插入和/或更新。它的优点是,仅用于更新,它比
UPDATE
语句更清晰,并且可以选择更好的执行计划。此外,您的子查询/视图需要是关键的-保留以在
UPDATE
语句中使用,但不能在
MERGE
语句中使用(但是,源数据对于
ON
连接条件必须是唯一的)。我在更新中遇到了问题,因为它说我的基表没有保留键。这意味着什么?我如何保留表的键?我对sql不是很有经验,所以请原谅,如果这是一个愚蠢的问题。@KevinLordofSpaghettiCode,您应该阅读以了解保留键的表。作为内部查询使用的联接具有some重复行。您需要更正它,因为我们尚未看到您的数据。
MERGE INTO STUDENT stdnt
USING (SELECT  SRM.STUDENT_ID, 
               SRM.route_code, 
               SRM.DISPATCH_TYPE, 
               SRM.RUN_CODE, 
               SRM.STOP_ADDRESS, 
               SRM.STOP_TIME, 
               ST.STOP_TEMPLATE_ID 
       FROM STOP_TEMPLATE ST 
       JOIN TASK_TEMPLATE TT ON ST.TASK_TEMPLATE_ID = TT.TASK_TEMPLATE_ID 
       JOIN RUN_TEMPLATE RT ON ST.RUN_TEMPLATE_ID = RT.RUN_TEMPLATE_ID,  
       STUDENT_ROUTE_MAPPING SRM 
       WHERE TT.TASK_NAME = SRM.route_code 
       AND TT.DISPATCH_TYPE = SRM.DISPATCH_TYPE 
       AND RT.RUN_CODE = SRM.RUN_CODE 
       AND ST.STOP_DESCRIPTION = SRM.STOP_ADDRESS 
       AND CAST(ST.EXPECTED_ARRIVAL_TIME AS TIME(7)) = SRM.STOP_TIME) I
ON (stdnt.STUDENT_ID = I.STUDENT_ID 
    AND stdnt.route_code = I.route_code 
    AND stdnt.DISPATCH_TYPE = I.DISPATCH_TYPE 
    AND stdnt.RUN_CODE = I.RUN_CODE 
    AND stdnt.STOP_ADDRESS = I.STOP_ADDRESS     
    AND stdnt.STOP_TIME = I.STOP_TIME)
WHEN MATCHED THEN UPDATE
                  SET stdnt.STOP_TEMPLATE_ID = I.STOP_TEMPLATE_ID