The following table(s) do not have a primary key

Главные вкладки

Аватар пользователя jura12 jura12 27 июня в 23:23

Есть самописный модуль . В отчете о состоянии ругаются на таблицу

Уровень изоляции транзакций
READ-COMMITTED
For this to work correctly, all tables must have a primary key. The following table(s) do not have a primary key: rating

что с этим делать? как написать патч к этой таблице в schema? в таблице есть записи. или вручную добавить в phpmyadmin primary key?

CREATE TABLE `rating` (
  `tid` INT(11) NOT NULL,
  `field1` INT(11) NOT NULL DEFAULT 0,
  `field2` INT(11) NOT NULL DEFAULT 0,
  `field3` INT(11) NOT NULL DEFAULT 0,
  `field4` INT(11) NOT NULL DEFAULT 0,
  `field5` INT(11) NOT NULL DEFAULT 0,
  `field6` INT(11) NOT NULL DEFAULT 0,
  `field7` INT(11) NOT NULL DEFAULT 0,
  `field8` INT(11) NOT NULL DEFAULT 0,
  `field9` INT(11) NOT NULL DEFAULT 0,
  `total` INT(11) NOT NULL DEFAULT 0,
  `type` VARCHAR(255) NOT NULL DEFAULT '',
  `name` VARCHAR(255) NOT NULL DEFAULT '',
  `date` DATE NOT NULL,
  `fo_place` INT(11) NOT NULL DEFAULT 0,
  `position` INT(11) NOT NULL DEFAULT 0,
  KEY `region_id` (`tid`),
  KEY `total` (`total`),
  KEY `date` (`date`),
  KEY `fo_place` (`fo_place`),
  KEY `position` (`position`),
  KEY `field1` (`field1`),
  KEY `field2` (`field2`),
  KEY `field3` (`field3`),
  KEY `field4` (`field4`),
  KEY `field5` (`field5`),
  KEY `field6` (`field6`),
  KEY `field7` (`field7`),
  KEY `field8` (`field8`),
  KEY `field9` (`field9`)
) ENGINE=InnoDB DEFAULT CHARSET=cp1251 COLLATE=cp1251_general_ci;

Комментарии

Аватар пользователя OldWarrior OldWarrior 28 июня в 6:47

jura12 wrote: что с этим делать? как написать патч к этой таблице в schema?

1. Добавить hook_update_NNN ()
(https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Extension...)

2. В нём добавить новое поле для primary key (или выбрать уже имеющееся, но с уникальным значением для каждого ряда).

3. Установить для этого поля признак primary key, типа:

$schema->addPrimaryKey('mytable', $field);

Пример: https://www.drupal.org/docs/drupal-apis/update-api/updating-database-sch...

Аватар пользователя jura12 jura12 29 июня в 10:59

спасибо, буду неспешно пробовать. только в таблице записи есть. и куда этот апдейт вставлять. в тело модуля rating.module?

Аватар пользователя OldWarrior OldWarrior 29 июня в 13:52

1. Записи никуда не денутся, но лучше забекапиться перед обновлением.

2. Да, вставлять в код модуля (*.module).

3. После добавления кода выполнить обновление, типа drush updb или через UI Друпала.

Аватар пользователя OldWarrior OldWarrior 30 июня в 3:13

Да, лучше в .install файле. В том смысле, что будет избирательная загрузка тела кода хука только на операциях инсталляции/обновления. Ещё избирательнее - перетащить тело хука hook_update_N в отдельный статический метод какого-нить уникального класса вроде HookUpdateN. Особенно если хуков hook_update_N будет много - для каждого можно запилить отдельный класс с единственным статическим методом. Это ну прям вообще песня. Smile

Аватар пользователя jura12 jura12 30 июня в 16:35

друпал апи это слишком сложно для меня. сделал так:

  1. через putty сделал тунеллирование порта 3306
  2. через heidisql подключился к базе
  3. выбрал таблицу и в разделе Основной добавил столбец
  4. дал имя, примари кей и авто инкремент.
  5. Сохранить

сделано на тестовой базе. осталось сделать на рабочей.

CREATE TABLE `rating` (
        `tid` INT(11) NOT NULL,
        `field1` INT(11) NOT NULL DEFAULT '0',
        `field2` INT(11) NOT NULL DEFAULT '0',
        `field3` INT(11) NOT NULL DEFAULT '0',
        `field4` INT(11) NOT NULL DEFAULT '0',
        `field5` INT(11) NOT NULL DEFAULT '0',
        `field6` INT(11) NOT NULL DEFAULT '0',
        `field7` INT(11) NOT NULL DEFAULT '0',
        `field8` INT(11) NOT NULL DEFAULT '0',
        `field9` INT(11) NOT NULL DEFAULT '0',
        `total` INT(11) NOT NULL DEFAULT '0',
        `type` VARCHAR(255) NOT NULL DEFAULT '' COLLATE 'cp1251_general_ci',
        `name` VARCHAR(255) NOT NULL DEFAULT '' COLLATE 'cp1251_general_ci',
        `date` DATE NOT NULL,
        `fo_place` INT(11) NOT NULL DEFAULT '0',
        `position` INT(11) NOT NULL DEFAULT '0',
        `rid` INT(11) NOT NULL AUTO_INCREMENT,
        PRIMARY KEY (`rid`) USING BTREE,
        INDEX `region_id` (`tid`) USING BTREE,
        INDEX `total` (`total`) USING BTREE,
        INDEX `date` (`date`) USING BTREE,
        INDEX `fo_place` (`fo_place`) USING BTREE,
        INDEX `position` (`position`) USING BTREE,
        INDEX `field1` (`field1`) USING BTREE,
        INDEX `field2` (`field2`) USING BTREE,
        INDEX `field3` (`field3`) USING BTREE,
        INDEX `field4` (`field4`) USING BTREE,
        INDEX `field5` (`field5`) USING BTREE,
        INDEX `field6` (`field6`) USING BTREE,
        INDEX `field7` (`field7`) USING BTREE,
        INDEX `field8` (`field8`) USING BTREE,
        INDEX `field9` (`field9`) USING BTREE
)
COLLATE='cp1251_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=22436
;
Аватар пользователя OldWarrior OldWarrior 1 июля в 10:43

Ну, получилось - и хорошо. Однако, это частный случай с кастомным модулем, где такой финт ещё можно применить. Во всех остальных случаях (да и для практики полезно) - лучше всё же обновления схемы БД делать через слой Drupal API. Ещё одно преимущество этого метода - в случае чего с помощью API можно откатить применённое ранее обновление схемы БД модуля по его уникальному номеру.