更新SQL多行删除字符串的一部分

时间:2016-07-05 11:02:57

标签: php mysql sql

我有一个像这样结构的SQL表

|[id]--|--[    colour    ]|  
|[ 1]--|--[red_blue_green]|   
|[ 2]--|--[ green_orange ]|   
|[ 3]--|--[  pink_green  ]|   
|[ 4]--|--[     green    ]|

我想要做的是从颜色中删除绿色,为此我尝试了这个

<?php
$del='green';
//DATABASE
require('config.php');
require('connect.php');
$db_content = mysql_query("SELECT * FROM colours WHERE colour LIKE '%_".$del."' OR colour LIKE '%_".$del."_%' OR colour LIKE '".$del."_%' OR colour='$del'");
$rows  = mysql_fetch_row($db_content);
foreach($rows as $row){
  $kaboom = explode('_', $row[6]);
  $i=0;

  while($kaboom[$i]!=$del){
    $i++;
  }

  unset($kaboom[$i]);

  $db_newcontent = implode('_', $kaboom);
  mysql_query("UPDATE colours SET colour='$db_newcontent' WHERE         id='{$row[0]}'");
}

但它不起作用。它没有给我任何错误消息,它只需要很多时间,然后它就会停止尝试。有什么建议吗?

2 个答案:

答案 0 :(得分:0)

您似乎在一个列中存储多个值。这是一个非常糟糕的主意。你应该有一个每种颜色一行的表,你现在有一个列表。

但有时候,我们会遇到其他人非常糟糕的设计。你可以做你想做的事:

update colours
    set colours = trim(both '_' from replace(concat('_', colours, '_'), '_green_', '_'))
    where concat('_', colours, '_') like '%_green_%';

答案 1 :(得分:0)

可以使用单个SQL语句。

以下代码(假设您的表名为 color )交叉将表连接到一对子查询,每个子查询返回数字0到9.这样每行提供100个副本,其中数字0到99.然后使用数字来获取每种颜色,WHERE子句排除那些“绿色”,然后使用GROUP_CONCAT将它们连接在一起。

UPDATE colour a
INNER JOIN
(
    SELECT id, GROUP_CONCAT(DISTINCT colours SEPARATOR '_') AS colour
    FROM
    (
        SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(colour, '_', tens.aCnt * 10 + units.aCnt + 1), '_', -1) AS colours
        FROM colour
        CROSS JOIN 
        (
            SELECT 1 AS aCnt UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0
        ) units
        CROSS JOIN 
        (
            SELECT 1 AS aCnt UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 0
        ) tens
        WHERE FIND_IN_SET('green', REPLACE(colour, '_', ','))
    ) sub0
    WHERE colours != 'green'
    GROUP BY id
) b
ON a.id = b.id
SET a.colour = b.colour

但是,在关系数据库中分隔字段通常是一个非常糟糕的主意。例如,如果要搜索列表中颜色为绿色的任何记录,则无法使用索引;数据库需要检查每条记录。您可以轻松地将这些分割为一个单独的表,主表上的每个记录都有多行(每个颜色一个表示主表上的记录)。您可以使用表连接轻松获取所有值,并且可以使用将使用索引的查询轻松检查特定值。

修改

如果你真的必须使用一个分隔的列,并且你想坚持使用类似于原始解决方案的东西,那么可以使用以下内容修复: -

<?php
$del='green';
//DATABASE
require('config.php');
require('connect.php');
$db_content = mysql_query("SELECT id, colour 
                            FROM colours 
                            WHERE FIND_IN_SET('".mysql_real_escape_string($del)."', REPLACE(colour, '_', ','))");
while ($rows  = mysql_fetch_assoc($db_content))
{
    $kaboom = explode('_', $rows['colour']);
    unset($kaboom[array_search($del, $kaboom)]);

    $db_newcontent = implode('_', $kaboom);
    mysql_query("UPDATE colours 
                    SET colour = '".mysql_real_escape_string($db_newcontent)."' 
                    WHERE id = ".(int)$rows[0]."");
}

再次编辑

规范化的例子。

你有一个(比方说)用户表。这有id字段: -

CREATE TABLE users
(
    id INT(11) NOT NULL AUTO_INCREMENT,
    user_name   VARCHAR(50),
    PRIMARY KEY (`id`),
    UNIQUE KEY `user_name` (`user_name`)
);

INSERT INTO users(id, user_name) VALUES
(1, 'Fred'),
(2, 'Freda'),
(3, 'Jo'),
(4, 'Joe');

然后,您可以获得每个用户的颜色表。每个用户每种颜色(或者他们输入的任何内容)都有一行: -

CREATE TABLE user_colours
(
    id INT(11) NOT NULL AUTO_INCREMENT,
    user_id INT(11) NOT NULL,
    colour  VARCHAR(50),
    PRIMARY KEY (`id`),
    KEY `user_id` (`user_id`),
    KEY `colour` (`colour`)
);

INSERT INTO user_colours(id, user_id, colour) VALUES
(1, 1, 'red'),
(2, 1, 'blue'),
(3, 1, 'green'),
(4, 2, 'green');
(5, 2, 'orange');
(6, 3, 'pink');
(7, 3, 'green');
(8, 4, 'green');

这样,如果您需要为用户添加额外的颜色,您只需找到该用户的ID并在第二个表中插入记录。例如,假设您要为 Freda 添加粉红色,您将获得Freda的id为2,然后在第二个表中插入一行,如 INSERT INTO user_colours (id,user_id,color)VALUES(NULL,2,'pink')

如果您需要删除它,那么您可以使用 DELETE FROM user_colours WHERE user_id = 2 AND color ='pink'

轻松完成

如果您想要计算每种颜色的用户数量,您可以这样做: -

SELECT colour, COUNT(user_id)
FROM user_colours
GROUP BY colour