【问题标题】:SQL: Change data type of a column from String to NumericSQL:将列的数据类型从字符串更改为数字
【发布时间】:2013-01-17 10:39:48
【问题描述】:

我将在 postgre 中将列的数据类型从“字符变化”更改为“bigint”。

旧列包含字符串“男性”和“女性”,现在我想将其更改为 0 或 1,分别代表男性或女性。

我认为一个简单的Alter表...Alter Column并不能解决这个问题,因为它不会进行男性-> 0,女性-> 1的转换。

谁能告诉我最安全的方法是什么?

非常感谢。

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    需要考虑的点

    1. 当您要使用 1 代表男性和 0 代表女性时, 为什么要使用 bigint 数据类型? BIT/TINYINT 数据类型将起作用
    2. 在更改列的数据类型之前, 您需要将男性更新为 1,女性更新为 0

    【讨论】:

    • 谢谢。我改变'male'->0和'female'->1并绑定使用命令:alter table information alter column gender TYPE bigint;但它失败并显示错误消息:错误:错误:列“性别”无法转换为类型 bigint。
    • 您可以一步完成。看我的例子。
    【解决方案2】:

    你们都在解决这个问题。这是一个简短的测试用例:

     create table test (username text, sex text); 
     insert into test values ('bob','male'),('sandra','female'),('stan','male'),('sue','male');
     select * from test;
     username |  sex   
     ----------+--------  
     bob      | male  
     sandra   | female  
     stan     | male  
     sue      | male 
     (4 rows)
    
     alter table test alter column sex type int using case when sex='male' then 0 when sex='female' then 1 end;
    
     select * from test;  
     username | sex 
     ----------+-----  
     bob      |   0  
     sandra   |   1  
     stan     |   0  
     sue      |   0 (4 rows)
    

    【讨论】:

      【解决方案3】:

      请注意,Postgres 能够提供ALTER COLUMN 的映射,根据@ScottMarlowe,这更简单。

      在大多数 RDBMS 中,这也可以按如下方式完成:

      1. 创建一个新的临时列,其中包含 Gender 的整数分类
      2. 更新表,使用 CASE / WHEN 将旧的 varchar 映射到新的 INT
      3. 删除旧的 varchar 列
      4. 将旧列添加回表中,这次使用新的数据类型
      5. 将临时 BIGINT 列中的数据复制回新列
      6. 删除临时 BIGINT 列

      您可能还需要处理无效的映射 - 我已经通过案例 ELSE 完成了这项工作。 正如@Madhivanan 建议的那样,使用BIGINT 进行性别分类听起来太过分了。

      SQL Fiddle here:

      -- Add new Column
      ALTER TABLE SomeTable ADD GenderTypeId BIGINT;
      
      -- Map old to new
      UPDATE SomeTable SET GenderTypeId = 
      CASE
         WHEN GenderVarchar = 'male' 
            THEN 0 
         WHEN  GenderVarchar = 'female' 
             THEN 1
         ELSE
            -1 -- Invalid source data
      END;
      
      -- Drop old
      ALTER TABLE SomeTable DROP COLUMN GenderVarchar;
      

      更新

      如果您需要使用与原始列名称相同的列名,那么您还需要重新添加旧列,这次使用新的数据类型,然后再次复制数据。 (我给它起了个新名字)

      ALTER TABLE SomeTable ADD Gender BIGINT;
      
      -- Copy the data across
      UPDATE SomeTable SET Gender = GenderTypeId;
      
      -- Drop the temporary column
      ALTER TABLE SomeTable DROP COLUMN GenderTypeId;
      

      【讨论】:

      • 看我的例子在一个语句中做到这一点。
      • +1,没错,不过请注意语法是 Postgres 特有的。实际上,许多 RDBMS 工具都会有前端 UI 来为您进行转换。
      • 非常正确。但由于标签是 PostgreSQL,我可以随意提供最有效的方式。请注意,对于非常大的数据集,转储表、删除它、通过 awk 或 sed 运行转储然后再次导入它通常更快。
      • 请注意,人们并没有真正意识到 PostgreSQL 优雅的其中一个例子,直到他们使用另一个数据库来做同样的事情并意识到它需要更多的工作。 OTOH,PostgreSQL 仍然没有正确的合并 sql 语句。叹息
      【解决方案4】:

      您必须先更新表并将男性更改为 0,将女性更改为 1

      然后你就可以Alter table ... Alter Column

      【讨论】:

        猜你喜欢
        • 2010-10-06
        • 2015-08-02
        • 2018-09-26
        • 2021-12-28
        • 2019-04-08
        • 1970-01-01
        • 2023-03-20
        • 2014-04-09
        • 1970-01-01
        相关资源
        最近更新 更多