Il modo migliore per rimuovere il valore dal campo SET?

Qual è il modo migliore per aggiornare un campo SET mysql, per rimuovere un valore specifico dal campo.

Per esempio. categorie di campi con valori: 1,2,3,4,5? Voglio rimuovere “2” dall’elenco:

UPDATE table SET categories = REPLACE(categories, ',2,', ',') WHERE field LIKE '%,2,%'; 

Ma cosa succede se ‘2’ è il primo o l’ultimo valore dalla lista?

 UPDATE table SET categories = REPLACE(categories, '2,', '') WHERE field LIKE '2,%'; UPDATE table SET categories = REPLACE(categories, ',2', '') WHERE field LIKE ',2%'; 

Come posso gestire tutti e 3 i casi con una sola query ?!

Se il valore che devi rimuovere dal set non può essere presente più di una volta, puoi usare questo:

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

vederlo funzionare qui . Se il valore può essere presente più di una volta, questo rimuoverà tutte le occorrenze di esso:

 UPDATE yourtable SET categories = TRIM(BOTH ',' FROM REPLACE( REPLACE(CONCAT(',',REPLACE(col, ',', ',,'), ','),',2,', ''), ',,', ',') ) WHERE FIND_IN_SET('2', categories) 
 update TABLE set COLUMN = COLUMN & ~NUM where COLUMN & NUM 

Tratto dalla sezione commenti di: http://dev.mysql.com/doc/refman/5.0/en/set.html

Attenzione però, NUM non è il valore ‘2’ ma il suo indice interno. Quindi se hai definito il campo come “set (‘1,’ 2 ‘,’ 3 ‘,’ 4 ‘,’ 5 ‘)” allora gli indici corrispondenti di questi valori sono (1,2,4,8,16).

Il modo migliore è di non salvare valori separati da una virgola sul tavolo.

Ma per rispondere alla tua domanda, puoi usare CASE su questo,

 UPDATE table SET categories = CASE WHEN field LIKE '%,2,%' -- In the middle THEN REPLACE(categories, ',2,', ',') WHEN field LIKE '2,%' -- At the beginning THEN REPLACE(categories, '2,', '') WHEN field LIKE '%,2' -- At the end THEN REPLACE(categories, ',2', '') WHEN field = '2' -- At whole THEN '' END WHERE FIND_IN_SET('2', categories) 

Ecco un altro modo per farlo:

 UPDATE table SET categories = CONCAT_WS(',', IF(FIND_IN_SET('1', categories), '1', NULL), -- Note that '2' is missing here! IF(FIND_IN_SET('3', categories), '3', NULL), IF(FIND_IN_SET('4', categories), '4', NULL), IF(FIND_IN_SET('5', categories), '5', NULL) ); 

CONCAT_WS concatena tutti i suoi argomenti (eccetto l’argomento 1) con il primo argomento (in questo caso ',' ), se non sono NULL . Cerchiamo ogni ansible valore del campo SET se il campo lo contiene ma salta quello che vogliamo rimuovere ( 2 in questo caso). Se sì, restituiamo quel valore, altrimenti NULL . Questo concatena tutti i valori dell’insieme con ',' , saltando quello che vogliamo eliminare, ricostruendo un nuovo valore per il campo SET .

Questo ovviamente funziona solo se conosci tutti i valori possibili delle categories , ma poiché questo è un campo SET , lo sai.

categorie di campi con valori: 1,2,3,4,5? Voglio rimuovere “2” dall’elenco:

Trovo che l’utilizzo di un operatore bit a bit per essere il modo più pulito. Il valore di ritorno di FIND_IN_SET() restituisce la posizione del valore in modo da poterlo utilizzare per calcolare il bit da distriggersre.

 UPDATE table SET categories = CAST(categories AS UNSIGNED) & ~POW(2, FIND_IN_SET('2', categories)) WHERE FIND_IN_SET('2', categories); 

Notare che (categories+0) è forzare il valore corrente SET su un numero intero. Potresti scoprire che è ridondante, ma fai attenzione agli insiemi che contengono molti valori. Ho scoperto che la matematica risultante può essere sbagliata se non si forza esplicitamente l’insieme su un numero intero – sicuramente non si vuole il valore sbagliato quando si esegue un’operazione come questa.