Какие запросы используются в базах данных
Что проверяют
Под общей формулировкой обычно скрыта проверка двух слоёв: знаете ли вы виды SQL-запросов и умеете ли правильно выполнять их из Go. Следом спрашивают про пул соединений, транзакции и защиту от SQL-инъекций.
Как отвечать
Коротко про SQL: DML (SELECT, INSERT, UPDATE, DELETE) работает с данными, DDL (CREATE, ALTER, DROP) со структурой, TCL (BEGIN, COMMIT, ROLLBACK) с транзакциями. Плюс JOIN, агрегаты с GROUP BY и подзапросы.
Основную часть отдайте Go. В стандартном database/sql вызовы различаются по тому, что возвращают:
QueryContext: много строк, результат*sql.Rows. Обязательныdefer rows.Close()и проверкаrows.Err()после циклаrows.Next();QueryRowContext: одна строка, ошибка приходит изScan, а отсутствие строки этоsql.ErrNoRows, который проверяют черезerrors.Is;ExecContext: запросы без выборки (INSERT,UPDATE,DELETE), возвращаетsql.Resultс методомRowsAffected;BeginTx: транзакция, все вызовы внутри идут черезtx, аdefer tx.Rollback()безопасен и после успешногоCommit.
Параметры передаются только плейсхолдерами: $1 в PostgreSQL, ? в MySQL. Склейка запроса через fmt.Sprintf открывает дорогу инъекциям. Контекст запроса или context.WithTimeout отменяет обращение к базе, если клиент ушёл или вышло время.
*sql.DB это пул соединений, а не одно подключение: его создают один раз на приложение и настраивают SetMaxOpenConns, SetMaxIdleConns, SetConnMaxLifetime. Для PostgreSQL часто берут pgx с pgxpool, поверх database/sql есть sqlx, а sqlc генерирует типизированный код из SQL.
Где спотыкаются
Забывают закрыть rows. Соединение не возвращается в пул, и под нагрузкой сервис упирается в лимит соединений.
Вызывают Query для UPDATE и не читают результат. Соединение снова остаётся занятым, для таких запросов нужен Exec.
Вызывают sql.Open на каждый запрос или считают, что он проверяет подключение. sql.Open только готовит пул, реальную проверку делает PingContext.