2011-10-20 3 views
5

У меня есть таблица в моей базе данных MySQL, называемая «дети». В этой таблице находится строка под названием «пожелания» (список элементов списка желаний, разделенных запятыми). Мне нужно обновить этот список, чтобы он удалял только одно значение. то есть список = размер 12 обычных джинсов, доски для серфинга, бейсбольная кепка Red Sox; Я хочу удалить Surfboard.Удалить значения из списка, разделенного запятой из базы данных

Мой запрос прямо сейчас выглядит следующим образом

$select = mysql_query('SELECT * FROM children WHERE caseNumber="'.$caseNum.'" LIMIT 1 '); 
    $row = mysql_fetch_array($select); 

    foreach ($wish as $w) { 
     $allWishes = $row['wishes']; 
     $newWishes = str_replace($w, '', $allWishes); 
     $update = mysql_query("UPDATE children SET wishes='$newWishes' WHERE caseNum='".$caseNum."'"); 
} 

Но запрос UPDATE это ничего не удаляется. Как я могу делать то, что мне нужно?

+5

Я думаю, пожелания должны быть его собственный стол и увязаны здесь путем обмена ключа caseNumber. –

+0

Похоже, что отсутствует конкатенация строк, но после сортировки вы оставляете этот запрос открытым для SQL Injection - хакер действительно получит то, что он хочет. – Andrew

+0

@ Daren - это действительно правильный ответ, модель БД неверна и нуждается в исправлении. Жалость upvotes на комментарии не считать – Andrew

ответ

3

Использование these user-defined REGEXP_REPLACE() functions, вы можете заменить его с пустой строкой:

UPDATE children SET wishes = REGEXP_REPLACE(wishes, '(,(\s)?)?Surfboard', '') WHERE caseNum='whatever'; 

К сожалению, вы не можете просто использовать обычный старый REPLACE(), потому что вы не знаете, где в строке появляется «Surfboard». На самом деле, для регулярного выражения, вероятно, потребуется дополнительная настройка, если «Серфинг» происходит в начале или в конце.

Может быть, вы могли бы обрезать начальные и конечные запятые оставленные как это:

UPDATE children SET wishes = TRIM(BOTH ',' FROM REGEXP_REPLACE(wishes, '(,(\s)?)?Surfboard', '')) WHERE caseNum='whatever'; 

Так что же здесь происходит? Регулярное выражение удаляет «Surfboard» плюс дополнительную запятую & перед ней. Тогда окружающая функция TRIM() исключает возможную ведущую запятую в случае, если «Серфинг» произошел в начале строки. Возможно, это может быть связано с регулярным выражением, но, честно говоря, я слишком устал, чтобы разобраться в этом.

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

Update

Думая об этом более, я более неравнодушен просто заставляя использовать встроенный REPLACE(), а затем вычищать лишнюю запятую, где вы можете получить две запятые подряд. Это ищет две запятые бок о бок, как будто не было пробелов, разделяющих ваши исходные элементы списка. Если элементы были разделены запятыми и пробелами, измените ',,' на ', ,' во внешнем REPLACE() звоните.

UPDATE children SET wishes = TRIM(BOTH ',' FROM REPLACE(REPLACE(wishes, 'Surfboard', ''), ',,', ',')) WHERE caseNum='whatever'; 
1

Не совсем прямой ответ на ваш вопрос, но, как и Дарен, лучше иметь желания как свои собственные таблицы. Может быть, вы могли бы изменить схему базы данных, так что вы есть 3 таблицы, например:

children 
-> caseNum 
-> childName 

wishes 
-> caseNum 
-> wishId 
-> wishName 

childrensWishes 
-> caseNum 
-> wishId 

Затем добавить или удалить пожелание ребенка, вы просто добавить или удалить соответствующую строку из childrensWishes. Ваш текущий дизайн затрудняет манипулирование (как вы находите), плюс оставляет вас в опасности для несогласованных данных.

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

0

Make хочет таблица имеет следующий формат:

caseNumber,wish 

Тогда вы получите все пожелания ребенка, как это:

SELECT * FROM children c left join wishes w on c.caseNumber = w.caseNumber WHERE c.caseNumber= ? 

Удаление желание становится:

DELETE from wishes where caseNumber = ? 

Добавление желающий будет:

INSERT into wishes (caseNumber,wish) values (?,?) 

Возвращение одно желание становится:

SELECT * FROM children c left join wishes w on c.caseNumber = w.caseNumber WHERE c.caseNumber= ? LIMIT 1 
0

Имея пожелания индексируются в массиве, который затем сериализации может быть идея, в противном случае вы должны получить строку, фрагмент, удалить часть, которую вы надеваете» т, а затем конкатенировать останки. Это можно сделать, используя функцию explode().

Если вы должны были использовать массив, вы бы получить массив, а затем отсортировать через него с петлей, как это:

// Wishes array: 
// Array (
//  [0] Regular Jeans 
//  [1] Surfboard 
//  [2] Red Sox Baseball Cap 
//) 

$wishes = $row['wishes']; // This is a serialized array taken from the database 
$wishes = unserialize($wishes); 

foreach ($wishes as $key => $value) { 
    if ($value == 'Surfboard') { 
     unset($wishes[$key]); 
     break; 
    } 
} 

$wishes = serialize($wishes); 
// Update database 

Имейте в виду, что индекс [1] теперь не будет существовать в массив, так что если вы хотите иметь чистый массив Вам необходимо цикл через массив и сделать его создать новый массив сам по себе:

foreach ($wishes as $wishes) { 
    $newArray[] = $wishes; 
} 
0

Я думаю, что лучший ответ на такой вопрос здесь The best way to remove value from SET field?

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

 
UPDATE yourtable 
SET 
    categories = 
    TRIM(BOTH ',' FROM 
     REPLACE(
     REPLACE(CONCAT(',',REPLACE(col, ',', ',,'), ','),',2,', ''), ',,', ',') 
    ) 
WHERE 
    FIND_IN_SET('2', categories) 

Здесь вы можете иметь свое состояние в ИНЕКЕ. для получения дополнительной информации см. ссылку выше.

0

Вы можете создать функцию, как это:

CREATE FUNCTION `remove_from_set`(v int,lst longtext) RETURNS longtext CHARSET utf8 
BEGIN 
set @lst=REPLACE(@lst, ',,', ','); 
set @lng=LENGTH(@lst) - LENGTH(REPLACE(@lst, ',', ''))+1; 
set @p=find_in_set(@v,@lst); 
set @l=SUBSTRING_INDEX(@lst, ',', @p-1); 
set @r=SUBSTRING_INDEX(@lst, ',', @[email protected]); 
IF @l!='' AND @r!='' THEN 
    return CONCAT(@l,',',@r); 
ELSE 
    RETURN CONCAT(@l,'',@r); 
END IF; 
END 

Использование:

SELECT remove_from_set('1,,2,3,4,5,6',1) 
Смежные вопросы