{"record":{"id":"e0ffe1ba9d24357e","repo":"phalcon/cphalcon","slug":"removing-a-primary-key-after-table-has-been-create","errorCode":null,"errorMessage":"Removing a primary key after table has been created is not supported by SQLite","messagePattern":"Removing a primary key after table has been created is not supported by SQLite","errorType":"exception","errorClass":"Phalcon\\Db\\Exceptions\\SqliteDropPrimaryKeyNotSupported","httpStatus":null,"severity":"error","filePath":"phalcon/Db/Dialect/Sqlite.zep","lineNumber":394,"sourceCode":"\n    /**\n     * Generates SQL to delete an index from a table\n     */\n    public function dropIndex( string tableName,  string schemaName,  string indexName) -> string\n    {\n        if schemaName {\n            return \"DROP INDEX \\\"\" . schemaName . \"\\\".\\\"\" . indexName . \"\\\"\";\n        }\n\n        return \"DROP INDEX \\\"\" . indexName . \"\\\"\";\n    }\n\n    /**\n     * Generates SQL to delete primary key from a table\n     */\n    public function dropPrimaryKey( string tableName,  string schemaName) -> string\n    {\n        throw new SqliteDropPrimaryKeyNotSupported();\n    }\n\n    /**\n     * Generates SQL to drop a table\n     */\n    public function dropTable( string tableName, string schemaName = null,  bool ifExists = true) -> string\n    {\n        var table;\n\n        let table = this->prepareTable(tableName, schemaName);\n\n        if ifExists {\n            return \"DROP TABLE IF EXISTS \" . table;\n        }\n\n        return \"DROP TABLE \" . table;\n    }\n","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Db/Dialect/Sqlite.zep#L376-L412","documentation":"Phalcon\\Db\\Dialect\\Sqlite::dropPrimaryKey() always throws SqliteDropPrimaryKeyNotSupported. In SQLite the primary key is fixed in the CREATE TABLE definition; there is no ALTER TABLE ... DROP PRIMARY KEY statement, so removing it after creation is impossible without rebuilding the table.","triggerScenarios":"Migration code calling $connection->dropPrimaryKey('posts', null) while the connection uses the Sqlite dialect; schema-normalization steps that strip primary keys on every supported database.","commonSituations":"Cross-dialect migrations; SQLite test databases exercising MySQL-oriented migration sets; tools that regenerate primary keys by drop-and-add, which works on MySQL but not SQLite.","solutions":["Skip the operation when $connection->getDialectType() === 'sqlite'","Rebuild the table without PRIMARY KEY (create new, copy, drop old, rename) if the key must really go","Restructure the migration so primary key changes ship as a new table definition rather than an ALTER step"],"exampleFix":"// before\n$connection->dropPrimaryKey('posts', null);\n\n// after\nif ($connection->getDialectType() !== 'sqlite') {\n    $connection->dropPrimaryKey('posts', null);\n}\n// on SQLite, recreate the table without PRIMARY KEY if required","handlingStrategy":"try-catch","validationCode":"if ($connection->getDialectType() !== 'sqlite') {\n    $connection->dropPrimaryKey('posts', null);\n}","typeGuard":null,"tryCatchPattern":"try {\n    $connection->dropPrimaryKey('posts', null);\n} catch (\\Phalcon\\Db\\Exceptions\\SqliteDropPrimaryKeyNotSupported $e) {\n    // SQLite: primary key is fixed at CREATE TABLE; rebuild if it must change\n    $logger->info('Skipped dropPrimaryKey on SQLite', ['table' => 'posts']);\n}","preventionTips":["Design migrations so primary-key changes ship as a table rebuild on SQLite","Detect dialect before alter operations and branch early","Cover the SQLite path of every migration in an integration test"],"tags":["sqlite","phalcon-db","ddl","primary-key","unsupported-operation","migrations"],"backgroundTag":"sqlite-alter-limitation","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}