Rails Migration内でのexecute >> SQLでUnicodeキャラクターが常にnullを返します


現在以下のことをしようとしています。

  1. ユーザーの名前(Name)をsplitted_nameという変数に代入。
  2. splitted_name[0]をfirst_nameに保存(first_name = splitted_name[0])
  3. splitted_name[0]とsplitted_name[-1]が別の値であればlast_nameにsplitted_name[-1]を保存

以下がコードです。

[code]

    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
    
[/code]

しかし、漢字でnameが保存されている場合にこのSQL文のu.nameが常にnullを返します。(DBのエンコーディングはUnicodeに設定されています。)

下記がエラー内容です。

PG::NotNullViolation: ERROR: null value in column "name" violates not-null
constraint  
=> 実際にはnameはnullではなく漢字のstringが入っています。

どなたか同様の問題を解決された方はいるでしょうか？原因と解決法がわかると助かります。

よろしくお願いします。




すみません。勉強不足でPostgresqlでArrayの最初の値がArray[0]Array[1]でないと取得出来ないことや、Array[-1]が無いことを知りませんでした。

以下のコードで動きました。

[code]

    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
    
[/code]

