19

フィールドから特定の値を削除するために、mysql SET フィールドを更新する最良の方法はどれですか。

例えば。値を持つフィールド カテゴリ: 1,2,3,4,5? リストから「2」を削除したい:

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

しかし、「2」がリストの最初または最後の値である場合はどうなるでしょうか?

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

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

1 つのクエリで 3 つのケースすべてを処理するにはどうすればよいでしょうか?!

4

7 に答える 7

32

セットから削除する必要がある値が複数回存在できない場合は、これを使用できます。

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

ここで動作することを確認してください。値が複数回存在する可能性がある場合、これによりすべての出現が削除されます。

UPDATE yourtable
SET
  categories =
    TRIM(BOTH ',' FROM
      REPLACE(
        REPLACE(CONCAT(',',REPLACE(col, ',', ',,'), ','),',2,', ''), ',,', ',')
    )
WHERE
  FIND_IN_SET('2', categories)
于 2013-02-01T09:26:17.800 に答える
8
update TABLE
set COLUMN = COLUMN & ~NUM
where COLUMN & NUM

以下のコメント セクションから引用: http://dev.mysql.com/doc/refman/5.0/en/set.html

ただし、NUM は値「2」ではなく、その内部インデックスであることに注意してください。したがって、「set ('1,'2','3','4','5')」のようにフィールドを定義すると、これらの値の対応するインデックスは (1,2,4,8,16) になります。

于 2013-02-01T11:03:54.790 に答える
5

最善の方法は、値をコンマで区切ってテーブルに保存しないことです。

しかし、あなたの質問に答えるためCASEに、これで使用できます、

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)
于 2013-02-01T09:03:51.930 に答える
2

これを行う別の方法を次に示します。

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は、すべての引数 (引数 1 を除く) を最初の引数 (この場合は',') と連結します (そうでない場合) NULLSETフィールドに値が含まれている場合は、フィールドの可能な値を探しますが、削除したい値はスキップします (2この場合)。はいの場合はその値を返し、そうでない場合は を返しますNULL。これは、セットのすべての値を で連結し','、削除したいものをスキップして、SETフィールドの新しい値を再構築します。

もちろん、これは のすべての可能な値を知っている場合にのみ機能しますcategoriesが、これはSETフィールドであるため、それはわかっています。

于 2016-10-13T09:22:23.940 に答える
0

ここでは、@palindrom と @JohnWoo によって最良の回答が提供されています。実際、@palindrom によって提供された回答は非常に優れており、受け入れられる回答になるはずです。

しかし、@JohnWoo によって提供された回答の場合、そのような大きな case ステートメントは絶対に不要であり、はるかに短くきちんとしたコーディングで実行できます。これを以下に示しました-

UPDATE my_table
    -> SET categories = CASE
    -> WHEN categories LIKE "2"
    -> THEN REPLACE(categories,"2","")
    -> WHEN categories LIKE "2%"
    -> THEN REPLACE(categories,"2,","")
    -> WHEN categories LIKE "%2%"
    -> THEN REPLACE(categories,",2","")
    -> ELSE categories
    -> END;

ここで、 2 つの更新ステートメントの結合に関するこの投稿を学習すると役立ちます。こちらにも回答をさせていただきました。

于 2021-09-27T18:16:32.687 に答える