Oracle SQL"精确提取返回超过请求的行数"

时间:2014-12-01 20:18:00

标签: sql oracle

我正在运行一些Oracle SQL并收到错误“ORA-01422:精确提取返回超过请求的行数”。我理解为什么通常会抛出这个错误,但是我正在请求一行,实际上只返回了一行。 (我无法为此创建一个SQL小提琴,因为我一直收到一个错误,即我的架构创建语法不正确,尽管它在SQL Plus中成功运行)

我的代码如下。该函数创建成功,不会抛出任何错误。但是,当我尝试运行验证码时,我收到上述错误。手动运行select语句只返回一行,即使错误声明返回了多行。我的代码导致此错误有什么问题?

数据库架构:

create table Employee 
(
    fname varchar(15),
    minit varchar(1),
    lname varchar(15),
    ssn char(9),
    bdate date,
    address varchar(30),
    sex varchar(1)  CHECK(sex = 'M' or sex = 'F'),
    salary number   CHECK(salary >= 20000 and salary <= 100000),
    super_ssn char(9),
    dno number  DEFAULT 0,
    constraint EMPPK
        primary key(ssn),
    constraint EMPSUPERVRFK
        foreign key(super_ssn) references Employee(ssn)
            ON DELETE SET NULL
);

create table Department 
(
    dname varchar(15)   NOT NULL,
    dnumber number,
    mgr_ssn char(9)     DEFAULT '000000000',
    mgr_start_date date,
    constraint DEPTPK
        primary key(dnumber),
    constraint DEPTMGRFK
        foreign key(mgr_ssn) references Employee(ssn)
            ON DELETE SET NULL
);

insert into Employee values ('James','E','Borg','888665555','10-NOV-1937','450 Stone, Houston, TX','M',55000,null,1);
insert into Employee values ('Franklin','T','Wong','333445555','08-DEC-1955','638 Voss, Houston, TX','M',40000,'888665555',5);
insert into Employee values ('John','B','Smith','123456789','09-JAN-1965','731 Fondren, Houston, TX','M',30000,'333445555',5);
insert into Employee values ('Jennifer','S','Wallace','987654321','20-JUN-1941','291 Berry, Bellaire, TX','F',43000,'888665555',4);
insert into Employee values ('Alicia','J','Zelaya','999887777','19-JAN-1968','3321 Castle, Spring, TX','F',25000,'987654321',4);
insert into Employee values ('Ramesh','K','Narayan','666884444','15-SEP-1962','975 Fire Oak, Humble, TX','M',38000,'333445555',5);
insert into Employee values ('Joyce','A','English','453453453','31-JUL-1972','5631 Rice, Houston, TX','F',25000,'333445555',5);
insert into Employee values ('Ahmad','V','Jabbar','987987987','29-MAR-1969','980 Dallas, Houston, TX','M',25000,'987654321',4);

insert into Department values ('Research',5,'333445555','22-MAY-1988');
insert into Department values ('Administration',4,'987654321','01-JAN-1995');
insert into Department values ('Headquarters',1,'888665555','19-JUN-1981');

功能(创建没有错误):

create or replace function getManagerNameDnameFunc(DNAME in department.dname%type)
    return varchar
is
    name varchar(50);
begin
    name := '';

    select e.fname || ' ' || e.lname into name from employee e, department d
    where d.dname = DNAME and d.mgr_ssn = e.ssn;

    return(name);

    exception
        when NO_DATA_FOUND then
            dbms_output.put_line('No data found');
            return(name);
end;
/
show errors

测试代码:

declare
    rs varchar(10);
    pr varchar(10);
begin
    rs := 'Research';
    pr := 'Printing';
    dbms_output.put_line('Manager of Research department is ' || getManagerNameDnameFunc(rs));
    dbms_output.put_line('Manager of Printing department is ' || getManagerNameDnameFunc(pr));
end;
/

select e.fname || ' ' || e.lname from employee e, department d where d.dname = 'Research' and d.mgr_ssn = e.ssn;的确切输出(此名称是应为输出的研究部门经理的名称):

E.FNAME||''||E.LNAME
-------------------------------
Franklin Wong

1 个答案:

答案 0 :(得分:3)

问题是函数参数的名称。在您的查询中,当您编写

where d.dname = DNAME

我假设您的目的是将dname表中的Department与传入的dname进行比较。但是,这不是您的代码所做的事情。由于右侧标识符不合格,因此Oracle首先尝试将其解析为其中一个表中列的名称。由于dname表格中有department列,因此dname指的是where d.dname = d.DNAME 。所以,你实质上是编写了一个无操作的

p_

一个常见的解决方案是提出一个标准约定,用于命名参数和不与列名冲突的局部变量。就个人而言,我使用l_create or replace function getManagerNameDnameFunc(p_dname in department.dname%type) return varchar is name varchar(50); begin select e.fname || ' ' || e.lname into name from employee e, department d where d.dname = p_dname and d.mgr_ssn = e.ssn; 的局部变量作为前缀,这是一个非常常见的惯例。

select e.fname || ' ' || e.lname 
  into name 
  from employee e, department d
 where d.dname = getManagerNameDnameFunc.DNAME 
   and d.mgr_ssn = e.ssn;

不太常见的是,您可以使用过程名称

明确地为标识符添加前缀
{{1}}