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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.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
PL/SQL是否编写更新列的过程?_Sql_Oracle_Plsql_Oracle10g - Fatal编程技术网

PL/SQL是否编写更新列的过程?

PL/SQL是否编写更新列的过程?,sql,oracle,plsql,oracle10g,Sql,Oracle,Plsql,Oracle10g,我应该根据程序将学生成绩更新为“a” ChangeGrade(p_sID, p_classID) 如果该学生未注册该课程(p_classID),则会打印一条错误消息 这是表格: 注册 sID classID Grade *** ******* ***** 104 10440 B 102 10220 C ... ..... . 我应该做一个内部连接吗?以下是我所拥有的: Create or Replace ChangeG

我应该根据程序将学生成绩更新为“a”

ChangeGrade(p_sID, p_classID)

如果该学生未注册该课程(p_classID),则会打印一条错误消息

这是表格:

注册

sID    classID   Grade
***    *******   *****
104      10440     B
102      10220     C
...      .....     .
我应该做一个内部连接吗?以下是我所拥有的:

Create or Replace ChangeGrade (
  p_sID enrolling.sID%type
  p_classID enrolling.classID%type )
AS
  p_id_enrolled NUMBER;

BEGIN
  SELECT sID into p_id_enrolled 
  FROM Enrolling
  WHERE sID = p_sID
  AND classID = p_classID

  IF p_sID = p_id_enrolled THEN
    update Enrolling
    set GRADE = 'A'
    dbms_output.put_line('Student grade has been changed.')
  ELSE
    dbms_output.put_line('Student record does not exist.')
  END IF;
END;
/   

我不知道打印出来的是什么样的错误,但似乎您缺少了“;”在某些命令的末尾(在if语句中和select into之后)。

正如我在评论中提到的,您的过程中有几个地方缺少分号(行termiator)。试试这个:

CREATE OR REPLACE Procedure ChangeGrade (
  p_sID enrolling.sID%type
  p_classID enrolling.classID%type )
AS
  p_id_enrolled NUMBER;

BEGIN
   SELECT sID
     INTO p_id_enrolled
     FROM Enrolling
    WHERE sID = p_sID AND classID = p_classID;

   IF p_sID = p_id_enrolled
   THEN
      UPDATE Enrolling
         SET GRADE = 'A'
       WHERE sID = p_sID;

      DBMS_OUTPUT.put_line ('Student grade has been changed.');
   ELSE
      DBMS_OUTPUT.put_line ('Student record does not exist.');
   END IF;

 EXCEPTION 
 WHEN NO_DATA_FOUND Then
dbms_output.put_line('Student record does not exist for this class');

END;
/

你需要处理学生不在课堂上这一事实作为例外:

Create or Replace PROCEDURE ChangeGrade (
  p_sID enrolling.sID%type,
  p_classID enrolling.classID%type,
  p_grade enrolling.grade%type  )
AS
 l_enrolled NUMBER;

BEGIN
  SELECT sID INTO l_enrolled 
  FROM Enrolling
  WHERE sID = p_sID
  AND classID = p_classID;

  IF l_enrolled = p_sID THEN
    update Enrolling set GRADE = p_grade WHERE sID = p_sID and classID = p_classID;
    dbms_output.put_line('Student grade has been changed.');
  END IF;

  EXCEPTION WHEN NO_DATA_FOUND
    dbms_output.put_line('Student record does not exist for this class');
END;
/   

我还为等级添加了一个参数,因为通过它也是合乎逻辑的。

以下是代码中的问题:

  • 这个查询毫无意义:

    SELECT sID into p_id_enrolled 
      FROM Enrolling
      WHERE sID = p_sID
      AND classID = p_classID
    
    您将
    sID
    选择到
    p\u id\u registered
    中,但在
    WHERE
    子句中您过滤
    sID=p\u sID
    ,因此
    p\u id\u registered
    将始终等于
    p\u sID
    ,并且您根本不需要此select语句

  • 此update语句更新整个表:

    UPDATE Enrolling
       SET GRADE = 'A';
    
    您需要添加筛选子句以仅更新一行

  • 如果学生未注册上课,查询不会返回任何行,您将得到
    no\u DATA\u FOUND
    异常。要处理它,您需要捕获异常或计算学生数

  • 我建议使用以下方法:

    Create or Replace procedure ChangeGrade (
      p_sID enrolling.sID%type,
      p_classID enrolling.classID%type )
    AS
      cnt NUMBER;
    
    BEGIN
      SELECT count(*) into cnt
        FROM Enrolling
       WHERE sID = p_sID
         AND classID = p_classID;
    
      IF cnt = 1 THEN
        update Enrolling
           set GRADE = 'A'
         where sID = p_sID
           AND classID = p_classID;
        dbms_output.put_line('Student grade has been changed.');
      ELSE
        dbms_output.put_line('Student record does not exist.');
      END IF;
    END;
    /
    

    您还可以使用光标,然后查看该学生是否已注册该课程。如果他/她是,则更新成绩。我认为光标比
    选择X进入n
    更安全,因为当您尝试插入
    NULL
    选择NULL进入n
    ,这些错误通常很难找到。

    例如:

    CREATE OR REPLACE ChangeGrade (p_sID enrolling.sID%TYPE,
                                   p_classID enrolling.classID%TYPE)
    AS
                  CURSOR cEnrolling IS
                         SELECT     *
                         FROM       Enrolling
                         WHERE      SID = p_sID
                         AND        classID = p_classID;
    
                  rEnrolling cEnrolling%ROWTYPE;
    BEGIN
            OPEN cEnrolling;
            FETCH cEnrolling INTO rEnrolling;
                  IF cEnrolling%FOUND THEN
                          -- Student record found.
                          UPDATE Enrolling
                          SET Grade = 'A'
                          WHERE SID = rEnrolling.sId;
    
                          DBMS_OUTPUT.PUT_LINE('Student grade has been changed.');
                  ELSE
                          -- Student record not found. 
                          DBMS_OUTPUT.PUT_LINE('Student record does not exist.');
                  END IF;
            CLOSE cEnrolling;
    END;
    /
    

    那么错误是什么呢。你面临什么问题<代码>dbms\u输出。put\u行(“学生成绩已更改”)结尾缺少分号。应该是
    dbms\u output.put\u行('学生成绩已更改')在第7行获取错误:如果p_sID=p_id_已注册,则表示SQL命令未正确结束。在第2行,在p_id_中选择sID,它表示SQL语句被忽略。PL/SQL代码中的每个语句后面都必须跟有
    在第7行获取错误:如果p_sID=p_id_已注册,则表示SQL命令未正确结束。在第2行,在p_id_登记中选择sID,它表示SQL语句已被忽略。这里不需要
    executeimmediate
    。您可以说“您根本不需要这个SELECT语句”和“您将获得
    no\u DATA\u FOUND
    异常”然后包括一条SQL语句,如果不解释为什么不遵循自己的建议,则不包括异常。@MT0谢谢,更正。事实上,错过关键字的不是我,我只是从问题中复制了代码;)另外,在第一个过程参数后缺少一个逗号。我认为答案并不完全正确。当学生未注册上课时,此代码
    SELECT count(*)into cnt
    给出了一个丑陋的错误,
    ORA-01722:无效数字
    。您将永远不会得到“学生记录不存在”select查询的输出将抛出一个
    NO\u DATA\u FOUND
    异常。@MT0的问题不是处理异常,而是Op为什么出错。像往常一样,你试着超越OP的要求去思考,我对你无话可说。谢谢你的否决票。下面是一个示例“如果学生未注册课程(p_classID),则会打印错误消息。”是问题的一部分-您的过程不会这样做。(您缺少了
    过程
    关键字)。这是最简单的解决方案,但稍微解释一下OP的代码为什么不起作用就好了。@MT0。如果此处也缺少异常块。请使用您的下一票特权。@XING此解决方案是正确的,没有异常处理块,因为它执行更新并检查更新是否更新了一行(通过匹配主键)或更新了零行(当找不到学生时)-由于未使用
    SELECT
    语句,这两种可能性都不会引发
    NO\u DATA\u FOUND
    异常。
    CREATE OR REPLACE ChangeGrade (p_sID enrolling.sID%TYPE,
                                   p_classID enrolling.classID%TYPE)
    AS
                  CURSOR cEnrolling IS
                         SELECT     *
                         FROM       Enrolling
                         WHERE      SID = p_sID
                         AND        classID = p_classID;
    
                  rEnrolling cEnrolling%ROWTYPE;
    BEGIN
            OPEN cEnrolling;
            FETCH cEnrolling INTO rEnrolling;
                  IF cEnrolling%FOUND THEN
                          -- Student record found.
                          UPDATE Enrolling
                          SET Grade = 'A'
                          WHERE SID = rEnrolling.sId;
    
                          DBMS_OUTPUT.PUT_LINE('Student grade has been changed.');
                  ELSE
                          -- Student record not found. 
                          DBMS_OUTPUT.PUT_LINE('Student record does not exist.');
                  END IF;
            CLOSE cEnrolling;
    END;
    /