Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: каскадное обновление/удаление
 
 автор: Medulla   (18.06.2007 в 11:02)   письмо автору
 
 

необходимо каскадно обновить/удалить только зависимые от id записи. количество уровней заранее неизвестно.

нпр, id
5550000000
5551000000
5551000001
5551000002
5551100000 5551100001

в базе:
id | kod (определяет вышестоящий уровень)
5551000000 | 5550000000
5551100001 | 5551100000

присваиваем 5551000000=666100000=> должны измениться только 6661000001
6661000002

$query = "UPDATE catalogue  SET id  = CONCAT('$new_prefix', SUBSTRING(id, 1+LENGTH('$old_prefix'))) 
WHERE id like '{$old_prefix}_______' and 
kod = $id or kod2 = $id or
 (kod or kod2 in  
(select  id from catalogue where id=$id
or kod or kod2  in 
(select id from catalogue where id=$id
or (kod or kod2) in 
(select id from catalogue where id=$id
or (kod or kod2) in 
(select id from catalogue where id=$id



"UPDATE catalogue  SET kod  = CONCAT('$new_prefix', SUBSTRING(kod, 1+LENGTH('$old_prefix'))) 
WHERE kod like '{$old_prefix}_______'and 
kod = $id or kod2 = $id[-//-//query]"; 


"UPDATE catalogue  SET kod2  = CONCAT('$new_prefix', SUBSTRING(kod2, 1+LENGTH('$old_prefix'))) 
WHERE kod2 like '{$old_prefix}_______'and 
kod = $id or kod2 = $id[-//-//query]"; 

$query4="delete *  from catalogue where id=$id 
or kod= $id   or kod2 = $id  or
(kod or kod2 in 
(select  id from catalogue where  id=$id or
kod or kod2 in 
(select * from catalogue where  id=$id or
kod or kod2 
(select  * from catalogue where  id=$id or
or kod  or kod2select * from catalogue where  id=$id 
)
))
))";

не знаю как исправить.

   
 
 автор: Trianon   (18.06.2007 в 11:06)   письмо автору
 
   для: Medulla   (18.06.2007 в 11:02)
 

покажите, пожалуйста, структуру и несколько строк данных из дампа. которые иллюстрировали бы процесс.
Очень трудно разобраться, как у Вас связаны записи...

   
 
 автор: Medulla   (18.06.2007 в 11:30)   письмо автору
 
   для: Trianon   (18.06.2007 в 11:06)
 

id (bigint) kod (bigint) kod2 (bigint)+pkey autoinc
4692000000////4690000002/////// 4690000000
4692000001////4690000002//////// 4692000000
4692010000////4692010001/////// 4692000000
4692010001//// 4690000002////// 4692010000
4692010002////4692010001//////// 4692010000
4692020000//// 4692020001///// 4692000000
4692020001//// 4690000002//// 4692020000
4692020002//// 4692020001//// 4692020000
4692020003//// 4692020001//// 4692020000
4693020003//// 4693020002//// 4693020000
4693020004//// 4693020002//// 4693020000
4693020005//// 4693020002//// 4693020000
4693020006//// 4693020002//// 4693020000


меняем 4692000000 на 7770000000

должны изменится все, кроме 4 последних строк


46920 в качестве параметра выборки использовать нельзя, т.к. возможны другие коды, кот. связаны с 4692000000 по kod, kod1

   
 
 автор: Trianon   (18.06.2007 в 12:33)   письмо автору
 
   для: Medulla   (18.06.2007 в 11:30)
 

>меняем 4692000000 на 7770000000

4692000000 и 7770000000 - это префиксы замены?
в каких полях?
Во всех трех?
какое поле какому соответствует - Вы не написали.

   
 
 автор: Medulla   (18.06.2007 в 12:45)   письмо автору
 
   для: Trianon   (18.06.2007 в 12:33)
 

>4692000000 и 7770000000 - это префиксы замены?
$id - 4692000000.
$id2 -7770000000
префикс 469 заменить на 777

>в каких полях?
>Во всех трех?
в 3. id, kod (2 столбец), kod2 (3 столбец)
2 и 3 столбец прямо/ косвенно (через несколько уровней) связаны с $id.

>какое поле какому соответствует - Вы не написали.
?

   
 
 автор: Trianon   (18.06.2007 в 13:58)   письмо автору
 
   для: Medulla   (18.06.2007 в 12:45)
 

Похоже, я понял.

Примерная схема алгоритма такова.

Потребуется ввести доп. поле (state)

количество циклов (и запросов) нужно как минимум равное глубине связи.

Каждый цикл будет вычислять записи очередного уровня глубины, помечая их в state флажками.

Когда не останется модифицированных записей - нужно пройти еще раз по всей таблице, и выполнить замену помеченных полей.

   
 
 автор: Medulla   (18.06.2007 в 14:09)   письмо автору
 
   для: Trianon   (18.06.2007 в 13:58)
 

>>Каждый цикл будет вычислять записи очередного уровня глубины, помечая их в state флажками.

получается вычислять записи только 1 уровня, как в delete, так и update.
не могу посторить запрос на вычисление уровня ниже.

   
 
 автор: Trianon   (18.06.2007 в 14:22)   письмо автору
 
   для: Medulla   (18.06.2007 в 14:09)
 

что-то такое...

UPDATE tab AS t1 JOIN tab AS t2 ON t1.id = t2.kod OR t1.id=t2.kod2 
SET t1.state = 1 WHERE 
     t2.state IS NOT NULL  
    AND 
    (t2.kod LIKE  '{$prefix}______'
      OR
      t2.kod2 LIKE  '{$prefix}______' )

   
 
 автор: Medulla   (18.06.2007 в 14:27)   письмо автору
 
   для: Trianon   (18.06.2007 в 13:58)
 


$query="select id from catalogue where id ='$id' or kod='$id' or kod2 ='$id'";
$query2="select id from catalogue where id = $query"; 
так?

   
 
 автор: Trianon   (18.06.2007 в 14:37)   письмо автору
 
   для: Medulla   (18.06.2007 в 14:27)
 

селект-то зачем?
Вам же менять надо, а не глядеть...
Если хотите глядеть - глядите все
SELECT id FROM catalogue WHERE state IS NOT NULL

   
 
 автор: Medulla   (18.06.2007 в 17:51)   письмо автору
 
   для: Trianon   (18.06.2007 в 14:37)
 

плохой пример) имела ввиду присвоение переменной.

допустим:

$level= "delete * from catalogue where pid in (select id from catalogue where pid='$id' or pid2='$id') or pid2 in (select id from catalogue where pid='$id' or pid2='$id')"; 
так работает.

присвоение+передача в запрос

$ main ="select id from catalogue where pid='$id' or pid2='$id'";
$result = mysql_query($main);
возвращает некорректную информацию.

возможно ли его использовать?

   
 
 автор: Trianon   (18.06.2007 в 17:58)   письмо автору
 
   для: Medulla   (18.06.2007 в 17:51)
 

Вы хотите получить массив с id-ами в php?
Это делается несколько по-другому.

$sql ="select id from catalogue where pid='$id' or pid2='$id'"; 
$res = mysql_query($sql); 
for($result = array(); $row = mysql_fetch_assoc($res) ;) 
    $result[] = $row['id'];


На больших объемах таблицы памяти может и не хватить.

   
 
 автор: Trianon   (18.06.2007 в 18:09)   письмо автору
 
   для: Trianon   (18.06.2007 в 17:58)
 

Между прочим...
по теме. При движке InnoDB возможен перенос некоторых каскадных действий на сам сервер. Там есть ограничения чужого ключа ON UPDATE CASCADE .... и ON DELETE CASCADE ....
Не то что это Вам сильно надо, раз не пользуетесь,.... но упомянуть стоит.

   
 
 автор: Medulla   (18.06.2007 в 19:12)   письмо автору
 
   для: Trianon   (18.06.2007 в 18:09)
 

где можно прочитать подробнее?

   
 
 автор: Medulla   (18.06.2007 в 19:12)   письмо автору
 
   для: Trianon   (18.06.2007 в 17:58)
 


$sql ="select id from catalogue where pid='$id' or pid2='$id'";  
$res = mysql_query($sql);  
for($result = array(); $row = mysql_fetch_assoc($res) ;)  
    $result[] = $row['id'];
$level2= "select id from catalogue where pid='$result' or pstaff ='$result'";
$result2 = mysql_query($level2);
$num_rows = mysql_num_rows($result2);
<p>На удаление помечено '."$num_rows \n".' записей. </p>';
for ($i=0; $i <$num_rows; $i++)
     {
     $row = mysql_fetch_assoc($result2);
     echo '<p><strong>'.($i+1).'. Код: ';
     echo specialchars(stripslashes($row['id']));
     echo '</strong><br />Название: ';
     echo stripslashes($row['dolg']);
     echo '</p>';
     }
mysql_free_result($result1) or die ("Ошибка1.");
mysql_close($connection);


отобразились некоррекктные данные, как и в первом случае.
почему после for не нужны { }?

   
 
 автор: Trianon   (18.06.2007 в 19:21)   письмо автору
 
   для: Medulla   (18.06.2007 в 19:12)
 

Вы явно хотите другого....

<?
$sql 
="select id from catalogue where pid='$id' or pid2='$id'";   
$res mysql_query($sql);   
for(
$result = array(); $row mysql_fetch_assoc($res) ;)   
    
$result[] = $row['id']; 
// массив id-ов. array('23416','283741','9123874')

$result  = empty($result) ? "()" : ("('"implode("','"$result) ."')");
//список id-ов. строка  "('23416','283741','9123874')"

$level2"select id from catalogue where pid IN $result or pstaff  IN $result"
$result2 mysql_query($level2); 

Второй запрос может быть отклонен из-за размера....


>почему после for не нужны { }?

после for нужен оператор тела.
Ему необязательно быть большим составным оператором. В данном случае подошел простой - оператор вычисления выражения.

   
 
 автор: Medulla   (19.06.2007 в 06:59)   письмо автору
 
   для: Trianon   (18.06.2007 в 19:21)
 

усложняю себе задачу) спасибо.

   
 
 автор: Medulla   (19.06.2007 в 13:58)   письмо автору
 
   для: Trianon   (18.06.2007 в 19:21)
 

delete удаляет $id + все зависимые коды

$level2= "delete * from catalogue where * id='$id' or pid in 
(select id from catalogue where pid in (select id from catalogue where pid in 
(select id from catalogue where pid='$id' or pid2='$id') or pid2 in 
(select id from catalogue where pid='$id' or pid2='$id')) or pid2 in 
(select id from catalogue where pid in 
(select id from catalogue where pid='$id' or pid2='$id') or pid2 in 
(select id from catalogue where pid='$id' or pid2='$id'))) or pid2 in 
(select id from catalogue where pid in (select id from catalogue where pid in 
(select id from catalogue where pid='$id' or pid2='$id') or pid2 in 
(select id from catalogue where pid='$id' or pid2='$id')) or pid2 in 
(select id from catalogue where pid in (select id from catalogue where pid='$id' or pid2='$id') or pid2 in 
(select id from catalogue where pid='$id' or pid2='$id')))";


update возвращает ошибку.

$level2 = "update catalogue set status = '1' where *
$result2 = mysql_query($level2);
mysql_free_result($result2) or die ("Ошибка1.");

   
 
 автор: Trianon   (19.06.2007 в 15:16)   письмо автору
 
   для: Medulla   (19.06.2007 в 13:58)
 

это какие-то совсем ужасные запросы...
Там не нужно звездочки ни в том, ни в другом.
Когда исполняете запрос - контролируйте сразу, удачно ли он выполнился.

$level2 = "delete from  catalogue where status 
$result2 = mysql_query($level2) or die("Error in $level2: ". mysql_error()); 
mysql_free_result($result2);


А что, идею с пошаговой пометкой реализовать не получилось?

   
 
 автор: Medulla   (20.06.2007 в 13:20)   письмо автору
 
   для: Trianon   (19.06.2007 в 15:16)
 

пока получилось так: 1 раз выполняю _ужасный_ запрос с вложенными подзапросами [>8 уровней]
передаю в $result все id возвращенные запросом.

$query = "update catalogue set status = '1' where id in $result"; 


потом update, delete в зависимости от условий/действий пользователя, где

Where status = '1' 


ошибка была здесь:

from catalogue where id='$id' or pid='$id' or pid2='$id' 

а уж потом

or pid in  (select id from catalogue where pid in (select 


ps * не самое лучшее усл. обозначения подзапросов из пред. кода)

большое спасибо за помощь.

   
 
 автор: cheops   (18.06.2007 в 11:10)   письмо автору
 
   для: Medulla   (18.06.2007 в 11:02)
 

>'{$old_prefix}_______'and
Между закрывающе кавычкой и and действительно пробела нет или это опечатка?

   
 
 автор: Medulla   (18.06.2007 в 11:16)   письмо автору
 
   для: cheops   (18.06.2007 в 11:10)
 

опечатка

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования