I’m trying to create table (using migrations) with foreign key like this
public function safeUp()
{
$this->createTable('tbl_category', array(
'id'=>'pk',
'title'=>'string NOT NULL',
'url'=>'string NOT NULL UNIQUE'
));
$this->addForeignKey('FK_category', 'tbl_product', 'category_id', 'tbl_category', 'id', 'CASCADE', 'NO ACTION');
}
It perfectly works in MySQL, but now I want to use SQLite and this code gives an error that in SQLite I can’t add foreign key to existing table, so I looked through the definition of createTable method:
public integer createTable(string $table, array $columns, string $options=NULL)
And tried to use $options param to add my foreign key there, but it generates this:
CREATE TABLE 'tbl_category' (
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"title" varchar(255) NOT NULL,
"url" varchar(255) NOT NULL UNIQUE
)
CONSTRAINT FK_category
FOREIGN KEY tbl_product(category_id)
REFERENCES tbl_category(id)
ON DELETE CASCADE ON UPDATE NO ACTION
Obviously, that “CONSTRAINT…” code should be inside these brackets, but it doesn’t. So how can I create this foreign key?
Explanation
The function createTable is defined in the source code as:
This tells me that all options are for things that would normally go after a Create statement (but before the final semi-colon), like
ENGINEorCHARSETin MySQL. The SQLite syntax is just different and doesn’t allow such options.The addForeignKey function doesn’t work, it’s just not coded:
And SQLite doesn’t support altering a table to add a foreign key clause.
Solution
Long story short, you should put the foreign key clause in the column definition (in your product table, not your category table):
Addendum
The idea with foreign keys is that the child table should declare it, not the parent table.