Что такое курсор в базе данных?

Ответ

Курсор — это объект базы данных, который позволяет приложению последовательно (построчно) обрабатывать результирующий набор данных 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 сам всё закроет, красава

Зачем весь этот цирк? Да затем, чувак, чтобы не обосраться с памятью, когда данных — хуева туча! Вместо того чтобы тянуть в оперативку целый вагон, ты его по кирпичику разбираешь. Но, блядь, помни главное: каждый открытый курсор жрёт ресурсы сервера базы, как сука. Его надо закрывать. Всегда. А то придёт админ и ебальник тебе нахуярит.