web-dev-qa-db-ja.com

DbDelta()で複合キーを定義する方法

dbDelta()と複合主キーを持つテーブルを作成しようとしているときにエラーが発生しました。 SQLはかなり簡単です。

$sql = "CREATE TABLE {$wpdb->prefix}voicemail_call (

    user_id BIGINT(9) UNSIGNED NOT NULL,
    call_id BIGINT(9) UNSIGNED NOT NULL,
    opened BOOL DEFAULT 0 NOT NULL,

    PRIMARY KEY  (user_id, call_id)
    );";

dbDelta($sql);

これはエラーを示します

WordPress database error: [Multiple primary key defined]
ALTER TABLE wp_voicemail_call ADD PRIMARY KEY (user_id, call_id)

私はそれを間違っていますか? dbDeltaを使用して複合主キーを正しく定義する方法

注: エラーは表示されますが、両方の列が主キーとして設定されているテーブルが作成されます。

4
Sisir

問題

テーブルがすでに存在する場合、コードは引き続き以下のクエリを実行しようとします。

1) ALTER TABLE wp_voicemail_call CHANGE COLUMN user_id user_id BIGINT(9) UNSIGNED NOT NULL
2) ALTER TABLE wp_voicemail_call CHANGE COLUMN call_id call_id BIGINT(9) UNSIGNED NOT NULL
3) ALTER TABLE wp_voicemail_call CHANGE COLUMN opened opened BOOL DEFAULT 0 NOT NULL
4) ALTER TABLE wp_voicemail_call ADD 
5) ALTER TABLE wp_voicemail_call ADD PRIMARY KEY (user_id, call_id)

このクエリに注意してください。

ALTER TABLE wp_voicemail_call ADD PRIMARY KEY (user_id, call_id)

既に定義されている別の主キーを追加しようとしていますが、そのうちの1つだけを持つことができます。したがって、エラーです。

このクエリ:

ALTER TABLE wp_voicemail_call ADD

PRIMARY KEY行の上の空行から来ています。

dbDelta()関数には この部分 があります。

foreach ( $index_strings as $index_string ) {
    if ( ! ( ( $aindex = array_search( $index_string, $indices ) ) === false ) ) {
        unset( $indices[ $aindex ] );
        break
     }
}

しかし、配列検索は何らかの理由であなたのケースでは常にfalseを返します。

私はもっ​​と深く掘り下げました。あなたの場合は$indices配列は次のようになります。

Array
(
    [0] => 
    [1] => PRIMARY KEY  (user_id, call_id)
)

しかし$index_strings配列は

Array
(
    [0] => PRIMARY KEY  (user_id,call_id)
    [1] => PRIMARY KEY  (user_id,call_id)
)

だから我々はミスマッチを見ることができます:

PRIMARY KEY  (user_id,call_id) 

versus

PRIMARY KEY  (user_id, call_id)

…ひとつのスペース!

提案された解決策

したがって、余分な空行と余分なスペースを削除すると、次のようになります。

$sql = "CREATE TABLE {$wpdb->prefix}voicemail_call (
    user_id BIGINT(9) UNSIGNED NOT NULL,
    call_id BIGINT(9) UNSIGNED NOT NULL,
    opened BOOL DEFAULT 0 NOT NULL,
    PRIMARY KEY  (user_id,call_id)
);";

それならこれらのクエリをdbDelta()で実行するだけです。

1) ALTER TABLE wp_voicemail_call CHANGE COLUMN user_id user_id BIGINT(9) UNSIGNED NOT NULL
2) ALTER TABLE wp_voicemail_call CHANGE COLUMN call_id call_id BIGINT(9) UNSIGNED NOT NULL
3) ALTER TABLE wp_voicemail_call CHANGE COLUMN opened opened BOOL DEFAULT 0 NOT NULL

テーブルが既に存在する場合.

5
birgire