У меня есть две таблицы:
CREATE TABLE main_table
(
id integer NOT NULL,
field character(10) NOT NULL,
CONSTRAINT main_table_pkey PRIMARY KEY (field)
)
WITH (
OIDS=FALSE
);
А также
CREATE TABLE child_table
(
id integer NOT NULL,
child_field character(10) NOT NULL,
CONSTRAINT child_table_pkey PRIMARY KEY (id),
CONSTRAINT main_table_field_fkey FOREIGN KEY (child_field)
REFERENCES main_table (field) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
Как вы можете видеть, child_table имеет внешний ключ к main_table от child_table.child_field -> main_table.field
Я хочу иметь возможность вставить сначала в child_table, а затем в main_table. Например:
INSERT INTO child_table(id, child_field) VALUES (1, '0123456789');
INSERT INTO main_table(id, field) VALUES(1, '0123456789');
Сначала я подумал, что транзакции помогают мне. Но даже если я выполняю ‘START TRANSACTION’, первый запрос INSERT выдает ошибку ограничения, и транзакция завершается неудачей перед фиксацией.
После того, как я попытался добавить команду DEFERRABLE в «START TRANSACTION». Результат тот же. Затем я добавляю к своему ключу переднего края «DEFERRABLE INITIALLY DEFERRED» к своему ключу переднего края, так что у меня есть:
CREATE TABLE child_table
(
id integer NOT NULL,
child_field character(10) NOT NULL,
CONSTRAINT child_table_pkey PRIMARY KEY (id),
CONSTRAINT main_table_field_fkey FOREIGN KEY (child_field)
REFERENCES main_table (field) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED
)
WITH (
OIDS=FALSE
);
ALTER TABLE child_table
OWNER TO postgres;
После этого у меня есть возможность выполнить мои INSERT с помощью командной строки даже без транзакции.
Но в любом случае я не мог сделать то же самое с PDO PHP. Я попробовал подготовленные запросы, это не сработало. Даже прямые запросы не работают:
$pdo->exec("INSERT INTO child_table(id, child_field) VALUES (1, '0123456789')");
$pdo->exec("INSERT INTO main_table(id, field) VALUES(1, '0123456789')");
Запуск транзакции тоже не поможет. Запрос ‘SET CONSTRAINTS ALL DEFERRED’ тоже не помогает. Я попытался добавить ‘PDO :: ATTR_PERSISTENT => true’ в массив инициализации. Нет результатов. Поэтому, пожалуйста, скажите мне, как я могу выполнить эти запросы в этом порядке с помощью PHP? Как мне кажется, я должен выполнить эти запросы одной транзакцией, но эта транзакция не должна проверять ограничения, пока она не будет зафиксирована. Или я не прав?
РЕШЕНИЕ
Проблема была не с PDO и не с транзакциями. Таблица main_table была создана другой ролью и, похоже, после того, как данные коммита не записались в main_table из-за проблемы владельца, поэтому child_table выбрасывает ошибку ограничения. Плохо, что main_table не выдает ошибку владельца, поэтому проблема не была очевидной.
Кто-то ответил мне этим решением:
$pdo->beginTransaction();
$pdo->exec("INSERT INTO child_table(id, child_field) VALUES (1, '0123456789')");
$pdo->exec("INSERT INTO main_table(id, field) VALUES(1, '0123456789')");
$pdo->commit();
Чувак, это было правильное решение, извините, что отвечаю вам, что оно не работает.
Задача ещё не решена.
Других решений пока нет …