Зачем нужен INTO в этой функции PL/SQL, если переменная не используется?

У меня есть функция Oracle 18c PL/SQL, которую я могу использовать для поиска значений задачи в определяемом пользователем пространственном типе под названием SDE.ST_GEOMETRY.

Найдите строку с проблемной формой (пространственный тип SDE.ST_GEOMETRY)

with function check_shape(anno_shape sde.st_geometry, boundary_shape sde.st_geometry) return varchar2 
is
    v_test_result varchar2(10);                       --<--look here
begin
    select
        sde.st_intersects (boundary_shape, anno_shape)
    into                                              --<--look here
        v_test_result                                 --<--look here
    from
        dual;
    return 'no error';
exception
    when others then
        return 'error';
end;

select 
    anno.objectid, 
    anno.shape as anno_shape,
    check_shape(anno.shape, boundary.shape) as check_shape
from 
    city.boundary boundary
cross join     
    infrastr.gcsm_hc_anno anno
where 
    check_shape(anno.shape, boundary.shape) = 'error'

Я собрал эту функцию из примеров онлайн-скриптов, и она работает так, как ожидалось. С учетом вышесказанного я хочу, чтобы код был максимально простым и правильным.

Моему неопытному глазу into и v_test_result кажутся ненужными; они, кажется, ничего не делают. Функция выбирает значение в переменной, но переменная, похоже, не используется return.

Моя интуиция состоит в том, чтобы удалить эти строки:

v_test_result varchar2(10);
...
into     
    v_test_result

Но когда я удаляю эти строки, я получаю сообщение об ошибке:

with function check_shape(anno_shape sde.st_geometry, boundary_shape sde.st_geometry) return varchar2 
is
--    v_test_result varchar2(10);                       --<--look here
begin
    select
        sde.st_intersects (boundary_shape, anno_shape)
--    into                                              --<--look here
--        v_test_result                                 --<--look here
    from
        dual;
    return 'no error';
exception
    when others then
        return 'error';
end;

select 
    anno.objectid, 
    anno.shape as anno_shape,
    check_shape(anno.shape, boundary.shape) as check_shape
from 
    city.boundary boundary
cross join     
    infrastr.gcsm_hc_anno anno
where 
    check_shape(anno.shape, boundary.shape) = 'error'
ORA-06553: PLS-428: an INTO clause is expected in this SELECT statement
06553. 00000 -  "PLS-%s: %s"

Зачем нужен into в этой функции? Есть ли способ упростить функцию, удалив ее?

В PL/SQL не может быть оператора select, который не преобразует выходные данные во что-либо. Это настолько просто, насколько это возможно.

pmdba 29.04.2024 00:39
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
1
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Зачем нужен into в этой функции?

Потому что язык PL/SQL требует, чтобы оператор SELECT всегда содержал либо предложение INTO, либо предложение BULK COLLECT INTO.

В Справочнике по языку баз данных PL/SQL синтаксис оператора SELECT следующий:

select_into_statement ::=

Description of select into statement

Из чего видно, что предложение INTO или BULK COLLECT INTO является обязательным.

Если у вас нет ни одного из этих предложений, ваш код синтаксически недействителен и будет возбуждено исключение.

Есть ли способ упростить функцию, удалив ее?

Если вы выполняете запрос в области PL/SQL, нет, его нельзя удалить.

Единственный способ не использовать оператор INTO (или BULK COLLECT INTO) — это выполнить SELECT в области SQL, что потребует использования чего-то вроде EXECUTE IMMEDIATE:

WITH function check_shape(
  anno_shape     infrastr.gcsm_hc_anno.shape%TYPE,
  boundary_shape city.boundary.shape%TYPE
) return varchar2 
is
begin
  EXECUTE IMMEDIATE 'select sde.st_intersects (:1, :2) from dual'
    USING boundary_shape, anno_shape;
  RETURN 'no error';
EXCEPTION
  WHEN OTHERS THEN
    RETURN 'error';
END;
select anno.objectid, 
       anno.shape as anno_shape,
       check_shape(anno.shape, boundary.shape) as check_shape
from   city.boundary boundary
       inner join infrastr.gcsm_hc_anno anno
       on check_shape(anno.shape, boundary.shape) = 'error';

PL/SQL select требуется предложение into, но вы можете встроить запрос через loop:

with function check_shape(anno_shape sde.st_geometry, boundary_shape sde.st_geometry) return varchar2 
is
begin
    for x in (select sde.st_intersects (boundary_shape, anno_shape) from dual) loop
        return 'no error';
    end if;
exception
    when others then
        return 'error';
end;

Другие вопросы по теме