Значимое выражение

Функция

Определение значения.

Спецификация

                 
< арифметический оператор >::=
{+ | - | * | / | %}
< элемент выражения >::=
< символьное выражение >::=
< символьная конкатенация >::=
< байтовое выражение >::=
< байтовая конкатенация >::=
< дата-время выражение >::=

Синтаксические правила

  1. Первым символом лексемы, следующей за унарным знаком операции, не может быть знак плюс или минус.

  2. Если тип < значения > – символьная/байтовая строка, то < значимое выражение > может включать только операцию конкатенации. Тип результата – также символьная/байтовая строка.

    Конструкция

    select 'Фирма: ' ||  make || ' модель: ' || model from auto;
    |Фирма: FORD модель: MERCURY COMET GT V8|
     …

    эквивалентна:

    select 'Фирма: ' +  make + ' модель: ' + model from auto;
  3. Использование в < значимом выражении > типа данных BLOB не допускается.

  4. При использовании в < значимом выражении > типа данных DATE допускаются операции добавления (вычитания) интервалов даты.

    select sysdate+to_date('01','mm');
    select sysdate,
           (sysdate+to_date('01','mm')) - to_date('05','yy');
    |24.04.2003:14:26:51.00 |24.05.1998:14:26:51.00 |
  5. Если у обоих операндов точный числовой тип, то и результат будет иметь точный числовой тип, определяемый следующим образом:

    • если один из операндов имеет тип DECIMAL, то тип результата – DECIMAL;

    • если оба операнда целые, то результат будет иметь целый тип;

    • если один из операндов имеет тип INT, то тип результата – INT;

    • если один из операндов имеет тип BIGINT, то тип результата – BIGINT;

    • если оба операнда типа SMALLINT, тип результата – SMALLINT.

  6. Если < значимое выражение > является < числовым выражением >, то в операциях сравнения и присвоения допускается использовать строковый литерал без оператора преобразования.

    create or replace table tst (si smallint,i int, bi bigint, d double, nm numeric);
    Эти запросы эквивалентны:
    insert into tst (si,i,bi,d,nm) values (12, 3658, 5688854, 45.e+3, 56.099);
    insert into tst (si,i,bi,d,nm) values ('12', '3658', '5688854', '45.e+3', '56.099');
    
    Эти запросы эквивалентны:
    select count(*) from auto where year='70';
    select count(*) from auto where year=70;
    select count(*) from auto where year= cast '70' as int;
  7. В случае арифметических действий над аргументами типа DECIMAL типом результата берется DECIMAL(30,10).

  8. Если тип одного из операндов приближенный, то тип результата тоже будет приближенным. Типом данных результата будет DOUBLE, если хотя бы один из операндов имеет тип DOUBLE.

  9. Если < значение > равно NULL, то результатом < значимого выражения > тоже будет NULL.

    create table tab1 (i1 int, i2 smallint, r real);
    insert into tab1 values (1, 5, 56.8);
    insert into tab1 values (1, NULL, 56.8);
    select * from tab1;
    
    |1|5   |56.7999992|
    |1|NULL|56.7999992|
    select (i1+i2)/r from tab1;
    |0.1056338 |
    |NULL      |
  10. Если операция не указана, то результат < значимого выражения > берется из < значения >.

  11. Когда < значимое выражение > применяется к строке таблицы, то указание столбца этой таблицы есть его значение в этой строке.

  12. Двухместные арифметические знаки «+», «-», «*», «/» обозначают сложение, вычитание, умножение, деление соответственно. Если делитель равен 0, будет зафиксирована исключительная ситуация.

  13. Унарный плюс не меняет операнд. Унарный минус меняет знак ненулевого числа на противоположный.

  14. Если тип результата – точный числовой, то возможны следующие варианты:

    • если операция – не деление, и результат ее точно не представляется значением результирующего типа, то будет зафиксирована исключительная ситуация;

    • если операция – деление, и результат ее представляется значением результирующего типа с потерей одной или более значащих цифр, то будет зафиксирована исключительная ситуация.

  15. Выражения внутри круглых скобок вычисляются первыми, и, если порядок вычисления не задан круглыми скобками, унарные операции выполняются перед умножением/делением, умножение/деление – перед сложением/вычитанием, операции одного уровня выполняются слева направо.

    create table tab1 (i1 int, i2 int, i3 int, i4 int);
    insert into tab1 values (1,2,3,4);
    select * from tab1;
    |1 |2 |3 |4 |
    select (i1 * i2) + (i3 * i4) from tab1;
    |14|
    select i1 * i2 + i3 * i4 from tab1;
    |14|
    select i1 * (i2 + i3) * i4 from tab1;
    |20|
    select ((length(make)+ year) * (length(model) -sqrt(4)))/100 from auto;
  16. Глубина стека для обработки выражений 50.

  17. При обработке числовой константы, если не удалось ее преобразовать к типу DECIMAL, делается попытка преобразовать ее к типу DOUBLE.

Общие правила

  1. Если используются арифметические операторы, то результат < значимого выражения > получается путем применения операторов к значениям операндов.

  2. Если какой-либо из операндов равен NULL, результат NULL.

  3. Арифметические операторы применимы только к числовым операндам.

  4. При невозможности вычислить < значимое выражение > (например, деление на нуль или переполнение числа) фиксируется исключительная ситуация.

  5. Если арифметическая ошибка выявляется при выполнении агрегатной функции, то фиксируется исключительная ситуация.

  6. Если эти алгоритмы обработки являются неприемлемыми при обработке данных, необходимо принять дополнительные меры, такие как:

    • включить проверку на нуль в операциях деления и установить желаемое (по смыслу) значение результата в таких случаях;

      create table tab1 (i1 dec, i2 dec not null);
      insert into tab1 values (1,2);
      insert into tab1 values (1,0);
      select * from tab1;
      |1.0 |2.0 |
      |1.0 |0.0 |
      select case i2 when 0 then 'Деление на нуль' 
                     else cast i1/i2 as char 
             end 
        from tab1;
      |0.5|

      Деление на нуль

      или

      select case i2 when 0 then null
                     else i1/i2 
             end 
        from tab1;
    • добавить дополнительные предикаты для управления NULL-значениями (подобно CHECK или атрибут NOT NULL при определении свойств столбца таблицы), например:

      check (c1*c2 is not NULL and c1*c2 >5000);

Примеры

Значимое выражение – < спецификация значения >:

select sysdate;
select * from person where name=user;
select rownum, count(*) from person group by name;

Значимое выражение – < имя столбца >:

select distinct make from auto;

Значимое выражение – < агрегатная функция >:

select default( make) from auto;
select count(*) from person where name='ADKINSON';

Значимое выражение – < значение последовательности >:

select ("my_seq".nextval +1000)/34;
select * from auto 
 where personid = (select "my_seq".currval);

Значимое выражение – (< значимое выражение >):

select (default( make)) from auto;
select (sysdate);

Значимое выражение – < подзапрос >:

select model from auto
 where auto.personid=
(select personid from person where auto.personid=person.personid and name='ANDERSON');
|OLDSMOBILE 98|
|PLUS 8       |
 …

Значимое выражение – < спецификация типа >:

select count(*) from auto
 where cast make as char(1) in ( 'A', 'B', 'C')
 group by cast make as char(1) ;
|98   |
|10   |
|175  |

Значимое выражение – < спецификация значения по условию >:

select case year when 70 then 'Год выпуска 1970'
                 else 'Год выпуска 1971' 
       end,
       count(*)
from auto group by year;
|Год выпуска 1970 |465 |
|Год выпуска 1971 |535 |

Значимое выражение – < числовое выражение >:

select make, mod(length(make), 3), year+1900
  from auto fetch first 2;
|FORD   |1 |1971 |
|ALPINE |0 |1970 |

Значимое выражение – < строковое выражение >:

select
case year when 70 then 'Год выпуска 1970'
else 'Год выпуска 1971' end
|| ' : ' || to_char( count(*), '999')
from auto group by year;
|Год выпуска 1970 : 465 |
|Год выпуска 1971 : 535 |

Значимое выражение – < дата-время выражение >:

select sysdate + to_date('17', 'dd');

Значимое выражение – < логическое выражение >:

select count(*) from auto
 where (length(make)-10) >0 or  (year-70)=0
 group by length(make)-10 fetch first 3;
|3  |
|14 |
|74 |