在Oracle 12

时间:2017-03-03 15:20:32

标签: oracle stored-procedures plsql

我主要是.NET程序员,偶尔会构建MS SQL Server存储过程。

我需要在Oracle中构建一个过程,根据一个或多个参数选择并返回一些记录。我已经尝试过建一个,但已经挫败了。

以下是我想要创建的示例:

CREATE OR REPLACE PROCEDURE P_TS_COLLISIONS_SEARCH(
        county IN VARCHAR2,
        township IN VARCHAR2,
        col_MRN IN VARCHAR2,
        answer OUT VARCHAR2)

AS
BEGIN
    SELECT COLLISION_MASTER_RECORD_NUMBER, CITY, ROAD_NAME
      INTO answer
      FROM DWOBDEV.OBIEE_TS_COLLISION_FACT_VW
    WHERE  COLLISION_MASTER_RECORD_NUMBER = col_MRN
    AND    TOWNSHIP = township
    AND    COUNTY = county;

END P_TS_COLLISIONS_SEARCH;

我收到这些错误:

  

错误(9,5):PL / SQL:忽略SQL语句错误(11,7):PL / SQL:   ORA-00947:值不够

我如何在Oracle 12中构建它?

2 个答案:

答案 0 :(得分:1)

你有几个问题。

  • 您正在选择三列INTO到一列。如果使用此选项返回单行,则必须将列数与选定的变量数相匹配。
  • 您正在选择结果中的ID,但您已将其作为输入值。重新选择它将是多余的。
  • 此外,您似乎已经传入了一个ID,目前还不清楚这是否是PK,如果是,您将不需要查询其他值。只传入一个ID参数来获取一个特定的行然后另一个proc来获取其他参数以匹配其他列值会更有意义。

这是你的proc的一个版本。如果您打算返回多行,则需要更改以返回光标。使用文档/网络搜索查找示例。

create table OBIEE_TS_COLLISION_FACT_VW
(collision_master_record_number number,
 county varchar2(50),
 township varchar2(50),
 city  varchar2(50),
 road_name varchar2(50));

insert into obiee_ts_collision_fact_vw values (1, 'WINCHESTER',     'SPRINGFIELD', 'MOSCOW', 'STATION');

CREATE OR REPLACE PROCEDURE P_TS_COLLISIONS_SEARCH(
    county IN VARCHAR2,
    township IN VARCHAR2,
    col_MRN IN VARCHAR2,
    city_o OUT VARCHAR2,
    road_name_o OUT VARCHAR2)
AS
BEGIN
    SELECT CITY, ROAD_NAME
      INTO city_o, road_name_o
      FROM OBIEE_TS_COLLISION_FACT_VW
    WHERE  COLLISION_MASTER_RECORD_NUMBER = col_MRN
    AND    TOWNSHIP = township
    AND    COUNTY = county;

END P_TS_COLLISIONS_SEARCH;

declare
    l_id number := 1;
    l_township VARCHAR2(50) := 'TOWNSHIP';
    l_county VARCHAR2(50) := 'COUNTY';
    l_city varchar2(50);
    l_road_name varchar2(50);
begin
    P_TS_COLLISIONS_SEARCH(l_county, l_township, l_id, l_city, l_road_name);
    dbms_output.put_line(l_city||'|'||l_road_name);
end;

答案 1 :(得分:0)

有点猜测,因为我不知道你想要什么样的输出,但也许这个:

create or replace procedure p_ts_collisions_search
    ( p_col_mrn   obiee_ts_collision_fact_vw.collision_master_record_number%type
    , p_township  obiee_ts_collision_fact_vw.township%type
    , p_county    obiee_ts_collision_fact_vw.county%type )
as
    rc sys_refcursor;
begin
    open rc for
        select collision_master_record_number
             , city
             , road_name
        from   obiee_ts_collision_fact_vw
        where  collision_master_record_number = p_col_mrn
        and    township = p_township
        and    county = p_county;

    dbms_sql.return_result(rc);
end;

请注意,我已使用p_为我的参数添加了前缀,以区别于数据库列,因为and township = township并未取得多大成就。 (另一种方法是用程序名称标记它们,例如p_ts_collisions_search.township。)

虚拟数据:

create view obiee_ts_collision_fact_vw
as
select 1 as collision_master_record_number
     , 'London' as city
     , 'Bond Street' as road_name
     , 'West End' as township
     , 'Lalaland' as county
from dual;

SQL * Plus中的演示:

SQL> exec p_ts_collisions_search(1, 'West End', 'Lalaland');

PL/SQL procedure successfully completed.

ResultSet #1

COLLISION_MASTER_RECORD_NUMBER CITY   ROAD_NAME
------------------------------ ------ -----------
                             1 London Bond Street

然而,它无处不在,因为客户需要能够处理隐含的结果:

SQL> call p_ts_collisions_search(1, 'West End', 'Lalaland');
call p_ts_collisions_search(1, 'West End', 'Lalaland')
     *
ERROR at line 1:
ORA-29478: Implicit result cannot be returned through this statement.
ORA-06512: at "SYS.DBMS_SQL", line 2785
ORA-06512: at "SYS.DBMS_SQL", line 2779
ORA-06512: at "WILLIAM.P_TS_COLLISIONS_SEARCH", line 17

或者,您可以通过out参数显式返回结果集:

create or replace procedure p_ts_collisions_search
    ( p_col_mrn   obiee_ts_collision_fact_vw.collision_master_record_number%type
    , p_township  obiee_ts_collision_fact_vw.township%type
    , p_county    obiee_ts_collision_fact_vw.county%type
    , p_results   out sys_refcursor )
as
begin
    open p_results for
        select collision_master_record_number
             , city
             , road_name
        from   obiee_ts_collision_fact_vw
        where  collision_master_record_number = p_col_mrn
        and    township = p_township
        and    county = p_county;
end;

演示:

SQL> var results refcursor
SQL> set autoprint on
SQL> exec p_ts_collisions_search(1, 'West End', 'Lalaland', :results);

PL/SQL procedure successfully completed.

COLLISION_MASTER_RECORD_NUMBER CITY   ROAD_NAME
------------------------------ ------ -----------
                             1 London Bond Street