4

我正在使用 PostgreSQL 和 Rails 3.2。我的数据库迁移之一具有以下内容:

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(隐式)具有before public,因此一旦系统函数退出,用户定义的函数就会停止运行 - 除非明确地限定模式。但是无论如何,您都应该在版本升级后将其删除。

我添加了这个,以建议对 @Wize 提供的一些改进:

  • 使用LANGUGAE sql(not plpgsql) 有多种原因:

  • 使用函数 volatile STABLE,这是合适的并且有助于性能。

  • 使用$n符号来引用函数参数,因为旧版本中的 SQL 函数不支持参数名称。

  • public在模式中显式创建函数。否则,它可能是在当前用户的“私有”模式中创建的,不适用于其他用户。根据您的架构搜索路径,这应该最适合您。

  • 使用 data type text,这是默认的字符类型,与left()orsubstr()返回相同。也适用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 回答