4

Rails 3.2 と共に PostgreSQL を使用しています。私のデータベース移行の1つには次のものがあります:

execute <<-SQL
  CREATE INDEX users_multi_idx
  ON users (lower(left(fname, 1)), fname)
  WHERE deleted_at IS NULL;
SQL

一部のデータベースで移行中に、次のエラーが発生します。

==  AddFnameIndexToUsers: migrating ===========================================
-- execute("      CREATE INDEX users_multi_idx\n      ON users (lower(left(fname, 1)), fname)\n      WHERE deleted_at IS NULL;\n")
rake aborted!
An error has occurred, this and all later migrations canceled:

PG::Error: ERROR:  function left(character varying, integer) does not exist
LINE 2:       ON users (lower(left(fname, 1)), fname)
                              ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
:       CREATE INDEX users_multi_idx
      ON users (lower(left(fname, 1)), fname)
      WHERE deleted_at IS NULL;

奇妙なのは、これがすべてのデータベースで発生するわけではなく、一部のデータベース (ステージング) だけで発生することです。このインデックスの実行の何が問題なのかについて何か提案はありますか?

4

2 に答える 2

9

というタグを付けましたが、ここで古いバージョンを扱っているのではないかと強く思います。次のように尋ねると、何が得られますか。

SELECT version();

left()バージョン 9.1 で導入されました。古いバージョンの場合は、次のように置き換えますleft(fname, 1)

substr(fname, 1, 1)

ドロップイン交換

何らかの理由 ( @Wize など) でクエリを変更できない場合は、9.1 より前の古いバージョンのドロップイン置換を作成できます。

CREATE OR REPLACE FUNCTION public.left(text, int)
 RETURNS text LANGUAGE sql STABLE COST 30 AS
'SELECT substr($1, 1, $2)';

これは通常、バージョンのアップグレード後に競合を引き起こすことはありません。これは、デフォルトのスキーマ検索パスpg_catalog(暗黙的に) beforepublicを持っているため、ユーザー定義関数は、システム関数が終了するとすぐに無効になります (明示的にスキーマ修飾されていない限り)。ただし、いずれにせよ、バージョン アップグレード後に削除する必要があります。

これを追加して、@Wize が提供したものに対する多くの改善を提案しました。

  • 複数の理由でLANGUGAE sql(not ) を使用します。plpgsql

  • function volatility を使用STABLEします。これは適切であり、パフォーマンスに役立ちます。

  • $n古いバージョンの SQL 関数ではパラメーター名がサポートされていないため、関数パラメーターを参照するには表記法を使用してください。

  • 関数をpublicスキーマに明示的に作成します。そうしないと、現在のユーザーの「プライベート」スキーマで作成され、他のユーザーには機能しない可能性があります。スキーマ検索パスによっては、これが最適です。

  • デフォルトの文字型であり、または戻り値textと同じであるdata type を使用します。同様に機能します。left()substr()varchar

于 2012-10-19T20:43:13.260 に答える
2

9.1 より前のバージョンの Posgres 用に次の関数を作成するだけです。

CREATE OR REPLACE FUNCTION left(s character varying,i int)
RETURNS character varying AS
$BODY$
BEGIN
  return substr(s, 1, i);
 END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
于 2015-11-20T05:05:15.247 に答える