idetodospoca
idetodospoca

Reputation: 93

ORA-01422 when returning timestamp

I have the following table

CREATE TABLE Vehicle_Location 
(
    id_park INTEGER CONSTRAINT nn_vehicle_location_id_park NOT NULL,
    id_vehicle VARCHAR(255),
    parkedtime TIMESTAMP NOT NULL,
    CONSTRAINT pk_vehicle_location_id_vehicle PRIMARY KEY (id_vehicle)
);

And I'm trying to return one timestamp with the following procedure

create or replace FUNCTION GETBICYCLEPARKEDTIME(id_vehicle VARCHAR)
RETURN TIMESTAMP AS
    refTime TIMESTAMP;
BEGIN
    Select "PARKEDTIME" into refTime 
    from "VEHICLE_LOCATION" 
    where "ID_VEHICLE" = id_vehicle;
    RETURN refTime;
END;

However I'm getting an error:

ORA-01422 : exact fetch returns more than requested number of rows

even though from my understanding I don't see how more than one row could be selected with the above procedure.

Upvotes: 1

Views: 98

Answers (3)

William Robertson
William Robertson

Reputation: 16001

Another approach, if you really want parameters to have the same names as table columns, would be to prefix the parameter name using dot notation:

create or replace function getbicycleparkedtime(id_vehicle varchar2)
    return timestamp
as
    reftime timestamp;
begin
    select parkedtime into reftime 
    from   vehicle_location l
    where  l.id_vehicle = getbicycleparkedtime.id_vehicle;

    return reftime;
end;

Here, l.id_vehicle explicitly refers to the table column and getbicycleparkedtime.id_vehicle refers to function parameter.

This can become quite verbose though, so it is more usual to name parameters using some convention which is different from column names. Some common naming patterns would give p_id_location (p for "parameter"), in_id_location (for an in parameter), idLocation or locationId (assuming column names use underscores).

Double-quoting is only needed for non-standard names that would otherwise cause parsing issues because they are reserved words, or begin with numbers, contain punctuation etc, which should be rare (this may be needed for cross-platform portability, or systems like SAP where tables can have names like SAPSMP./BIC/A011DAP). It is considered poor practice to use double-quoting when not absolutely necessary.

Use of upper/lower/mixed case is a style preference, but as a programmer I recommend that you pick one style that works best for you and stick to it.

Upvotes: 1

Popeye
Popeye

Reputation: 35900

There is an issue with the select query.

It is returning more than one record with given WHERE condition:

Select "PARKEDTIME" into refTime from "VEHICLE_LOCATION" where "ID_VEHICLE" = id_vehicle;

Try to restrict the WHERE clause to return only one record.

You can use more conditions in the WHERE clause or use DISTINCT or use GROUP BY and AGGREGATE function.

Cheers!!

Upvotes: 0

APC
APC

Reputation: 146239

PL/SQL is not case-sensitive. So this line is your problem:

where "ID_VEHICLE" = id_vehicle

As identifiers "ID_VEHICLE" and id_vehicle are identical. (Double-quotes only make identifiers case-sensitive when the identifier is not all caps.) So the WHERE clause resolves both to the closest identifier in scope, which is the column name. Consequently your WHERE clause is equivalent to where 1 = 1. So your query returns every row in the table.

The solution is to make the parameter distinct. That's why it's common practice to use a prefix when naming parameters:

create or replace FUNCTION GETBICYCLEPARKEDTIME(p_id_vehicle VARCHAR)
RETURN TIMESTAMP AS
    refTime TIMESTAMP;
BEGIN
    Select "PARKEDTIME" into refTime 
    from "VEHICLE_LOCATION" 
    where "ID_VEHICLE" = p_id_vehicle;
    RETURN refTime;
END;

Upvotes: 5

Related Questions