Ответ
Курсор — это объект базы данных, который позволяет приложению последовательно (построчно) обрабатывать результирующий набор данных SQL-запроса. Он предоставляет механизм для итерации по строкам, когда загрузка всего результата в память неэффективна или невозможна.
Основные типы курсоров:
- Статический (Static/Insensitive): Снимок данных на момент открытия. Не отражает изменения, сделанные другими транзакциями.
- Динамический (Dynamic): Отражает все изменения данных (вставки, обновления, удаления) в реальном времени.
- Ключевой набор (Keyset-driven): Фиксирует набор первичных ключей на момент открытия. Видит обновления существующих строк, но не вставки.
- Быстрый последовательный доступ (Forward-only): Позволяет движение только вперёд, наиболее производительный.
Практический пример (Java JDBC):
JDBC использует ResultSet в качестве курсора.
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery("SELECT id, name FROM large_table")) {
// Явное указание FETCH_SIZE для потоковой обработки
stmt.setFetchSize(100);
while (rs.next()) { // Перемещение курсора
int id = rs.getInt("id");
String name = rs.getString("name");
// Обработка строки
}
} // Автоматическое закрытие ресурсов (курсора) в try-with-resources
Зачем это нужно? Для обработки очень больших результирующих наборов, минимизируя потребление памяти на стороне клиента. Важно: курсоры потребляют ресурсы на сервере БД, поэтому их необходимо всегда явно закрывать.
Ответ 18+ 🔞
Да ты посмотри, что эти умники придумали! Ну прям как в жизни, блядь. Вот представь: ты в базу данных залез, как в огромный склад, запрос написал — и тебе вываливают десять тысяч тонн товара прямо на голову. Ты стоишь, смотришь на эту гору и думаешь: «Ну ёпта, я ща тут сдохну, пока всё это переберу». А мозги-то уже текут.
Вот тут-то, сука, на сцену и выходит курсор. Это не палочка мигающая, нет. Это такой хитрожопый управляющий, который говорит: «Расслабься, мудила. Не надо всё сразу тащить. Давай я тебе по одной штуке из этой кучи буду подавать, а?». И он прав, блядь!
Какие они бывают, эти управляющие:
- Статический (Static) — это тот тип, который, как бабушка у подъезда, один раз всё увидел и запомнил. Открыл он снимок данных и хоть ты там войну развязывай — ему похуй. Он тебе будет показывать ту самую картинку, которую увидел в момент открытия. Никаких изменений от других не видит, в своём мирке живёт.
- Динамический (Dynamic) — полная его противоположность, шизофреник ебаный. Мечется туда-сюда и орет: «О, Васька только что запись обновил! А Машка — удалила! Смотри, смотри, новая строка появилась!». Отражает всё, что происходит, в реальном времени. За ним, блядь, не уследишь.
- Ключевой набор (Keyset-driven) — уже поадекватнее. Он как участковый: запомнил всех по паспортам (первичным ключам). Кто из «паспортиков» обновил свои данные — видит. А кто новый приехал без прописки — того уже не замечает. Не его район, блядь.
- Быстрый последовательный (Forward-only) — это наш герой, работяга. Тупой, но быстрый. Движется только вперёд, как танк, и нихуя не видит по сторонам. Зато производительность у него — овердохуищная. Для простой выгрузки — то, что надо.
А вот как это выглядит в коде, на Java (JDBC):
Смотри, тут ResultSet — это и есть наш замаскированный курсор.
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery("SELECT id, name FROM large_table")) {
// Говорим: "Не грузи всё сразу, давай пачками по 100 штук, а то память лопнет"
stmt.setFetchSize(100);
while (rs.next()) { // Вот эта команда — "дай следующую строку, курсарик"
int id = rs.getInt("id");
String name = rs.getString("name");
// И вот тут мы её уже обрабатываем
}
} // А тут try-with-resources сам всё закроет, красава
Зачем весь этот цирк? Да затем, чувак, чтобы не обосраться с памятью, когда данных — хуева туча! Вместо того чтобы тянуть в оперативку целый вагон, ты его по кирпичику разбираешь. Но, блядь, помни главное: каждый открытый курсор жрёт ресурсы сервера базы, как сука. Его надо закрывать. Всегда. А то придёт админ и ебальник тебе нахуярит.