У меня есть база данных с «книгами» (рассказами для детей), и было бы чрезвычайно информативно иметь количество слов для каждого слова в книгах.
Я выяснил, как получить количество слов для каждого слова, используя:
SELECT SUM
(
ROUND
(
(LENGTH(pageText) - LENGTH (REPLACE (pageText, "Word", "")))
/LENGTH("Word")
)
) FROM pages WHERE bookID = id;
Который прекрасно работает для подсчета слов. НО это требует, чтобы я просмотрел каждую книгу, вытащил каждое слово и провел через эту функцию (я сохранил его как хранимую процедуру).
У меня есть таблица, которая содержит каждое слово, без дубликатов.
Мой вопрос: есть ли способ сделать какой-то цикл «для каждого» в таблице «Слова», используя мою хранимую процедуру?
то есть. передайте хранимой процедуре идентификатор книги и слово и запишите результат. Делать каждое слово, для каждой книги. Таким образом, экономя мне много ручного времени ... Это то, что я должен делать со стороны БД? Должен ли я попробовать это с PHP вместо этого?
Честно говоря, любой вклад очень ценится!
источник
count(explode(' ', $pageText))+1
. Или что-то более сложное для обработки нескольких пробелов между словами, возможно, с участиемpreg_replace('/\s+/', ' ', $pageText)
1+split(/\s+/, $pageText)
. 1, потому что количество пробелов, а не слов.Ответы:
Создайте вторую процедуру, которая использует два вложенных курсора.
Курсоры в хранимых процедурах позволяют вам делать что-то совсем не похожее на SQL: выполнять итерацию по результирующему набору по одной строке за раз, помещая значения выбранных столбцов в переменные и работая с ними.
Их легко неправильно использовать, поскольку SQL, будучи декларативным, а не процедурным, обычно не должен нуждаться в операциях типа «для каждого», но в этом случае он выглядит как действительное приложение.
Как только вы освоите их, курсоры станут проще, но они требуют структурированного подхода в своем поддерживающем коде, который не всегда интуитивен.
Недавно я предоставил некоторый довольно стандартный «шаблонный» код для работы с курсором для вызова хранимой процедуры в ответе о переполнении стека , и я буду очень заимствовать из этого ответа ниже.
Использование курсора требует некоторого стандартного стандартного кода для его окружения.
Вы
SELECT
хотите передать значения, откуда бы вы их ни получали (это может быть временная таблица, базовая таблица или представление и могут включать в себя вызовы хранимых функций), а затем вызывать вашу процедуру existinf с этими значениями.Вот синтаксически правильный пример необходимого кода с комментариями, объясняющими, что делает каждый компонент.
В этом примере используются 2 столбца для передачи 2 значений вызываемой процедуре.
Обратите внимание, что события здесь происходят в определенном порядке по определенной причине. Переменные должны быть объявлены в первую очередь, курсоры должны быть объявлены до их обработчиков продолжения, и циклы должны следовать за всеми этими вещами.
Вы не можете делать вещи не по порядку, поэтому, когда вы вкладываете один курсор в другой, вы должны сбросить область действия процедуры, вложив дополнительный код внутри
BEGIN
...END
блоков внутри тела процедуры; например, если вам нужен второй курсор внутри цикла, вы просто объявите его внутри цикла, внутри другогоBEGIN
...END
блока.источник
BEGIN
/END
и неявно закрываются, когда выпадают из области видимости ... поэтому закрывать курсоры не обязательно. На практике я считаю это ненужным и не включаю его, но для полноты я добавилCLOSE
утверждение в ответ.