Проблемы SQL, требующие курсоров - SQL problems requiring cursors

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

Параллельная обработка может быть на порядки быстрее последовательной.

Ограничения

В этой статье применяются следующие ограничения:

  • Термин «курсор» включает в себя все поведение, подобное курсору. Например, используя цикл в сценарии оболочки, который перебирает однорядные SQL-запросы или выход многострочных SQL-запросов ведет себя как курсор и не достигает цели истинной обработки на основе наборов в пределах база данных.
  • Весь SQL на основе наборов должен быть ANSI SQL. Ряд поставщиков предоставляют чрезвычайно мощные проприетарные расширения. Цель состоит в том, чтобы избежать таких расширений в пользу ANSI SQL.
  • Решение должно быть обобщаемым. В одном или нескольких приведенных ниже примерах конкретные значения могут использоваться в демонстрационных целях, но любое решение должно масштабироваться до любого числа, которое возможно в пределах возможностей программного обеспечения базы данных и машинных ресурсов.

Пример: вставка строк на основе количества в самой таблице

В таблице ниже представлены типы мрамора. Четыре текстовых столбца представляют четыре характеристики мрамора. Каждая характеристика имеет два значения, всего 16 типов шариков.

Столбец «количество» показывает, сколько у нас есть шариков этого типа. Задача состоит в том, чтобы создать вторую таблицу, содержащую по одной строке для каждого шарика этого типа. Таким образом, целевая таблица будет иметь четыре текстовых столбца и всего 40 + 20 + 20 + 10 + ... + 10 + 5 = 270 строк.

Исходная таблица:

  КОЛИЧЕСТВО ТЕКСТУРА ВНЕШНИЙ ВИД ФОРМА ЦВЕТ ---------- ---------- ---------- ---------- ----- 40 гладкий блестящий круглый синий 20 гладкий блестящий деформированный синий 20 гладкий тусклый круглый синий 10 гладкий тусклый деформированный синий 20 грубый блестящий круглый синий 10 грубый блестящий деформированный синий 10 грубый матовый круглый синий 5 грубый тусклый деформированный синий 40 грубый тусклый деформированный красный 20 грубый тусклый круглый красный 20 грубый блестящий деформированный красный 10 грубый блестящий круглый красный 20 гладкий матовый деформированный красный 10 гладкий матовый круглый красный 10 гладкий блестящий деформированный красный 5 гладкий блестящий круглый красный

Таблица для создания:

ВИД ТЕКСТУРЫ ЦВЕТ ФОРМЫ ---------- ---------- ---------- ----- гладкий блестящий круглый синий - 1 гладкий блестящий круглый синий - - 2 ... - и так далее гладкий блестящий круглый синий - 40 гладкий блестящий деформированный синий - 1 гладкий блестящий деформированный синий - 2 ... - и так далее гладкий блестящий деформированный синий - 20 ... - и так далее гладкий блестящий круглый красный - 1 гладкий блестящий круглый красный - 2 гладкий блестящий круглый красный - 3 гладкий блестящий круглый красный - 4 гладкий блестящий круглый красный - 5

Решение в виде курсора

Создать целевую таблицу с помощью курсора довольно просто.

объявить  курсор c является Выбрать * из marbles_seed;начинать  за р в c петля    за я в 1..р.количество петля      вставлять в шарики значения (        р.текстура,        р.внешний вид,        р.форма,        р.color_actual      );    конец петля;  конец петля;конец;

Решение на SQL без зацикливания

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

Таблица номеров

Решение требует промежуточного стола. В таблице есть один столбец типа ЧИСЛО, в котором есть значения от 0 до любого необходимого количества строк. В этом обсуждении мы ограничим его одним миллионом строк. Код выглядит следующим образом: Настройка:

Создайте стол numbers_seed ( п номер(1) );Создайте стол числа ( п номер(7));вставлять в numbers_seed значения ( 0 );вставлять в numbers_seed значения ( 1 );вставлять в numbers_seed значения ( 2 );вставлять в numbers_seed значения ( 3 );вставлять в numbers_seed значения ( 4 );вставлять в numbers_seed значения ( 5 );вставлять в numbers_seed значения ( 6 );вставлять в numbers_seed значения ( 7 );вставлять в numbers_seed значения ( 8 );вставлять в numbers_seed значения ( 9 );вставлять в числаВыбрать n6.п * 100000 +       n5.п * 10000 +       n4.п * 1000 +       n3.п * 100 +       n2.п * 10 +       n1.п * 1 пиз numbers_seed n1,       numbers_seed n2,       numbers_seed n3,       numbers_seed n4,       numbers_seed n5,       numbers_seed n6

Таблицу номеров можно создавать параллельно.

Ядро решения

Предположим, что приведенная выше таблица типов мрамора называется marbles_seed, а целевая таблица - marbles. Код, который генерирует необходимые 270 строк:

вставлять в шарики(м.текстура, м.внешний вид, м.форма, м.color_actual)Выбрать м.текстура,       м.внешний вид,       м.форма,       м.color_actual  из marbles_seed м,       числа п куда м.количество > п.п

База данных может обрабатывать эту вставку параллельно без участия программиста.