我正在尝试使用外键创建表(使用迁移),如此
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');
}
它完全适用于MySQL,但现在我想使用SQLite,这个代码给出了一个错误,在SQLite中我无法将外键添加到现有表中,因此我查看了createTable
方法的定义:
public integer createTable(string $table, array $columns, string $options=NULL)
并尝试使用$options
param在那里添加我的外键,但它生成了这个:
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
显然,“CONSTRAINT ...”代码应该在这些括号内,但事实并非如此。那么如何创建这个外键呢?
答案 0 :(得分:6)
函数createTable在source code中定义为:
public function createTable($table, $columns, $options=null)
{
$cols=array();
foreach($columns as $name=>$type)
{
if(is_string($name))
$cols[]="\t".$this->quoteColumnName($name).' '.$this->getColumnType($type);
else
$cols[]="\t".$type;
}
$sql="CREATE TABLE ".$this->quoteTableName($table)." (\n".implode(",\n",$cols)."\n)";
return $options===null ? $sql : $sql.' '.$options;
}
这告诉我所有选项都适用于通常在Create语句之后(但在最终的分号之前)的内容,例如MySQL中的ENGINE
或CHARSET
。 SQLite语法不同,不允许这样的选项。
addForeignKey函数不起作用,它只是没有编码:
public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete=null, $update=null)
{
throw new CDbException(Yii::t('yii', 'Adding a foreign key constraint to an existing table is not supported by SQLite.'));
}
SQLite不支持更改表以添加外键子句。
长话短说,您应该将外键子句放在列定义中(在产品表中,而不是您的类别表中):
$this->createTable('tbl_product', array(
'id'=>'pk',
'name'=>'string NOT NULL',
'category_id'=>'integer NOT NULL REFERENCES tbl_category(id)'
));
使用外键的想法是子表应该声明它,而不是父表。
答案 1 :(得分:1)
使用$ this->执行,我放置了纯SQL语句。