Базы данных позволяют использовать неверные внешние ключи из Rails Fixtures

Я использую Rails Fixtures для загрузки некоторых тестовых данных в свою базу данных и случайно ввел внешний ключ за пределы допустимого диапазона.

К моему удивлению, база данных приняла его, несмотря на ограничения ссылочной целостности (которые работают). Я пробовал с PostgreSQL и с MySQL InnoDB, и оба разрешены.

Пример:

Имея в базе данных "Ароматы" с числовым первичным ключом (id), 5 записей (от 1 до 5). Я могу ввести плохие данные:

Icecream_1: название: мое мороженое flavor_id: 6

Как возможно, что загрузка фикстур обходит ограничения моей базы данных?

Спасибо.


Вот две таблицы. Имея 200 user_types (fake data) я смог ввести пользователя с user_type_id 201 но только из фикстур, pgAdmin запрещает.

CREATE SEQUENCE user_types_id_seq;
CREATE TABLE user_types (
id SMALLINT
  NOT NULL
  DEFAULT NEXTVAL('user_types_id_seq'),
name VARCHAR(45) 
  NOT NULL 
  UNIQUE,
PRIMARY KEY (id));

CREATE SEQUENCE users_id_seq;
CREATE TABLE users (
id BIGINT
    NOT NULL
    DEFAULT NEXTVAL('users_id_seq'),
user_type_id SMALLINT
    NOT NULL
    REFERENCES user_types (id) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY (id));


---------

Fixture

<% for i in (1..201) %>

user_<%= i %>:
    id: <%= i %>
    user_type_id: <%= i %>
<% end %>

Как я уже сказал, и innoDb, и postgresql приняли неверный ключ.

Спасибо


person Ferreira    schedule 13.08.2010    source источник
comment
Можем ли мы взглянуть на ваши определения таблицы? Там может быть подсказка.   -  person Brian Hooper    schedule 13.08.2010


Ответы (4)


PostgreSQL не принимает поврежденные данные, не волнуйтесь. В MySQL все зависит от движка (должен быть innoDB) и настроек (подключения) для параметра Foreign_key_checks.

Как выглядят ваши таблицы и ограничения? Проверьте pgAdmin (или какой-либо другой клиент) и выгрузите соответствующую часть модели данных здесь, чем мы можем вам помочь.

pgadmin запрещает.

Нет, ваша база данных PostgreSQL запрещает это. pgAdmin — это просто клиент, и он только отправляет запрос в базу данных. База данных делает некоторые проверки, FK был нарушен и возвращает ошибку.

Похоже, вы работаете не с той базой данных (без FK или MySQL с неправильным движком и/или настройками), PostgreSQL отлично работает с FK.

person Frank Heikens    schedule 13.08.2010

Я согласен с Фрэнком. Скорее всего, ваша тестовая база данных для PostgreSQL настроена неправильно. Вы либо забыли создать ограничения FK, либо отключили их.

Тот факт, что вы получили ошибку в pgAdmin, указывает на то, что вы работаете с другой базой данных из pgAdmin и вашего тестового сценария.

Что касается MySQL, я бы поискал неправильный движок по умолчанию в тестовой базе данных или если вы также забыли создать там ограничения FK (обратите внимание, что вы не получите ошибку, если создадите ограничение FK с движком, который не не поддерживает ссылочную целостность в MySQL)

person a_horse_with_no_name    schedule 13.08.2010

Проверьте определения таблиц в вашей тестовой базе данных. IIRC, «rake db:test:prepare» не поддерживает точность при создании таблиц в тестовой базе данных.

person nirvdrum    schedule 13.08.2010

Спасибо всем за ответ.

Кто-то на рубиновом форуме понял это. Похоже, что триггеры, обеспечивающие RI, отключены до загрузки приборов.

Я не знаю почему, но это решает загадку.

person Ferreira    schedule 13.08.2010
comment
Эти триггеры не являются триггерами базы данных, в PostgreSQL невозможно отключить ограничения внешнего ключа (также известные как триггеры). В вашей базе данных есть FK или нет FK, нет ничего похожего на отключенный FK. - person Frank Heikens; 13.08.2010
comment
Я думаю, вы обнаружите, что таблицы в MySQL, обеспечивающие ссылочную целостность, должны создаваться с предложением ENGINE=INNODB. Если это не так, они могут сохранять ограничения, но не действуют на них. - person Brian Hooper; 13.08.2010
comment
Да, Брайан, ты прав, все таблицы в MySQL имеют ENGINE=INNODB. - person Ferreira; 13.08.2010
comment
Фрэнк, я тоже так думал и поэтому разместил этот вопрос. Фикстуры должны выполнять множество операций с БД, включая удаление/очистку, и я предполагаю, что для этого им нужно обойти RI. - person Ferreira; 13.08.2010
comment
На самом деле можно отключить системные триггеры, реализующие проверку FK, но только от имени суперпользователя (ALTER TABLE foo DISABLE TRIGGER ALL). Скорее всего это делает тестовая программа. Еще один хороший пример того, почему разработка не должна выполняться с использованием суперпользователя базы данных... - person a_horse_with_no_name; 13.08.2010
comment
Если тестовый загрузчик отключает ограничения, это опасно. Это совершенно неуместно. - person matthudson; 22.05.2013