4

I am getting error while trying to create a table with dbDelta() and composite primary key. The sql is pretty straight forward.

$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);

This shows error

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

Am I doing it wrong? How to correctly defined composite primary key with dbDelta?

Note: Although error is shown but it still creates the table where both columns are set as primary key.

5

The problem

If the table already exists your code will still try to execute the following queries:

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)

Note that this query:

ALTER TABLE wp_voicemail_call ADD PRIMARY KEY (user_id, call_id)

is trying to add another primary key that's already defined and we can only have of one of those. Thus the error.

This query:

ALTER TABLE wp_voicemail_call ADD

comes from the empty line above the PRIMARY KEY line.

In the dbDelta() function there's this part that should unset the primary parts:

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

but the array search always return false in your case for some reason.

I dug deeper and in your case the $indices array is:

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

but the $index_strings array is

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

So we can see the mismatch:

PRIMARY KEY  (user_id,call_id) 

versus

PRIMARY KEY  (user_id, call_id)

... a single space!!

The suggested solution

So if we remove the extra empty line and the extra space:

$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)
);";

then we should only get these queries to run with 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

when the table already exists.

|improve this answer|||||
  • An empty line and a space. God bless us! – Sisir Dec 26 '15 at 10:34
  • 1
    Using dbDelta() is like "feeding the crocodiles", we have to be very careful ;-) @Sisir – birgire Dec 26 '15 at 10:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.