【问题标题】:PostgreSQL can't cast type json to character varying[]PostgreSQL 无法将类型 json 转换为字符变 []
【发布时间】:2017-09-30 13:20:15
【问题描述】:

在我的 Rails 5.0.5 应用程序中,我需要将 json 列转换为 string, array: true

我的json 列中的值如下:

[ "200px-RR5219-0015R.png", "2017_03_25_2235.doc", "137555.jpg" ]

我尝试了这种迁移:

class ChangeTaskAttachmentsTypeToString < ActiveRecord::Migration[5.0]
  def change
    change_column :tasks, :attachments, :string, array: true
  end
end

得到了这个错误:

ActiveRecord::StatementInvalid: PG::DatatypeMismatch: ERROR:  column "attachments" cannot be cast automatically to type character varying[]
HINT:  You might need to specify "USING attachments::character varying[]".
: ALTER TABLE "tasks" ALTER COLUMN "attachments" TYPE character varying[]

然后我编辑了迁移:

class ChangeTaskAttachmentsTypeToString < ActiveRecord::Migration[5.0]
  def change
    change_column :tasks, :attachments, 'character varying[] USING attachments::character varying[]' 
  end
end

最后得到这个错误:

PG::CannotCoerce: ERROR:  cannot cast type json to character varying[]
: ALTER TABLE "tasks" ALTER COLUMN "attachments" TYPE character varying[] USING attachments::character varying[]

如何进行此迁移?

【问题讨论】:

    标签: ruby-on-rails postgresql ruby-on-rails-5 postgresql-9.3 rails-migrations


    【解决方案1】:

    我猜数组元素是文件名。如果是这样,那么您可以删除所有字符 []" 和空格并将结果拆分为数组,如下所示:

    with my_table(attachments) as (
    values
        ('[ "200px-RR5219-0015R.png", "2017_03_25_2235.doc", "137555.jpg" ]'::json)
    )
    select string_to_array(translate(attachments::text, '[] "', ''), ',')::varchar[]
    from my_table;
    
                         string_to_array                     
    ---------------------------------------------------------
     {200px-RR5219-0015R.png,2017_03_25_2235.doc,137555.jpg}
    (1 row)
    

    所以使用:

    ... USING string_to_array(translate(attachments::text, '[] "', ''), ',')::varchar[]
    

    更正式(和通用)的解决方案需要自定义函数,例如:

    create or replace function json_to_text_array(json)
    returns text[] language sql immutable as $$
        select array_agg(value)
        from json_array_elements_text($1)
    $$;
    

    可用于

    alter table tasks alter column attachments type text[] 
        using json_to_text_array(attachments);
    

    注意,我使用 text[] 作为 Postgres 的更自然选择,但如果重要的话,您可以将其替换为 varchar[]

    Db<>fiddle.中测试它

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 2018-01-13
      • 1970-01-01
      相关资源
      最近更新 更多