← Назад к вопросам

Какие знаешь виды Statement в SQL?

1.3 Junior🔥 191 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Виды Statement в SQL и Java

Statement — это объект в Java (из пакета java.sql), который используется для выполнения SQL запросов к базе данных. Существует несколько видов Statement, каждый из которых предназначен для различных сценариев.

1. Statement (простой Statement)

Statement — базовый интерфейс для выполнения простых SQL запросов без параметров.

import java.sql.Statement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

public class SimpleStatementExample {
    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/mydb", "user", "password")) {
            
            // Создание Statement
            Statement stmt = conn.createStatement();
            
            // Выполнение SELECT
            String query = "SELECT id, name, email FROM users WHERE age > 18";
            ResultSet rs = stmt.executeQuery(query);
            
            while (rs.next()) {
                System.out.println("ID: " + rs.getInt("id"));
                System.out.println("Name: " + rs.getString("name"));
                System.out.println("Email: " + rs.getString("email"));
            }
            
            // Выполнение INSERT
            String insertSql = "INSERT INTO users (name, email, age) VALUES ('John', 'john@example.com', 30)";
            int rows = stmt.executeUpdate(insertSql);
            System.out.println("Rows inserted: " + rows);
            
            // Выполнение UPDATE
            String updateSql = "UPDATE users SET age = 31 WHERE name = 'John'";
            int updatedRows = stmt.executeUpdate(updateSql);
            System.out.println("Rows updated: " + updatedRows);
            
            // Выполнение DELETE
            String deleteSql = "DELETE FROM users WHERE age < 18";
            int deletedRows = stmt.executeUpdate(deleteSql);
            System.out.println("Rows deleted: " + deletedRows);
            
            stmt.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Характеристики:

  • Простой в использовании
  • Уязвим к SQL injection атакам
  • Подходит для простых запросов без параметров
  • Медленнее, чем PreparedStatement (нет кеширования плана)

2. PreparedStatement (подготовленный запрос)

PreparedStatement — интерфейс для выполнения параметризованных запросов. Более безопасен и эффективен.

import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.DriverManager;

public class PreparedStatementExample {
    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/mydb", "user", "password")) {
            
            // Параметризованный запрос с ?
            String query = "SELECT id, name, email FROM users WHERE age > ? AND name = ?";
            PreparedStatement pstmt = conn.prepareStatement(query);
            
            // Установка параметров
            pstmt.setInt(1, 18); // Первый параметр
            pstmt.setString(2, "John"); // Второй параметр
            
            ResultSet rs = pstmt.executeQuery();
            
            while (rs.next()) {
                System.out.println("ID: " + rs.getInt("id"));
                System.out.println("Name: " + rs.getString("name"));
            }
            
            // INSERT с параметрами
            String insertQuery = "INSERT INTO users (name, email, age) VALUES (?, ?, ?)";
            PreparedStatement insertStmt = conn.prepareStatement(insertQuery);
            insertStmt.setString(1, "Alice");
            insertStmt.setString(2, "alice@example.com");
            insertStmt.setInt(3, 25);
            
            insertStmt.executeUpdate();
            
            // UPDATE с параметрами
            String updateQuery = "UPDATE users SET email = ? WHERE id = ?";
            PreparedStatement updateStmt = conn.prepareStatement(updateQuery);
            updateStmt.setString(1, "newemail@example.com");
            updateStmt.setInt(2, 1);
            
            updateStmt.executeUpdate();
            
            pstmt.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Характеристики:

  • Защита от SQL injection
  • Кеширование плана запроса (быстрее при повторении)
  • Автоматическая сериализация параметров
  • Рекомендуется для всех параметризованных запросов

3. CallableStatement (для хранимых процедур)

CallableStatement — интерфейс для вызова хранимых процедур и функций в БД.

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import java.sql.DriverManager;

public class CallableStatementExample {
    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/mydb", "user", "password")) {
            
            // Вызов хранимой процедуры
            String storedProc = "{ call sp_GetUserById(?, ?) }";
            CallableStatement cstmt = conn.prepareCall(storedProc);
            
            // Установка IN параметров
            cstmt.setInt(1, 5); // IN параметр
            
            // Регистрация OUT параметра
            cstmt.registerOutParameter(2, Types.VARCHAR);
            
            // Выполнение процедуры
            cstmt.execute();
            
            // Получение результатов
            String resultName = cstmt.getString(2); // OUT параметр
            System.out.println("User name: " + resultName);
            
            cstmt.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Примером хранимой процедуры может быть:

CREATE PROCEDURE sp_GetUserById(
    IN userId INT,
    OUT userName VARCHAR(100)
)
BEGIN
    SELECT name INTO userName FROM users WHERE id = userId;
END;

Характеристики:

  • Для вызова хранимых процедур и функций
  • Поддержка IN, OUT, INOUT параметров
  • Может возвращать результаты через OUT параметры

4. Батч (Batch) операции

Batch — выполнение нескольких запросов одной командой для оптимизации производительности.

import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.DriverManager;

public class BatchStatementExample {
    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/mydb", "user", "password")) {
            
            // Batch с простым Statement
            Statement stmt = conn.createStatement();
            
            stmt.addBatch("INSERT INTO users (name, email, age) VALUES ('User1', 'user1@example.com', 20)");
            stmt.addBatch("INSERT INTO users (name, email, age) VALUES ('User2', 'user2@example.com', 25)");
            stmt.addBatch("INSERT INTO users (name, email, age) VALUES ('User3', 'user3@example.com', 30)");
            
            int[] results = stmt.executeBatch();
            System.out.println("Batch executed. Results: " + java.util.Arrays.toString(results));
            
            // Batch с PreparedStatement (рекомендуется)
            String insertQuery = "INSERT INTO users (name, email, age) VALUES (?, ?, ?)";
            PreparedStatement pstmt = conn.prepareStatement(insertQuery);
            
            pstmt.setString(1, "Alice");
            pstmt.setString(2, "alice@example.com");
            pstmt.setInt(3, 28);
            pstmt.addBatch();
            
            pstmt.setString(1, "Bob");
            pstmt.setString(2, "bob@example.com");
            pstmt.setInt(3, 32);
            pstmt.addBatch();
            
            pstmt.setString(1, "Charlie");
            pstmt.setString(2, "charlie@example.com");
            pstmt.setInt(3, 27);
            pstmt.addBatch();
            
            int[] batchResults = pstmt.executeBatch();
            System.out.println("Batch prepared executed. Results: " + java.util.Arrays.toString(batchResults));
            
            stmt.close();
            pstmt.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Характеристики:

  • Значительно повышает производительность
  • Отправляет несколько запросов одной командой
  • Требует осторожности с обработкой ошибок

5. Методы выполнения

Каждый Statement поддерживает три основных метода выполнения:

public class ExecutionMethodsExample {
    public static void demonstrateExecutionMethods(Connection conn) throws SQLException {
        PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users");
        
        // 1. executeQuery() — для SELECT запросов
        ResultSet rs = pstmt.executeQuery();
        while (rs.next()) {
            System.out.println(rs.getString("name"));
        }
        
        // 2. executeUpdate() — для INSERT, UPDATE, DELETE
        PreparedStatement updateStmt = conn.prepareStatement("UPDATE users SET age = ? WHERE id = ?");
        updateStmt.setInt(1, 30);
        updateStmt.setInt(2, 1);
        int rowsAffected = updateStmt.executeUpdate();
        System.out.println("Rows affected: " + rowsAffected);
        
        // 3. execute() — универсальный метод (возвращает boolean)
        Statement stmt = conn.createStatement();
        boolean hasResults = stmt.execute("SELECT * FROM users");
        if (hasResults) {
            ResultSet result = stmt.getResultSet();
        } else {
            int updateCount = stmt.getUpdateCount();
        }
    }
}

Таблица сравнения Statement типов

ХарактеристикаStatementPreparedStatementCallableStatement
ИспользованиеПростые запросыПараметризованныеХранимые процедуры
SQL injectionУязвимЗащищёнЗащищён
Кеширование планаНетДаДа
ПроизводительностьНизкаяВысокаяВысокая
ПараметрыНетIN параметрыIN, OUT, INOUT
СложностьПростотаСредняяВысокая

Лучшие практики

  1. Всегда используйте PreparedStatement вместо Statement для параметризованных запросов
  2. Используйте try-with-resources для автоматического закрытия ресурсов
  3. Используйте Batch операции для вставки большого количества данных
  4. Используйте CallableStatement для сложной логики в БД
  5. Всегда закрывайте Statement и ResultSet после использования
  6. Используйте ORM фреймворки (Hibernate, JPA) вместо прямого JDBC для сложных проектов
Какие знаешь виды Statement в SQL? | PrepBro