yiisoft/yii2 · error · yii\base\NotSupportedException
yii\db\mssql\conditions\InConditionBuilder::buildSubqueryInC
Error message
yii\db\mssql\conditions\InConditionBuilder::buildSubqueryInCondition is not supported by MSSQL.
What it means
yii\db\mssql\conditions\InConditionBuilder::buildSubqueryInCondition() (framework/db/mssql/conditions/InConditionBuilder.php:29) overrides the base builder to reject composite IN conditions where $columns is an array and $values is a Query — e.g. ['in', ['col1','col2'], $subquery]. SQL Server does not support row-value (tuple) comparisons like (a,b) IN (SELECT x,y ...), so Yii throws NotSupportedException instead of emitting invalid SQL. A single column with a subquery falls through to the parent implementation and works.
Source
Thrown at framework/db/mssql/conditions/InConditionBuilder.php:29
use yii\base\NotSupportedException;
use yii\db\Expression;
/**
* {@inheritdoc}
*
* @author Dmytro Naumenko <d.naumenko.a@gmail.com>
* @since 2.0.14
*/
class InConditionBuilder extends \yii\db\conditions\InConditionBuilder
{
/**
* {@inheritdoc}
* @throws NotSupportedException if `$columns` is an array
*/
protected function buildSubqueryInCondition($operator, $columns, $values, &$params)
{
if (is_array($columns)) {
throw new NotSupportedException(__METHOD__ . ' is not supported by MSSQL.');
}
return parent::buildSubqueryInCondition($operator, $columns, $values, $params);
}
/**
* {@inheritdoc}
*/
protected function buildCompositeInCondition($operator, $columns, $values, &$params)
{
$quotedColumns = [];
foreach ($columns as $i => $column) {
if ($column instanceof Expression) {
$column = $column->expression;
}
$quotedColumns[$i] = strpos($column, '(') === false ? $this->queryBuilder->db->quoteColumnName($column) : $column;
}
$vss = [];View on GitHub (pinned to 66f00d18a2)
Solutions
- Rewrite as a correlated EXISTS: ->andWhere(['exists', (new Query())->select('1')->from('selected s')->where('s.o = t.order_id AND s.l = t.line')])
- Replace IN-subquery with a JOIN against the subquery and DISTINCT selection
- If the composite key can be reduced to one expression (e.g. a computed key), filter on that single column instead
Example fix
// before (works on MySQL/PG, throws NotSupportedException on MSSQL)
$query->andWhere(['in', ['order_id', 'line'], (new Query())->select(['order_id', 'line'])->from('selected_rows')]);
// after (portable)
$query->andWhere(['exists', (new Query())
->select('1')
->from('selected_rows sr')
->where('sr.order_id = t.order_id AND sr.line = t.line'),
]); Defensive patterns
Strategy: validation
Validate before calling
function isMssqlCompositeInSubquery($columns, $values, string $driverName): bool
{
return $driverName === 'sqlsrv'
&& is_array($columns)
&& $values instanceof \yii\db\Query;
}
if (isMssqlCompositeInSubquery($columns, $values, $db->driverName)) {
throw new \RuntimeException('Composite IN with subquery is not supported by MSSQL — use EXISTS.');
}
$query->andWhere(['in', $columns, $values]); Type guard
function isCompositeColumns($columns): bool
{
return is_array($columns) && count($columns) > 1;
} Try / catch
try {
$rows = $query->all();
} catch (\yii\db\NotSupportedException $e) {
// composite IN + subquery on MSSQL — rewrite as EXISTS
\Yii::error($e->getMessage(), __METHOD__);
throw new \RuntimeException('Rewrite this IN-subquery as EXISTS for SQL Server.', 0, $e);
} Prevention
- Prefer correlated EXISTS over IN-subqueries when targeting multiple DBMSs
- Test query code against every driver in the support matrix, not just dev's MySQL/PostgreSQL
- Remember single-column IN with a subquery IS supported on MSSQL — only the array-columns form throws
When it happens
Trigger: ->where(['in', ['order_id','line'], (new Query())->select(['o','l'])->from('selected')]) on a SQL Server connection; queries written and tested on MySQL/PostgreSQL (whose builders support composite IN with subqueries) then executed on MSSQL; composite-key matching against junction tables.
Common situations: Cross-DBMS applications where dev uses MySQL and production SQL Server; composite primary keys on junction/mapping tables; upgrading a project to run on MSSQL without auditing IN conditions.
Related errors
- Subquery for EXISTS operator must be a Query object.
- Operator '$operator' requires two operands.
- Table not found: $tableName
- There is not sequence associated with table '$tableName'.
- Table not found: $table
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/a79c03025c8caf43.
Report an issue: GitHub.