Loading...
Loading...
Covers direct database work in Bitrix — Application::getConnection(), Connection, MysqliConnection, SqlHelper, SqlExpression, raw SQL queries via query()/queryExecute()/queryScalar(), transactions (startTransaction/commitTransaction/rollbackTransaction), DDL and schema migrations, bulk operations (insertBatch, addMulti), additional connections via the connections section in .settings.php. Applied when ORM is insufficient — bulk operations, raw SQL, migrations, working with external databases, and building custom queries. Key terms — Connection, SqlHelper, SqlExpression, transaction, raw SQL, bulk insert, DDL, migration.
npx skill4agent add bxmaximum/bitrix-framework-skills bitrix-databasebitrix-ormquery()ConditionTreedeleteByFilterinstall/index.phpupdater.phpUPSERTREPLACEGROUP BYuse Bitrix\Main\Application;
use Bitrix\Main\DB\Connection;
/** @var Connection $db */
$db = Application::getConnection(); // default
$db = Application::getConnection('default');
$analytics = Application::getConnection('analytics'); // additional.settings.php'connections' => [
'value' => [
'default' => [
'className' => \Bitrix\Main\DB\MysqliConnection::class,
'host' => 'db',
'database' => 'bx',
'login' => 'bx',
'password' => '***',
'options' => \Bitrix\Main\DB\Connection::DEFERRED, // 2 — connect on first query
],
'analytics' => [
'className' => \Bitrix\Main\DB\PgsqlConnection::class,
'host' => 'pg',
'database' => 'analytics',
'login' => 'ro',
'password' => '***',
'options' => \Bitrix\Main\DB\Connection::DEFERRED,
],
'redis' => [
'className' => \Bitrix\Main\Data\RedisConnection::class,
'host' => 'redis',
'port' => 6379,
'persistent'=> true,
'serializer'=> \Redis::SERIALIZER_IGBINARY,
'compression' => \Redis::COMPRESSION_LZ4,
],
],
'readonly' => true,
],optionsConnection::PERSISTENT = 1Connection::DEFERRED = 23\Bitrix\Main\DB\MysqliConnectionmysqli\Bitrix\Main\DB\PgsqlConnection\Bitrix\Main\DB\MssqlConnection\Bitrix\Main\DB\OracleConnection\Bitrix\Main\Data\MemcacheConnectionMemcachedConnectionRedisConnection\Bitrix\Main\Data\HsphpReadConnectionSELECT$rs = $db->query('SELECT ID, NAME FROM b_user WHERE ACTIVE = "Y"');
$rs = $db->query('SELECT ID FROM b_user', 10); // LIMIT 10
$rs = $db->query('SELECT ID FROM b_user', 0, 100); // LIMIT 0, 100
while ($row = $rs->fetch())
{
$id = (int)$row['ID'];
}
foreach ($rs as $row) { /* ... */ }
$id = $db->queryScalar('SELECT COUNT(*) FROM b_user WHERE ACTIVE = "Y"');fetch()Bitrix\Main\Type\DateTimefetchRaw()$result->getSelectedRowsCount()$result->getFields()$result->getResource()mysqli_resultResult$rs = $db->query('SELECT ID, ACTIVE, DATE_REGISTER FROM b_user');
$rs->setConverters(['DATE_REGISTER' => static fn ($v) => $v ? strtotime($v) : null]);
$rs->addFetchDataModifier(static function (array $row): array {
$row['ACTIVE_BOOL'] = $row['ACTIVE'] === 'Y';
return $row;
});$id = $db->add('my_table', [
'NAME' => 'example',
'CONTENT' => $raw, // automatically escaped
]);
$lastId = $db->addMulti('my_table', [
['NAME' => 'a', 'CONTENT' => '1'],
['NAME' => 'b', 'CONTENT' => '2'],
]);
$db->queryExecute(
'UPDATE my_table SET NAME = "' . $db->getSqlHelper()->forSql($name) . '" WHERE ID = ' . (int)$id
);addaddMultiIMPORTANT: theparameter in$bindsdoes not create prepared statements — these are only placeholders for LOBs in some drivers. Protect against SQL injections viaquery/queryScalar/queryExecuteorSqlExpression.SqlHelper
$h = $db->getSqlHelper();
$h->quote('table.id'); // `table`.`id`
$h->forSql($userInput); // escapes quotes
$h->convertToDb($value); // 'v' | 'NULL' | '123'
$h->convertToDbString(null); // ''
$h->convertToDbString('long', 5); // 'long ' (truncated)
$h->convertToDbInteger('x'); // 0
$h->convertToDbInteger(1e10, 4); // 2147483647 — 4 byte limit
$h->convertToDbFloat(1.2345, 1); // '1.2'
$h->convertToDbDate(new \Bitrix\Main\Type\Date('01.01.2025')); // '2025-01-01'
$h->convertToDbDateTime(new \Bitrix\Main\Type\DateTime());
$h->getCurrentDateTimeFunction(); // NOW()
$h->addSecondsToDateTime(60, $h->quote('c')); // DATE_ADD(`c`, INTERVAL 60 SECOND)
$h->addDaysToDateTime(30); // DATE_ADD(NOW(), INTERVAL 30 DAY)
$h->getConcatFunction($h->quote('a'), "'-'", $h->quote('b'));
$h->getIsNullFunction($h->quote('a'), 0); // IFNULL(`a`, 0)
$h->getMatchFunction($h->quote('body'), $h->convertToDb('bitrix')); // MATCH ... AGAINSTquoteconvertToDbprepareMerge*[$sql] = $h->prepareMerge(
'b_user_counter',
['USER_ID', 'SITE_ID', 'CODE'],
insertFields: ['USER_ID' => 1, 'SITE_ID' => 's1', 'CODE' => 'visits', 'CNT' => 1],
updateFields: ['CNT' => new \Bitrix\Main\DB\SqlExpression('?# + ?i', 'CNT', 1)],
);
$db->queryExecute($sql);prepareMergeValuesprepareMergeSelectprepareMergeMultipleREPLACE INTOuse Bitrix\Main\DB\SqlExpression;
$sql = new SqlExpression(
'SELECT * FROM ?# WHERE (ID = ?i OR ID > ?f) AND NAME = ?s AND CREATED > ?',
'b_user',
1,
1.23,
'admin',
new \Bitrix\Main\Type\Date('01.01.2025'),
);
$db->query($sql);
echo (string)$sql; // compiled SQL?Date/DateTimenullNULL?s?i?f?#?vVALUES(...)DateDateTime?'2025-01-01 00:00:00'?s$db = Application::getConnection();
$db->startTransaction();
try {
$db->queryExecute('...');
$db->commitTransaction();
} catch (\Throwable $e) {
$db->rollbackTransaction();
throw $e;
}startTracker()startFileLog($path)$tracker = \Bitrix\Main\Application::getConnection()->startTracker();
$tracker->startFileLog($_SERVER['DOCUMENT_ROOT'] . '/mysql_debug.sql');
// ... queries ...
$queries = $tracker->getQueries();
$tracker->stop();$DBDebugToFilestart.phpPgsqlConnectionbitrix-postgresql/local/php_interface/after_connect_d7.phpsql_modeConnectionPoolbitrix-project-structure