PG ::错误:错误:函数left(字符变化,整数)不存在

时间:2012-10-19 20:36:18

标签: postgresql substring postgresql-9.1

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

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

在某些dbs上迁移时,我们收到以下错误:

==  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;

奇怪的是,这并不会发生在所有dbs上,只有一些(暂存)。关于这个索引执行有什么问题的任何建议?

2 个答案:

答案 0 :(得分:9)

你标记了它,但我强烈怀疑你在这里处理旧版本。当你提问时,你会得到什么:

SELECT version();
版本9.1引入了

left()。对于旧版本,使用以下代码替换left(fname, 1)

substr(fname, 1, 1)

直接替换

如果由于某种原因(like @Wize)无法修改查询,则可以在9.1之前为旧版本创建插件替换:

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

在版本升级后,这通常不会导致冲突,因为默认schema search pathpg_catalog之前有public(隐式),所以用户 - 一旦系统函数退出,定义的函数就会停止运行 - 除非明确地进行模式限定。但无论如何,你应该在版本升级后删除它。

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

  • 出于多种原因使用LANGUGAE sql(而不是plpgsql):

  • 使用函数波动率STABLE,这是合适的并有助于提升绩效。

  • 使用$n表示法引用函数参数,因为旧版本的SQL函数不支持参数名称。

  • 显式创建public架构中的函数。否则,它可能在当前用户“私有”架构中创建,而不适用于其他用户。这取决于您的schema search path,这应该是最适合您的。

  • 使用数据类型text,这是默认字符类型,与left()substr()返回相同。适用于varchar

答案 1 :(得分:1)

为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;