В связи с высказаным мной предположением в части 3-й и 4-й я решил модифицировать модуль базы. Изменение этого модуля повлекло модификацию всех исполнительных. Но это того стоило. Модификация состоит в том, что для вызова СУБД — зависимых запросов можно настроить однотипные процедуры, принимающие параметры на входе.
Рассмотрим функцию database.select_from_where(select, from, where), которая часто используется в процедурах для получения табличной информации:
Вызывается это благолепие командой:
Дальше всё это обрабатывается через цикл и построчно извлекаются данные:
Здесь заполняется первоначальный вызов функции fetch() для последующего снижения дублирования везде, где только возможно. Таким образом мы вырезаем половину кода из модулей исполнения и передаём им массив с данными по запросу.
Следующая функция — database.update_set_where(update, set, where) — используется для обновления данных без индексного удаления. Это ситуации, в которых нам надо изменить данные позиции / пользователя без перелапачивания документов и данные выплат по позиции:
В функцию забивается имя таблицы, имя столбца для изменения и условие обновления. Здесь можно указать ячейку с конкретным значением полей или целую группу. В случае некорректного ввода данных (например, изменилась цена на несколько категорий) информацию можно изменить очень быстро.
Функция database.delete_from_where(from, where) используется для ликвидации данных в таблицах. дабы исключить случайное уничтожение всех данных в таблице, функция создаёт строку с параметром сравнения:
И последняя, часто используемая функция — database.insert_into_values(table, fields, values) — предназначенная для вставки данных:
Как видите, во всех функциях, кроме SELECT'а, используется элементарное исполнение запроса. Прикол в том, что базы SQLite3 по окончании записи / модификации строки не выдают значение индеска, как это делает Firebird. По этой причине приходится запускать поиск индекса добавленной строки при последующем добавлении индекса в связаные таблицы.
Таким образом, все вышеуказаные функции сводят 4-6 строк на исполнение запроса в модулях бизнес-логики до 1-5 строчек на каждую. Такая оптимизация вдогонку улучшила удобочитаемость исполнительных модулей.
P.S. Маленькая просьба — если хотите передать замечание по этому циклу статей, прошу предварительно прочитать статью «Разработка микро-учётной системы на lua, часть вторая. Постановка задачи», в которой я указываю условия разработки программы и функции, которые на неё возлагаются. Учитывайте это.
Рассмотрим функцию database.select_from_where(select, from, where), которая часто используется в процедурах для получения табличной информации:
function database.select_from_where(select, from, where)
text = "SELECT " .. select .. " FROM " .. from
if where ~= nil then
text = text .. " WHERE " .. where .. " ;"
else
text = text .. " ;"
end
query = database.link()
thread = query:execute(text)
result = thread:fetch({}, "a")
return result
end
Вызывается это благолепие командой:
base = require "database"
data = base.select_from_where( "number, name" , "customer" , nil )
Дальше всё это обрабатывается через цикл и построчно извлекаются данные:
while data do
print("| № " .. data.number .. " | " .. data.name .. " | " .. data.phone .. " |" )
data = thread:fetch(data, "a")
end
Здесь заполняется первоначальный вызов функции fetch() для последующего снижения дублирования везде, где только возможно. Таким образом мы вырезаем половину кода из модулей исполнения и передаём им массив с данными по запросу.
Следующая функция — database.update_set_where(update, set, where) — используется для обновления данных без индексного удаления. Это ситуации, в которых нам надо изменить данные позиции / пользователя без перелапачивания документов и данные выплат по позиции:
function database.update_set_where(update, set, where)
text = "UPDATE " .. update .. " SET " .. set .. " WHERE " .. where .. " ;"
query = database.link()
thread = query:execute(text)
end
В функцию забивается имя таблицы, имя столбца для изменения и условие обновления. Здесь можно указать ячейку с конкретным значением полей или целую группу. В случае некорректного ввода данных (например, изменилась цена на несколько категорий) информацию можно изменить очень быстро.
Важное замечание при создании процедур, управляющих изменением данных базы:
Когда работаете с базами Вам необходимо корректно обрабатывать следующие аспекты:
Без этих правил запись / чтение данных будет стопориться при каждой ошибке запроса.
- Соблюдение изоляции текстовых аргументов запроса (чаще всего одинарной кавычкой, но зависит от СУБД);
- Соблюдение пространства между ключевыми словами (SELECT, WHERE, FROM и прочих из языка SQL) и данными запроса;
- Соблюдение порядка запроса и изолирующих знаков — сначала идут ключевые слова, заключившие данные в своих блоках, затем завершаем дело точкой с запятой.
- В случае изменения больших объёмов однотипных данных (запрос на внос — вынос данных, создание / изменение документа и прочее, что передаётся в едином логическом блоке) рекомендуется использовать механизм транзакций. Но это в случае превышения суммарного объёма записей свыше 10000 штук.
Без этих правил запись / чтение данных будет стопориться при каждой ошибке запроса.
Функция database.delete_from_where(from, where) используется для ликвидации данных в таблицах. дабы исключить случайное уничтожение всех данных в таблице, функция создаёт строку с параметром сравнения:
function database.delete_from_where(from, where)
text = "DELETE FROM " .. from .. " WHERE " .. where .. " ;"
query = database.link()
thread = query:execute(text)
end
И последняя, часто используемая функция — database.insert_into_values(table, fields, values) — предназначенная для вставки данных:
function database.insert_into_values(table, fields, values)
text = "INSERT INTO " .. table .. " ( " .. fields .. " ) VALUES ( " .. values .. ") ;"
query = database.link()
thread = query:execute(text)
end
Как видите, во всех функциях, кроме SELECT'а, используется элементарное исполнение запроса. Прикол в том, что базы SQLite3 по окончании записи / модификации строки не выдают значение индеска, как это делает Firebird. По этой причине приходится запускать поиск индекса добавленной строки при последующем добавлении индекса в связаные таблицы.
Таким образом, все вышеуказаные функции сводят 4-6 строк на исполнение запроса в модулях бизнес-логики до 1-5 строчек на каждую. Такая оптимизация вдогонку улучшила удобочитаемость исполнительных модулей.
P.S. Маленькая просьба — если хотите передать замечание по этому циклу статей, прошу предварительно прочитать статью «Разработка микро-учётной системы на lua, часть вторая. Постановка задачи», в которой я указываю условия разработки программы и функции, которые на неё возлагаются. Учитывайте это.
Поделиться с друзьями
Комментарии (5)
napa3um
02.06.2016 10:12+1Используйте db:prepare для параметрических запросов вместо конструирования запросов из строк. Для получения индекса последней вставленной записи используйте db:lastid.
hantenellotf
02.06.2016 10:13Это относится к LuaSQL-SQLite?
napa3um
02.06.2016 10:18Да, похоже, не db:lastid, а db:last_insert_rowid. Вы в документацию принципиально не подглядываете?
PerlPower
При всем моем уважении, ваша лабораторная работа затянулась.