Cannot add or update a child row: a foreign key constraint fails

Дмитрий1990
Дата: 17.12.2012 13:30:01
Здравствуйте! Изучая MySQL и PHP столкнулся с такой вот проблемкой:
Cannot add or update a child row: a foreign key constraint fails (`xml`.`item`, CONSTRAINT `item_ibfk_1` FOREIGN KEY (`N_p`) REFERENCES `persacc` (`N_p`))

Данная ошибка вылазит когда я пытаюсь создать таблицу 'item' со связующим ключом.

...
	foreach($xml->PersAcc->attributes() as $a => $b){$pers .= "$a varchar(50),";}
	$prs = substr($pers,0,-1);
	$prsq = "create table persacc (N_p int AUTO_INCREMENT NOT NULL,$prs,PRIMARY KEY (N_p))";
	mysql_query($prsq); // создаем таблицу
	$pers="";
	
	foreach($xml->PersAcc->item->attributes() as $a => $b){$item .= "$a varchar(50),";}
	$itm = substr($item,0,-1);
	$itmq = "create table item (N_s int AUTO_INCREMENT NOT NULL,N_p int NOT NULL, $itm, PRIMARY KEY(N_s), FOREIGN KEY (N_p) REFERENCES persacc(N_p))";//задаем ключ
mysql_query($itmq); // создаем таблицу

	$item="";
...


Не понимаю в чем дело
miksoft
Дата: 17.12.2012 13:34:26
Что-то не клеится, из сообщения об ошибке следует, что в родительской таблице уже есть записи, а вы пытаетесь изменить данные в дочерней.
Вы уверены, что ошибка возникает именно в этот момент, а не позднее?
tanglir
Дата: 17.12.2012 13:39:45
Дмитрий1990
Данная ошибка вылазит когда я пытаюсь создать таблицу 'item' со связующим ключом.
Насколько я знаю, эта ошибка возникает только при запрос на вставку/изменение данных. А у вас - создание таблицы. Ошибка точно здесь возникает, не дальше?
trew
Дата: 17.12.2012 14:41:08
Дмитрий1990,

попробуйте так:
$itmq = "create table item (N_s int AUTO_INCREMENT NOT NULL, N_p int, $itm, PRIMARY KEY(N_s), FOREIGN KEY (N_p) REFERENCES persacc(N_p))";

ссылка
Дмитрий1990
Дата: 18.12.2012 06:19:55
Хм, Действительно.

			$itmq = "insert into item values('','',$itm)"; //Ошибка скорее всего здесь. Кавычками я как бы пропускаю ключи от заполнения. Как можно поступить иначе, не перелопачивая цикл?


<?
set_time_limit (0);
function get_micro_time(){list($usec, $sec) = explode(" ",microtime());return ((float)$usec + (float)$sec);}
$start_time = get_micro_time();

// Подразумевается, что до этого мы уже создали пустую базу и пользователя
// с одинаковыми именами: "domen_test" и паролем "12345abcd"

$dbhost = "localhost"; // Хост
$dbuser = "admin"; // Имя пользователя
$dbpassword = "123456"; // Пароль
$dbname = "xml"; // Имя базы данных
//N-p Ключ человека, N-s Ключ услуги
//or die(mysql_error()) после каждого mysql_query() вывод ошибок
// mysql_connect() открывает соединение с сервером MySQL $dbhost
$link = mysql_connect($dbhost, $dbuser, $dbpassword);

mysql_select_db($dbname, $link); // Выбирает базу данных MySQL $dbname

$xml = simplexml_load_file('c:\\WebServers\\home\\test1.ru\\www\\4.xml');

	foreach($xml->PersAcc->attributes() as $a => $b){$pers .= "$a varchar(50),";}
	$prs = substr($pers,0,-1);
	$prsq = "create table persacc (N_p int AUTO_INCREMENT NOT NULL,$prs,PRIMARY KEY (N_p))";
	mysql_query($prsq); // создаем таблицу
	$pers="";
	
	foreach($xml->PersAcc->item->attributes() as $a => $b){$item .= "$a varchar(50),";}
	$itm = substr($item,0,-1);
	$itmq = "create table item (N_s int AUTO_INCREMENT NOT NULL,N_p int NOT NULL, $itm, PRIMARY KEY(N_s), FOREIGN KEY (N_p) REFERENCES persacc(N_p))";//задаем ключ
mysql_query($itmq); // создаем таблицу

	$item="";

if (!mysql_ping ($link)) {
   mysql_close($link);
   $link =  mysql_connect($dbhost, $dbuser, $dbpassword);
   mysql_select_db($dbname, $link); 
}

foreach($xml->PersAcc as $PersAcc){

	foreach($PersAcc->attributes() as $a){$pers .= "'$a',";}
	$kod_ls = $PersAcc['kod_ls'];//наш мастер ключ
	$prs = substr($pers,0,-1);
	$prsq = "insert into persacc values('',$prs)";
	mysql_query($prsq); // Добавляем запись в таблицу

		foreach($PersAcc->item as $item){
			foreach($item->attributes() as $a){$item .= "'$a',";}
			$itm = substr($item,0,-1);
			$itmq = "insert into item values('','',$itm)"; //Ошибка скорее всего здесь. Кавычками я как бы пропускаю ключи от заполнения. Как можно поступить иначе, не перелопачивая цикл?
			mysql_query($itmq) or die(mysql_error()); // Добавляем запись в таблицу
		}
$pers="";
$item="";
}

mysql_close($link); // Закрываем соединение с сервером $dbhost

     echo 
         'Скрипт работал ', 
        ($start_time - get_micro_time()), 
       ' сек';
?>
tanglir
Дата: 18.12.2012 06:40:31
Дмитрий1990
Хм, Действительно.

			$itmq = "insert into item values('','',$itm)"; //Ошибка скорее всего здесь. Кавычками я как бы пропускаю ключи от заполнения. Как можно  поступить иначе, не перелопачивая цикл?
"как бы пропускаете"? А ничего, что они NOT NULL? И как вы вообще догадались пихать строки в интовые поля? В смысле, как можно до такого додуматься, мне интересно.
Откройте для себя форму
insert into table (field1,field2,...) values (val1,val2,...)
и функцию last_insert_id()
gormonn
Дата: 18.12.2012 11:38:36
tanglir
И как вы вообще догадались пихать строки в интовые поля? В смысле, как можно до такого додуматься, мне интересно.

После того как в этой строке поставил '' :
$prsq = "insert into persacc values($prs)";

$prsq = "insert into persacc values('',$prs)";

Данные стали записываться в таблицу.
Т.е. пустые кавычки - это в любом случае строка?

tanglir
Откройте для себя форму
insert into table (field1,field2,...) values (val1,val2,...)


К сожалению, я не вижу как это можно использовать в моем случае, имея xml следующего вида (где на одну строку 'persacc' идет 4-5 строк 'item' ):
<?xml version="1.0" encoding="UTF-8"?>
<ORG name="" inn="" filedate="">
	<PersAcc kodls="" name="" pass="" email="" Barcode="" debtbeg="" debtend="" name="" AddressRegion="" AddressDistrict="" AddressCity="" AddressSettlement="" AddressStreet="" AddressHouse="" AddressFlat="" people="" commonarea="" habarea="">
		<item kod="" name="" edizm="" norm="" tarif="" ammount="" sum="" sumtopay="" sumpayed=""/>
		<item kod="" name="" edizm="" norm="" tarif="" ammount="" sum="" sumtopay="" sumpayed=""/>
		<item kod="" name="" edizm="" norm="" tarif="" ammount="" sum="" sumtopay="" sumpayed=""/>
		<item kod="" name="" edizm="" norm="" tarif="" ammount="" sum="" sumtopay="" sumpayed=""/>
		<item kod="" name="" edizm="" norm="" tarif="" ammount="" sum="" sumtopay="" sumpayed=""/>
	</PersAcc>
</ORG>

Мне кажется логичным заносить строки по порядку.
tanglir
Дата: 18.12.2012 12:07:14
Алгоритм:
Взять элемент "аккаунт" из хмл
Записать его в акки:
insert into persacc (kodls,name,pass,...) values($prs)

Взять ид внесённой записи
select last_insert_id()
, получим некий lastid
потом в цикле по итемам обрабатываемого аккаунта
insert into item (n_p,name,edizm,norm,...), values(lastid,$itm)

...
Profit!!!
gormonn
Дата: 20.12.2012 08:29:58
Большое спасибо! В данном случае оказалось целесообразнее использовать mysql_insert_id()
Но, т.к. я решил полностью перейти на mysqli, то mysqli_insert_id() соответственно. ;)