DeepEdit!

Программирование баз данных на Oracle, техническая документация, литература, статьи и публикации

  • Увеличить размер шрифта
  • Размер шрифта по умолчанию
  • Уменьшить размер шрифта

Генерирование случайных значений

Базы данных предназначены для хранения достоверных фактов; мы тщательно собираем данные, касающиеся нашего бизнеса или другой деятельности, всеми силами защищаем их и поддерживаем в целости и сохранности. Зачем нам может понадобиться нечто совершенно противоположное - непредсказуемые случайные значения? Давайте рассмотрим несколько ситуаций, в которых администратору базы данных может потребоваться генератор случайных чисел:
Вы создаете временные пароли или идентификаторы для зарегистрированных пользователей веб-сайта. Вы участвуете в разработке приложения, требующего тщательного всестороннего тестирования (производительности, масштабирования, точности и т. д.), и в рамках этого проекта вам необходимо создать набор тестов с представительными данными. Под представительными понимаются такие данные, которые каким-то образом соответствуют той сущности, которую они представляют; например, столбец с номерами счетов должен отражать формат реальных номеров, имя должно состоять из букв и т. п.
Вы хотите протестировать эффект, создаваемый некоторым важным структурным компонентом базы данных, таким как индексы. Чтобы ответить на вопросы о количестве индексов, об индексируемых столбцах, о количестве собираемых в процессе анализа гистограмм, о целесообразности использования блочной выборки (block sampling) и тому подобных, необходимы большие массивы данных, отражающих реальные ситуации. Не всегда есть возможность получить эти данные со стороны, поэтому может возникнуть потребность в их создании. В таком случае важно сгенерировать такие данные, которые достаточно случайны, но в то же время соответствуют реальным образцам.
Вы создаете инфраструктуру шифрования, и вам необходимо сгенерировать ключ. Oracle9i и последующие версии позволяют генерировать по-настоящему случайные ключи, в более ранних версиях вам придется делать это самостоятельно.
В этой главе рассказывается о том, как при помощи PL/SQL генерировать случайные значения (числовые и строковые), представляющие реальные значения. Рассматриваются способы задания начального значения, позволяющие получать случайные последовательности. Приведено множество примеров и фрагментов кода, ориентированных на создание тестовых данных (имен клиентов и сумм на их счетах) для банковского приложения, которые вы легко сможете использовать в собственных разработках.
Большинство примеров этой главы основано на использовании встроенного пакета Oracle DBMS_RANDOM. В этом пакете имеются две ключевые функции, возвращающие случайные значения:
Для чисел
Функция VALUE возвращает положительное число с плавающей точкой в диапазоне от 0 до 1 с точностью 38 знаков, например 0,034869472.
Для строк
Функция STRING возвращает случайную строку символов с указанными пользователем длиной и распределением символов.
Использование этих и других функций пакета DBMS_RANDOM будет проиллюстрировано в примерах этой главы.
Генерирование случайных чисел
Одно из наиболее распространенных применений генераторов случайных значений заключается в создании случайных чисел. Числа могут быть разными: положительными или отрицательными, целыми или дробными и т. п. Давайте начнем с простейшей разновидности - положительных чисел.
Генерирование положительных чисел
Требуется сгенерировать ряд чисел, представляющих значения остатков на счетах для наших тестовых данных. Остаток на счете может быть представлен целочисленным значением или значением с плавающей точкой с двумя разрядами в дробной части, например 12345,98. Примем для простоты, что банк не допускает перерасхода - то есть баланс не может быть отрицательным. Функция VALUE пакета DBMS_RANDOM возвращает положительное число большее или равное нулю и меньшее 1, имеющее 38 знаков после запятой. Вот как эта функция используется для получения числа:

Благодаря тому что функция имеет степень чистоты WNDS (write no database state - не менять состояние данных), ее можно вызывать прямо в операторе SELECT или внутри INSERT.
Отвлечемся ненадолго и рассмотрим приложение другого типа. Предположим, что необходимо написать программу для научных расчетов, которая считывает показания термометра и сохраняет их для последующего анализа. Набор чисел можно сформировать в таком коде:

Обратите внимание, что значения температуры совершенно случайны. Теперь представим, что их надо сохранить для анализа в будущем. Используем следующий код для записи в таблицу TEMPERATURES, имеющую такой вид:


Этот пример можно расширить, увеличив количество записываемых показаний, добавив другие источники данных (дополнительные термометры) и т. п.
Задание точности
В предыдущем примере генерировались числа с плавающей точкой с 38 знаками после запятой. Числа такого вида не очень подходят для приложения, работающего с номерами банковских счетов, которые должны иметь целочисленный формат и, как правило, фиксированное количество разрядов. Нет проблем! Изменим нашу функцию, чтобы сделать ее более полезной. Например, в следующем варианте функции возвращаемое случайное число находится в диапазоне от 1 до 100:


Увеличивая значение множителя, можно повысить разрядность получаемых случайных чисел.
Тот же принцип применим к генерированию чисел с плавающей запятой. В США значения денежных сумм принято хранить в долларах и центах. Цент равен одной сотой части доллара, следовательно, требует двух знаков после запятой. Под этот формат подходят валюты многих стран. В этом случае генерируемое случайное значение остатка должно иметь два знака в дробной части. Простейший способ достичь этого заключается в задании масштаба в функции ROUND. Добавим в нашу функцию параметр, чтобы получить более общее решение:

С этими аргументами легко можно получать случайные числа нужного формата.
Задание диапазона
Предположим, что нужно сгенерировать суммы остатков, попадающие в определенный диапазон. К примеру, банк может требовать некоторой минимальной суммы на счете, поэтому случайные значения должны быть больше допустимого минимума и, вероятно, меньше некоторого разумного максимума. Для выполнения этого требования перегруженная функция VALUE в пакете DBMS_RANDOM принимает два параметра, low и high, и возвращает значение из этого диапазона. Вот пример вызова перегруженной функции для получения случайных чисел в диапазоне от 1000 до 9999:

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


Заметьте, эта функция достаточно универсальна и удовлетворяет многим задачам по генерированию случайных чисел, таким как:
• Генерация номеров банковских счетов, которые представляются десятизначными целыми числами. Эти номера строго десятизначные, т. е. не могут содержать ведущие нули.

• Использование той же функции для генерации значений остатков на счетах, которые имеют два знака после запятой и находятся в диапазоне от 1000 (требуемый банком минимальный остаток) до 1000000 (предполагаемое максимальное значение остатка). Для генерации двух дробных разрядов параметру p_scale требуется передать значение 2.

• Использование функции в научных приложениях, например при считывании показаний высокочувствительного термометра, применяемого в атомных установках, где значения представлены тремя разрядами до и десятью разрядами после запятой (то есть числа находятся в диапазоне от 100,0000000000 до 999,9999999999):
 









jAntivirus