【问题标题】:Stored procedure in PL/SQL to insert new record in tablePL/SQL 中的存储过程在表中插入新记录
【发布时间】:2015-05-30 00:03:09
【问题描述】:

我需要创建一个 PL/SQL 存储过程来向 tblCity2 表添加一条记录。 tblCity2 示例:

+-------------+--------+-------------+------------+
|     NAME    | CAPITAL|  POPULATION | STATE_CODE |
+-------------+--------+-------------+------------+
| Monterrey   |   Y    |   2015000   |      MX19  |
| Mazatlan    |   N    |    199830   |      MX25  |
| Guadalajara |   Y    |   2325000   |      MX14  |
+-------------+--------+-------------+------------+

该程序接收 4 个参数:城市名称、城市是否为首都、城市人口和州名。状态名称取自表 tblState2:

+------+-----------------------+---------+-----------+
| CODE |         NAME          | POP1990 | AREA_SQMI |
+------+-----------------------+---------+-----------+
| MX02 | Baja California Norte | 1660855 | 28002.325 |
| MX03 | Baja California Sur   |  317764 | 27898.191 |
| MX18 | Nayarit               |  824643 | 10547.762 |
+------+-----------------------+---------+-----------+

该过程调用一个存储函数,将状态名称传递给它,该函数返回状态代码,然后将其与其他参数一起用于在 tblCity2 中插入新记录。

我已经开始了一些代码,但我不确定下一步:

PROCEDURE question2
(i_StateName IN TBLSTATE2.NAME%TYPE,
i_CityName IN TBLCITY2.NAME%TYPE,
i_CityCapital IN TBLCITY2.CAPITAL%TYPE,
i_CityPopulation IN TBLCITY2.POPULATION%TYPE);

FUNCTION create_city
(i_StateName IN TBLSTATE2.NAME%TYPE)
RETURN [something??]
INSERT INTO TBLCITY2 VALUES;
END question2;

我还需要插入一个匿名程序块来调用该过程。它是否正确?我可以在与上面相同的代码中运行此代码还是必须单独运行?

BEGIN
question2(i_StateName, i_CityName, i_CityCapital, i_CityPopulation);
END;

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    您可以编写一个带有SELECT .. INTO 语句的函数,以根据状态名称获取状态代码。 INTO 子句允许您指定存储选择语句返回值的变量。

    FUNCTION getStateCode
      (i_StateName IN TBLSTATE2.NAME%TYPE) 
    RETURN tblState2.CODE%TYPE IS
      V_CODE tblState2.CODE%TYPE;
    BEGIN
        SELECT CODE
        INTO   V_CODE
        FROM   tblState2
        WHERE  NAME = i_StateName;
    
        RETURN V_CODE;
    END;
    

    请注意,查询必须恰好返回一行。如果返回 0 行或多于 1 行,则会失败并显示 No Data Found 或 Too Many Rows。

    可以通过将查询嵌入到 SELECT FROM DUAL 查询中来捕获 No Data Found 错误:

    FUNCTION getStateCode
      (i_StateName IN TBLSTATE2.NAME%TYPE) 
    RETURN tblState2.CODE%TYPE IS
      V_CODE tblState2.CODE%TYPE;
    BEGIN
        SELECT (SELECT CODE
                FROM   tblState2
                WHERE  NAME = i_StateName)
        INTO   V_CODE
        FROM   DUAL
    
        RETURN V_CODE;
    END;
    

    该函数返回代码,然后可以在过程中的插入语句中使用该代码:

    PROCEDURE insertCity
      (i_StateName      IN TBLSTATE2.NAME%TYPE,
       i_CityName       IN TBLCITY2.NAME%TYPE,
       i_CityCapital    IN TBLCITY2.CAPITAL%TYPE,
       i_CityPopulation IN TBLCITY2.POPULATION%TYPE) IS
    
    BEGIN
    
        INSERT INTO TBLCITY2 (NAME, CAPITAL, POPULATION, STATE_CODE)
        VALUES(
          i_CityName,
          i_CityCapital,
          i_CityPopulation,
          getStateCode(i_StateName)
        );
    
    END;
    

    然后你可以像你一样调用这个过程:

    BEGIN
      insertCity(i_StateName, i_CityName, i_CityCapital, i_CityPopulation);
    END;
    

    就像@APC 在 cmets 中提到的那样,在函数内部修改数据是不好的做法。这样做的原因是,也可以从查询中调用函数,这意味着当您只想查询数据时可能会意外修改数据。

    所以在上面的设置中,有一个只查询数据的函数。该函数可用于 SQL 或(在本例中)过程中。该过程可以安全地修改数据,因为它无论如何都不能在选择查询中使用。

    【讨论】:

    • OP 想要一个函数来检索state_code 的查找,而不是在插入语句中使用标量游标。如您所知,使用 FUNCTION 更改系统状态被认为是不好的做法(没有双关语)。带有 PROCEDURE 的原始实现更好。
    • @APC 我同意你关于改变状态的功能,我想我只是误解了这个问题。我删除了所有以前的内容并编写了一个新内容,其中一个函数返回状态名称,然后在过程中使用该函数而不是子选择。
    猜你喜欢
    • 2018-02-03
    • 2020-04-24
    • 1970-01-01
    • 2013-11-13
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多