【问题标题】:Renaming multiple columns in PostgreSQL在 PostgreSQL 中重命名多个列
【发布时间】:2015-10-28 20:52:21
【问题描述】:

我的表格有一堆格式如下的列:

_settingA
_settingB
_settingB

我想重命名它们只是为了添加一个前缀,如下所示:

_1_settingA
_1_settingB
_1_settingC

我有一个 很多 超过三列要以这种方式重命名。如果我只有三个,我会一个一个地手动完成。

实现这一目标最快/最有效的方法是什么?

【问题讨论】:

标签: sql postgresql automation sql-update ddl


【解决方案1】:

没有单一的命令方法。显然,您可以自己为RENAME 键入多个命令,但让我进行一些改进:) 正如我在this answer 中所说的

...对于所有此类批量管理操作,您可以使用 PostgreSQL 系统表为您生成查询,而不是手动编写它们

在你的情况下是:

SELECT
    'ALTER TABLE ' || tab_name || ' RENAME COLUMN '
    || quote_ident(column_name) || ' TO '
    || quote_ident( '_1' || column_name) || ';'
FROM (
    SELECT
        quote_ident(table_schema) || '.' || quote_ident(table_name) as tab_name,
        column_name
    FROM information_schema.columns  
    WHERE 
            table_schema = 'schema_name'
            AND table_name = 'table_name'
            AND column_name LIKE '\_%'
) sub;

这将为您提供一组字符串,这些字符串是 SQL 命令,例如:

ALTER TABLE  schema_name.table_name RENAME COLUMN "_settingA" TO "_1_settingA";
ALTER TABLE  schema_name.table_name RENAME COLUMN "_settingB" TO "_1_settingB";
...

如果您的表在public 模式中,则无需在WHERE 子句中使用table_schema还记得使用函数quote_ident() - 阅读我的原始答案以获得更多解释。

编辑:

我更改了我的查询,现在它适用于名称以下划线_ 开头的所有列。因为下划线是 SQL 模式匹配中的特殊字符,所以我们必须对其进行转义(使用\)才能准确找到它。

【讨论】:

  • 关于以下部分:AND column_name IN ('_settingA', '_settingB', '_settingC') 有没有一种方法可以通用地指定,而不必明确列出每个(有很多),以便它对以 @987654332 开头的任何列名进行操作@?
  • 是的,只需将AND column_name IN ('_settingA', '_settingB', '_settingC') 更改为AND column_name LIKE '\\_%'。我将编辑我的答案。
  • 不能让它工作。我将schema_name 替换为public,将table_name 替换为test,因为它们与表的架构和名称匹配。这给了我一个语法错误,似乎可以通过从第一个 SELECT 中删除 ; 来解决。但后来我得到ERROR: subquery in FROM must have an alias / LINE 5: FROM ( / HINT: For example, FROM (SELECT ...) [AS] foo。我已尝试按照提示进行操作,但仍无法找到有效的解决方案。
  • 很抱歉我会更正查询。你是对的。首先 ; 在第一个 SELECT 之后不应该在那里。其次,子查询必须有一个别名(我添加了sub)。 LIKE子句中的转义字符还有第三个错误——必须只有一个`\`。
  • 好的,太好了。我对您的方法了解更多:执行此操作实际上不会更新列名,而是生成执行此操作所需的查询。这很聪明,而且有效。一个改进建议:在第一个SELECT 的末尾添加|| ';',这样您就可以直接复制/粘贴字符串而无需进一步编辑。 (我可以看到您的原始答案 尝试 包含此内容,但它被解释为文字 ; 而不是字符串 ';'
【解决方案2】:

像这样简单的事情会起作用。

SELECT FORMAT(
  'ALTER TABLE %I.%I.%I RENAME %I TO %I;',
  table_catalog,
  table_schema,
  table_name,
  column_name,
  '_PREFIX_' + column_name
)
FROM information_schema.columns
WHERE table_name = 'foo';

%I 会做quote_ident,这要好得多。如果您在 PSQL 中,您可以使用 \gexec 运行它

【讨论】:

    【解决方案3】:

    您可以使用以下功能: (我用它为超过 50 列的表添加前缀)

    首先创建函数:

    CREATE OR REPLACE FUNCTION rename_cols( schema_name_ text,table_name_ text, prefix varchar(4))
        RETURNS bool AS
         $BODY$
         DECLARE
           rec_selection record;
            BEGIN
              FOR rec_selection IN (
                  SELECT column_name FROM information_schema.columns WHERE table_schema = schema_name_ AND table_name = table_name_) LOOP
                EXECUTE 'ALTER TABLE '||schema_name_||'.'||table_name_||' RENAME COLUMN "'|| rec_selection.column_name ||'" TO "'||prefix|| rec_selection.column_name ||'" ;';
              END LOOP;
            RETURN True;
           END;
         $BODY$
        LANGUAGE plpgsql VOLATILE
        COST 100;
    

    然后执行函数:

    SELECT rename_cols('public','test','d');
    

    希望对你有用,

    【讨论】:

      【解决方案4】:

      你不能这样做。

      除了 RENAMESET SCHEMA 之外的所有操作都可以组合成多个更改列表以并行应用。

      最有效的方法是使用 ActiveRecord。

      【讨论】:

        猜你喜欢
        • 2019-08-14
        • 2014-06-10
        • 2018-10-27
        • 1970-01-01
        • 2020-07-18
        • 1970-01-01
        • 2017-06-10
        • 1970-01-01
        • 2023-03-26
        相关资源
        最近更新 更多