2

我需要更新我的数据库中的表。为简单起见,我们假设表的名称是tab并且它有 2 列:id (PRIMARY KEY, NOT NULL)col (UNIQUE VARCHAR(300))。我需要以这种方式更新表:

id                    col
----------------------------------------------------
1                     'One two three'
2                     'One twothree'
3                     'One two       three'
4                     'Remove white spaces'
5                     'Something'
6                     'Remove whitespaces '

至:

id                    col
----------------------------------------------------
1                     'Onetwothree'
2                     'Removewhitespaces'
3                     'Something'

Id更新后的行数和顺序并不重要,可以不同。我使用 PostgreSQL。一些列是外键。这就是为什么放弃UNIQUE约束col会很麻烦。

4

3 回答 3

2

我认为仅以replace这种格式使用就可以满足您的要求。

update tab
set col = replace(col, ' ', '');

这是一个SQLFiddle

于 2013-07-18T15:42:54.700 回答
1

你不应该使用非描述性的 column name id,即使一些半机智的 ORM 习惯这样做。我用tab_id这个演示代替。

我这样解释您的描述:您有其他表的 FK 列指向 tab.col. 就像child1下面我的示例中的表格。

要清理混乱,请在单个会话中执行所有这些操作以保留我使用的临时表。更好的是,在一次事务中完成所有操作。

  1. 更新所有引用表,使所有引用行指向.tab

    创建一个up用于所有更新的转换表:

    CREATE TEMP TABLE up AS
    WITH t AS (
        SELECT tab_id, col, replace(col, ' ', '') AS col1
             ,row_number() OVER (PARTITION BY replace(col, ' ', '')
                                 ORDER BY  tab_id) AS rn
        FROM   tab
        )
    SELECT b.col AS old_col, a.col AS new_col
    FROM  (SELECT * FROM t WHERE rn = 1) a
    JOIN  (SELECT * FROM t WHERE rn > 1) b USING (col1);
    

    然后更新所有参考表。

    UPDATE child1 c
    SET    col = up.new_col
    FROM   up
    WHERE  c.col = up.old_col;
    
    --  more tables?   
    

    -> SQL小提琴

    现在,所有的引用都指向了一群骗子中的“第一个”,而你已经获得了杀死其他人的许可证。

  2. 从 中删除除第一行之外的重复行tab

    DELETE FROM tab t
    USING  up
    WHERE  t.col = up.old_col
    
  3. 确保所有引用 FK 约束都有该ON UPDATE CASCADE子句。

    ALTER TABLE child1 DROP CONSTRAINT child1_col_fkey;
    
    ALTER TABLE child1  ADD CONSTRAINT child1_col_fkey FOREIGN KEY (col)
    REFERENCES tab (col)
    ON UPDATE CASCADE;
    
    -- more tables?
    
  4. 通过删除空白来清理您的价值观

    UPDATE tab
    SET    col = replace(col, ' ', '');
    

    这只需要处理好的旧空格字符(ASCII 值 32,Unicode U+0020)。你有其他人吗?

所有 FK 约束都应该指向tab.tab_id开始。你的桌子会更小更快,所有这一切都会更容易。

于 2013-07-18T18:14:23.557 回答
0

我比Erwin更容易解决它。我的计算机上没有 SQL 来测试它,但类似的东西对我有用:

DELETE FROM tab WHERE id IN (
    SELECT id FROM (
        SELECT id, col, row_number() OVER (PARTITION BY regexp_replace(col, '[ \t\n]*', '')) AS c WHERE c > 1;
    )
)

UPDATE tab SET col = regexp_replace(col, '[ \t\n]*', '');
于 2013-07-20T12:17:32.403 回答