1

このような外部キーで(移行を使用して)テーブルを作成しようとしています

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)

$optionsparamを使用してそこに外部キーを追加しようとしましたが、次のように生成されます。

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...」コードはこれらの括弧内にある必要がありますが、そうではありません。では、この外部キーを作成するにはどうすればよいでしょうか。

4

2 に答える 2

7

説明

関数 createTable は、ソース コードで次のように定義されています。

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;
}

ENGINEこれは、すべてのオプションが、またはCHARSETMySQLのように、通常は Create ステートメントの後 (ただし、最後のセミコロンの前) にあるものであることを示しています。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)'
));

補遺

外部キーの考え方は、親テーブルではなく、子テーブルがそれを宣言する必要があるということです。

于 2012-11-02T14:33:19.890 に答える
1

$this->execute で実行し、純粋な SQL ステートメントを配置しました。

于 2012-11-02T11:42:22.053 に答える