yiisoft/yii2 · error · Exception

Oracle does not support ON UPDATE clause.

Error message

Oracle does not support ON UPDATE clause.

What it means

Oracle foreign keys support only the ON DELETE referential action; ON UPDATE does not exist in Oracle DDL. yii\db\oci\QueryBuilder::addForeignKey() therefore builds the ALTER TABLE ... FOREIGN KEY ... ON DELETE clause and throws yii\db\Exception as soon as a non-null $update option is passed.

Source

Thrown at framework/db/oci/QueryBuilder.php:185

        $this->db->createCommand('CREATE SEQUENCE "' . $tableSchema->sequenceName . '" START WITH ' . $value
            . ' INCREMENT BY 1 NOMAXVALUE NOCACHE')->execute();
    }

    /**
     * {@inheritdoc}
     */
    public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null)
    {
        $sql = 'ALTER TABLE ' . $this->db->quoteTableName($table)
            . ' ADD CONSTRAINT ' . $this->db->quoteColumnName($name)
            . ' FOREIGN KEY (' . $this->buildColumns($columns) . ')'
            . ' REFERENCES ' . $this->db->quoteTableName($refTable)
            . ' (' . $this->buildColumns($refColumns) . ')';
        if ($delete !== null) {
            $sql .= ' ON DELETE ' . $delete;
        }
        if ($update !== null) {
            throw new Exception('Oracle does not support ON UPDATE clause.');
        }

        return $sql;
    }

    /**
     * {@inheritdoc}
     */
    protected function prepareInsertValues($table, $columns, $params = [])
    {
        list($names, $placeholders, $values, $params) = parent::prepareInsertValues($table, $columns, $params);
        if (!$columns instanceof Query && empty($names)) {
            $tableSchema = $this->db->getSchema()->getTableSchema($table);
            if ($tableSchema !== null) {
                $columns = !empty($tableSchema->primaryKey) ? $tableSchema->primaryKey : [reset($tableSchema->columns)->name];
                foreach ($columns as $name) {
                    $names[] = $this->db->quoteColumnName($name);
                    $placeholders[] = 'DEFAULT';

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Omit the $update argument (pass null) for Oracle - ON DELETE alone is fine.
  2. Branch per driver when defining FKs and only send $update where supported.
  3. If ON UPDATE behavior is mandatory, implement it with a database trigger instead.
  4. Catch yii\db\Exception in generic schema builders and retry without the update option.

Example fix

// before
$this->addForeignKey('fk_order_user', 'order', ['user_id'], 'user', ['id'], 'RESTRICT', 'CASCADE');

// after
if ($this->db->driverName === 'oci') {
    $this->addForeignKey('fk_order_user', 'order', ['user_id'], 'user', ['id'], 'RESTRICT', null);
} else {
    $this->addForeignKey('fk_order_user', 'order', ['user_id'], 'user', ['id'], 'RESTRICT', 'CASCADE');
}
Defensive patterns

Strategy: validation

Validate before calling

// Driver-aware FK options: Oracle has no ON UPDATE
$update = ($db->driverName === 'oci') ? null : 'CASCADE';
$this->addForeignKey('fk_order_user', 'order', ['user_id'], 'user', ['id'], 'RESTRICT', $update);

Try / catch

try {
    $sql = $db->getQueryBuilder()->addForeignKey($name, $table, $cols, $refTable, $refCols, $delete, $update);
} catch (\yii\db\Exception $e) {
    // Oracle: retry without the ON UPDATE option
    $sql = $db->getQueryBuilder()->addForeignKey($name, $table, $cols, $refTable, $refCols, $delete, null);
}

Prevention

When it happens

Trigger: A migration or schema call like $this->addForeignKey('fk', 't', ['ref_id'], 'ref', ['id'], 'CASCADE', 'CASCADE') - any non-null seventh argument ($update) on an Oracle connection.

Common situations: Migrations shared between MySQL/PostgreSQL (where ON UPDATE CASCADE is common) and Oracle; FK definitions copied from MySQL documentation; multi-driver applications with a single migration set.

Related errors


AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17). Data as JSON: /api/errors/1254d550b2f95e74. Report an issue: GitHub.