2011-10-20 15 views
5

Tengo una tabla en mi base de datos MySQL llamada 'hijos'. En esa tabla hay una fila llamada 'deseos' (una lista separada por comas de los artículos de la lista de deseos del niño). Necesito poder actualizar esa lista para que solo elimine un valor. es decir, la lista = pantalones vaqueros regulares talla 12, tabla de surf, gorra de béisbol de los Medias Rojas; Quiero eliminar la tabla de surfEliminar valores en una lista separada por comas de la base de datos

Mi consulta ahora se ve así

$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."'"); 
} 

Pero la consulta de actualización no es la eliminación de cualquier cosa. ¿Cómo puedo hacer lo que necesito?

+5

creo deseos deben ser su propia mesa y ligado de nuevo aquí al compartir el caseNumber clave. –

+0

Parece que falta una concatenación de 1 cadena, pero una vez que se clasifica, está dejando esta consulta abierta a Inyección SQL: un hacker realmente obtendría lo que deseaba. – Andrew

+0

@Daren - esa es realmente la respuesta correcta, el modelo de DB está mal y necesita ser corregido. Pity upvotes en los comentarios no cuentan – Andrew

Respuesta

3

Usando these user-defined REGEXP_REPLACE() functions, es posible que pueda sustituirla por una cadena vacía:

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

Por desgracia, no se puede simplemente usar el viejo y simple REPLACE() porque usted no sabe dónde en la cadena aparece 'tabla de surf'. De hecho, la expresión regular anterior probablemente necesitaría ajustes adicionales si aparece "Tabla de surf" al principio o al final.

Tal vez usted podría ajustar de ataque y de salida comas sobrantes como esto:

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

Entonces, ¿qué está pasando aquí? La expresión regular quita 'Tabla de surf' más una coma opcional & espacio antes. Luego, la función circundante TRIM() elimina una posible coma inicial en caso de que ocurra 'Tabla de surf' al comienzo de la cadena. Eso también podría ser manejado por la expresión regular, pero francamente, estoy demasiado cansado para descifrarlo.

Nota, Nunca he usado estos y no puedo garantizar su efectividad o robustez, pero es un buen lugar para comenzar. Y, como otros mencionan en los comentarios, realmente debería tenerlos en una tabla de lista de deseos normalizada, en lugar de como una cadena separada por comas.

actualización

Pensando en esto más, estoy más parcial a simplemente forzando el uso de una función de REPLACE() y luego la limpieza de la coma adicional donde se puede obtener dos comas en una fila. Esto busca dos comas una al lado de la otra, como si no hubiera habido espacios que separaran los elementos de la lista original. Si los artículos se han separado por comas y espacios, cambie ',,' a ', ,' en la llamada externa REPLACE().

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

No es exactamente una respuesta directa a su pregunta, pero al igual que Daren dice que es mejor tener deseos como su propia mesa. Tal vez usted podría cambiar el esquema de base de datos por lo que tiene 3 mesas, por ejemplo:

children 
-> caseNum 
-> childName 

wishes 
-> caseNum 
-> wishId 
-> wishName 

childrensWishes 
-> caseNum 
-> wishId 

A continuación, para añadir o eliminar un deseo para un niño, que acaba de añadir o eliminar la fila relevante de childrensWishes. Su diseño actual hace que sea difícil de manipular (como usted está encontrando), además lo deja en riesgo de datos inconsistentes.

Como respuesta más directa, puede solucionar su problema actual obteniendo la lista de deseos, explotándolos, eliminando el que no desea de la matriz e implosionándolo() de nuevo a una cadena para actualizar la base de datos.

0

hacer que los deseos de la tabla tienen el siguiente formato:

caseNumber,wish 

entonces obtendrá todos los deseos de un niño como éste:

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

Extracción de un deseo se convierte en:

DELETE from wishes where caseNumber = ? 

Adición de una deseo se convierte en:

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

Volviendo un deseo se convierte en:

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

Tener los deseos indexadas en una matriz que a continuación serializado podría ser una idea, de lo contrario tendría que recuperar la cadena, cortarlo, quitar la parte usted don' t querer, luego concatenar los restos. Esto se puede hacer utilizando la función explode().

Si se va a utilizar una matriz, que recuperaría la matriz y luego ordenar a través de ella con un lazo como esto:

// 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 

Tenga en cuenta que el índice [1] ya no existirá en el matriz, por lo que si usted desea tener una matriz limpia que debería recorrer la matriz y hacer que crear una nueva matriz por sí mismo:

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

creo que la mejor respuesta a tal cuestión es aquí The best way to remove value from SET field?

consulta debe ser como este que cubre el, valor o valor, o sólo un valor en la columna de la coma

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

Aquí separado puede tener su condición en la cláusula where. para más detalles, consulte el enlace de arriba.

0

Puede crear función como esta:

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 

Usando:

SELECT remove_from_set('1,,2,3,4,5,6',1) 
Cuestiones relacionadas