1.2.8. Вычисляемые поля

Для иллюстрации вычисляемых полей я всегда привожу пример с покупками в магазине, потому что он наиболее наглядный. Допустим, что у нас есть количество товара и его цена, а нужно рассчитать сумму денег, затраченных на каждый товар. Для решения задачи нужно создать таблицу из четырех полей: название, цена, количество, сумма. Давайте удалим старую таблицу TestTable и создадим новую, которая позволит решить поставленную проблему:

CREATE TABLE TestTable 
(
  vcName varchar(50),
  iCost money,
  iNumber float,
  iSumm AS (iCost * iNumber)
)

В данном примере у нас создается таблица из 4 полей:

  • "vcName" – наименование товара. Для этого поля мы указали тип varchar и ограничили ввод 50 символами;
  • "iCost" – цена товара. Для хранения цены лучше всего подходит специализированный тип money;
  • "iNumber" – количество товара. Здесь можно использовать целочисленный тип, но я выбрал число с плавающей запятой, т.е. дробный (float). Это для того, чтобы можно было использовать количество в килограммах, когда число получается с запятой;
  • "iSumm" - самое интересное кроется именно в этой колонке, потому что у нее нет типа. Вместо этого стоит ключевое слово AS и формула, по которой должно рассчитываться значение. В данном случае в качестве формулы указано умножение значение в колонке "iCost" на "iNumber".

Давайте наполним таблицу строками значений и посмотрим на результат:

Листинг 1.7. Наполнение таблицы значениями

INSERT INTO TestTable(vcName, iCost, iNumber)
VALUES('Хлеб', 7.5, 2)

INSERT INTO TestTable(vcName, iCost, iNumber)
VALUES('Молоко', 17, 3)

INSERT INTO TestTable(vcName, iCost, iNumber)
VALUES('Печенье', 46, 0.5)

INSERT INTO TestTable(vcName, iCost, iNumber)
VALUES('Морковь', 12, 0.8) 

INSERT INTO TestTable(vcName, iCost, iNumber)
VALUES('Картофель', 15, 5) 

SELECT * FROM TestTable

Что выполняется в листинге, нас пока не особо интересует. Достаточно понимать, что в нем в таблицу добавляется пять строк, а в последней строке запрашиваются все строки из таблицы.

В листинге 1.16 во время заполнения таблицы значениями, я заполнял все поля в строках, кроме последнего поля "iSumm". Но не смотря на это, в последнем поле есть значения и они являются результатом перемножения цены товара, на его количество.

Особое внимание нужно уделить строке 4, где показана цена моркови. Я в таблицу заносил значение 0.8, но сервер показал, что там находиться число 0.80000000000000004. Почему? Это погрешность Intel процессора и того, как он хранит вещественные числа. Если вы работали с такими языками программирования как C++, то должны знать, что целое число 1 никогда не будет равно вещественному 1.0, потому что процессор может воспринять вещественную единицу как число 1.00000000000000001, которое уже отличается от целого числа 1. Но если округлить вещественное число, то тогда результат будет равным.

В большинстве языков программирования и в базах данных эта погрешность не убирается на уровне отображения, хотя это достаточно легко. Например, SQL сервер мог бы обрезать последний символ.

Учитывайте эту особенность в своих проектах. Если необходимо, чтобы не было погрешности, то лучше всего использовать вместо типа float тип numeric и явно указывать необходимую точность.

На этот раз на экране нет никакой погрешности, потому что она может быть только в последнем разряде вещественного числа, а мы используем только первые два разряда. Единственное, программа при отображении вещественного числа не отображает ноль перед запятой, т.е. вместо числа "0.8" отображается ".8". Но это уже недочет отображения, а не ошибка и не погрешность, ведь расчеты все верные.

Предыдущая глава

1.2.8. Опции индексов

О блоге

Программист, автор нескольких книг серии глазами хакера и просто блогер. Интересуюсь безопасностью, хотя хакером себя не считаю

Обратная связь

Без проблем вступаю в неразборчивые разговоры по e-mail. Стараюсь отвечать на письма всех читателей вне зависимости от страны проживания, вероисповедания, на русском или английском языке.

Пишите мне