【问题标题】:PL/SQL Function, how to use SELECT INTO clause to declare variables from an existing table?PL/SQL 函数,如何使用 SELECT INTO 子句从现有表中声明变量?
【发布时间】:2022-12-11 11:51:04
【问题描述】:

我想创建一个 PL/SQL 函数,根据姓名从现有表“家谱”(Familienbaum) 中计算任何人的年龄。该表具有所需的值 Name、BirthYear (Geburtsjahr)、YearOfDeath (Sterbejahr) 等。

现在我想用两种方式计算这个人的年龄:

  1. 如果 Person 有 YearOfDeath,则应从 YearofDeath 中减去 BirthYear 来计算
  2. 如果人员没有 YearOfDeath,则应从 Oracle SQL Server 的当前系统年份中减去 BirthYear

    到目前为止,我已经尝试使用 SELECT INTO 子句来声明从表 Family Tree (Familienbaum) 计算所需的变量:

    CREATE OR REPLACE FUNCTION BerechneAlter(Person VARCHAR2)
    RETURN INTEGER IS 
    BEGIN
    SELECT Name, Sterbejahr, Geburtsjahr FROM Familienbaum
    WHERE Person = Name;
    RETURN (CASE 
            WHEN Sterbejahr IS NULL THEN (year(curDate()) - Geburtsjahr)
            WHEN Sterbejahr IS NOT NULL THEN (Sterbejahr - Geburtsjahr)
            END);
    END BerechneAlter;
    

    SELECT INTO 子句给我带来了很多问题,有人知道语法中需要更改什么吗?

    我也尝试过使用游标,但它似乎比需要的更复杂:

    create or replace FUNCTION BerechneAlter(Person VARCHAR2)
    RETURN INTEGER IS 
    Sterbejahr INTEGER; 
    Geburtsjahr INTEGER;
    
    CURSOR SJ IS SELECT familienbaum.sterbejahr FROM familienbaum WHERE familienbaum.name=Person;
    CURSOR GJ IS SELECT familienbaum.geburtsjahr FROM familienbaum WHERE familienbaum.name=Person;
    
    BEGIN
    
    OPEN SJ; 
    FETCH SJ INTO Sterbejahr;
    CLOSE SJ;
    
    OPEN GJ;
    FETCH GJ INTO Geburtsjahr;
    CLOSE GJ;
    
    RETURN (CASE
            WHEN Sterbejahr IS NULL THEN (2022 - Geburtsjahr)
            WHEN Sterbejahr IS NOT NULL THEN (Sterbejahr - Geburtsjahr)
            END);
    END BerechneAlter;
    

【问题讨论】:

    标签: function plsql select-into


    【解决方案1】:

    如果您在匿名块或函数或过程等中使用 SQL SELECT 语句(在 PL/SQL 中 - 在 BEGIN 和 END 关键字之间),您必须选择 INTO 某些内容,以便 PL/SQL 可以利用变量来保存您的结果从查询。重要的是要注意这里,如果您选择多个列(通过“SELECT Name, Sterbejahr, Geburtsjahr”),您必须指定多个变量或一个记录以将查询结果插入其中。

    例如:

    SELECT 1 
    INTO v_dummy 
    FROM dual;
    
    SELECT 1, 2 
    INTO v_dummy, v_dummy2 
    FROM dual;
    

    还值得指出的是,如果您的 SELECT , ... FROM... 将返回多行,PL/SQL 将抛出错误。您应该只希望从 SELECT INTO 中检索 1 行数据。

    在你的情况下,它看起来像这样(注意 - 我还没有确认你的逻辑是否正确,还要注意我不知道你的数据类型所以你也必须处理那个位):

    CREATE OR REPLACE FUNCTION BerechneAlter(p_person VARCHAR2)
    RETURN INTEGER IS 
    
    v_name VARCHAR2(100);
    v_sterbejahr VARCHAR2(100);
    v_geburtsjahr VARCHAR2(100)
    
    BEGIN
    
    SELECT Name, Sterbejahr, Geburtsjahr 
    INTO  v_name, v_sterbejahr, v_geburtsjahr 
    FROM Familienbaum
    WHERE Name = p_person;
    
    RETURN (CASE 
            WHEN v_sterbejahr IS NULL THEN (year(curDate()) - v_geburtsjahr)
            WHEN v_sterbejahr IS NOT NULL THEN (v_sterbejahr - v_geburtsjahr)
            END);
    END BerechneAlter;
    

    【讨论】:

    • 感谢您的回答和解释,我将尝试您为每个需要的变量进行特定选择的方式!现在我找到了另一个解决方案,可能比需要的要复杂一些,尽管根据需要声明游标并获取它们。
    • YEARCURDATE 不是有效的 Oracle 函数,您需要 EXTRACT(YEAR FROM SYSDATE)
    • 如果返回的数据行超过 1 个,则 CURSOR 很有用。如果您仅在 WHERE 子句中使用名称,请小心。您可以有多个数据行在 Name 中具有相同的值
    • @AmyGrange 我现在已经尝试过了,它在没有名称变量的情况下工作得很好,因为在计算中不需要它,谢谢你的帮助!
    • @MT0 也感谢您的帮助,我将 year(CurDate()) 替换为 2022,因为它不起作用,但这绝对是更好的选择!
    【解决方案2】:

    我认为函数的逻辑过于复杂。你可以在一条SQL语句中获取数据并计算年龄,所以只需要一个var。

    create or replace function get_age(p_name varchar2) return number
    is
      l_aelter number;
    begin
    
      select nvl(sterbejahr, to_char(sysdate, 'YYYY')) - geburtsjahr aelter
        into l_aelter
        from familienbaum
       where name = p_name;
    
     return l_aelter;
    end;
    

    如果不需要使用 plsql,您可能希望使用独立的 SQL 语句来执行您需要的所有计算:

    select nvl(sterbejahr, to_char(sysdate, 'YYYY')) - geburtsjahr aelter
      from familienbaum
     where name = p_name;
    

    【讨论】:

    • 此任务需要使用 plsql,但我也会尝试使用不太复杂的版本!感谢您的意见 :)
    猜你喜欢
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 2017-03-29
    相关资源
    最近更新 更多