Rails迁移错误:Unicode字符串在“execute>> SQL”中返回null值

时间:2015-10-18 16:30:40

标签: ruby-on-rails postgresql unicode

我正在尝试在迁移中执行以下操作。

  1. 将“Name”拆分为splitted_name数组。
  2. SET first_name as splitted_name [0]。
  3. 如果splitted_name [0]和splitted_name [-1]不同,则将last_name设置为splitted_name [-1]。
  4. 如果splitted_name [0]和splitted_name [1]相同,则将last_name设置为空字符串。
  5. 这是代码。

    class ConvertNameIntoFirstAndLastName < ActiveRecord::Migration
      def up
        execute <<-SQL
          DO
          $do$
          DECLARE
            u record;
          BEGIN
          FOR u IN SELECT * FROM users LOOP
            DECLARE
              splitted_name text[];
            BEGIN
              splitted_name := CASE WHEN u.name IS NULL THEN '{''}'
                                    ELSE regexp_split_to_array(u.name, E'\\s+')
                               END;
              UPDATE users
                SET 
                  first_name = splitted_name[0],
                  last_name = CASE WHEN splitted_name[0] = splitted_name[-1] THEN ''
                                   ELSE splitted_name[-1]
                              END,
                  name = splitted_name[0] || ' ' || (CASE WHEN splitted_name[0] = splitted_name[-1] THEN '{''}'
                                                          ELSE splitted_name[-1]
                                                    END)
              WHERE id = u.id;
            END;
          END LOOP;
          END;
          $do$;
        SQL
      end
    
      def down
      end
    end
    

    问题是当名称是unicode字符时,u.name总是返回null。数据库编码设置为Unicode。

    以下是错误消息。

    PG :: NotNullViolation:ERROR:“name”列中的空值违反了非空约束 =&GT;该名称实际上不是null,而是一些Unicode字符串。

    您是否知道此错误的原因是什么以及如何解决此问题?

1 个答案:

答案 0 :(得分:0)

抱歉,我太天真了,以至于我不知道我应该使用splitted_name [1]作为first_name,而且没有数组[-1]。

此代码有效。

class ConvertNameIntoFirstAndLastName < ActiveRecord::Migration
  def up
    execute <<-SQL
      DO
      $do$
      DECLARE
        u record;
      BEGIN
      FOR u IN SELECT * FROM users LOOP
        DECLARE
          splitted_name text[];
        BEGIN
          splitted_name := regexp_split_to_array(regexp_replace(u.name, ' ', ' '), ' ');
          UPDATE users
            SET 
              first_name = splitted_name[1],
              last_name = CASE WHEN splitted_name[1] = splitted_name[array_upper(splitted_name, 1)] THEN ''
                               ELSE splitted_name[array_upper(splitted_name, 1)]
                          END,
              name = splitted_name[1] || ' ' || (CASE WHEN splitted_name[1] = splitted_name[array_upper(splitted_name, 1)] THEN ''
                                                      ELSE splitted_name[array_upper(splitted_name, 1)]
                                                END)
          WHERE id = u.id;
        END;
      END LOOP;
      END;
      $do$;
    SQL
  end

  def down
  end
end