8

这个 psql 会话片段应该是不言自明的:

psql (9.1.7)
Type "help" for help.
=> CREATE TABLE languages(language VARCHAR NOT NULL);
CREATE TABLE
=> INSERT INTO languages VALUES ('english'),('french'),('turkish');
INSERT 0 3
=> SELECT language, to_tsvector('english', 'hello world') FROM languages;
 language|     to_tsvector     
---------+---------------------
 english | 'hello':1 'world':2
 french  | 'hello':1 'world':2
 turkish | 'hello':1 'world':2
(3 rows)

=> SELECT language, to_tsvector(language, 'hello world') FROM languages;
ERROR:  function to_tsvector(character varying, unknown) does not exist
LINE 1: select language, to_tsvector(language, 'hello world')...
                         ^
HINT:  No function matches the given name and argument types.  
You might need to add explicit type casts.

问题是 Postgres 函数to_tsvector不喜欢字段类型,但是根据文档,varchar这个调用应该是完全正确的?

4

2 回答 2

12

使用显式类型转换:

SELECT language, to_tsvector(language::regconfig, 'hello world') FROM languages;

或将列更改languages.language为 type regconfig请参阅@Swav 的回答。

为什么?

Postgres 允许函数重载。函数签名由它们的(可选的模式限定)名称加上(列表)输入参数类型定义。2 参数形式to_tsvector()期望类型regconfig作为第一个参数:

SELECT proname, pg_get_function_arguments(oid)
FROM   pg_catalog.pg_proc
WHERE  proname = 'to_tsvector'

   proname   | pg_get_function_arguments
-------------+---------------------------
 to_tsvector | text
 to_tsvector | regconfig, text             -- you are here

如果没有现有函数完全匹配,则函数类型解析的规则决定最佳匹配 - 如果有的话。这是成功的 to_tsvector('english', 'hello world'),因为'english'它是一个无类型的字符串文字。但是使用typedvarchar参数失败,因为没有注册的隐式转换from varcharto regconfig手册

丢弃输入类型不匹配且无法转换(使用隐式转换)以匹配的候选函数。为此,未知文字被假定为可转换为任何内容。

大胆强调我的。
注册演员表regconfig

SELECT castsource::regtype, casttarget::regtype, castcontext
FROM   pg_catalog.pg_cast
WHERE  casttarget = 'regconfig'::regtype;

 castsource | casttarget | castcontext
------------+------------+-------------
 oid        | regconfig  | i
 bigint     | regconfig  | i
 smallint   | regconfig  | i
 integer    | regconfig  | i

解释castcontext

castcontext char
指示可以在哪些上下文中调用强制转换。e仅表示作为显式强制转换(使用CAST::语法)。a 意味着隐含地分配给目标列,以及显式地。i隐含在表达式中,以及其他情况。

在 CREATE CAST 一章中阅读有关三种不同类型分配 的更多信息。

于 2013-01-25T15:09:28.383 回答
1

Erwin Brandstetter 答案的替代方法

您可以将语言列定义为 regconfig 类型,这将使​​您的查询不那么冗长,即:

CREATE TABLE languages(language regconfig NOT NULL DEFAULT 'english'::regconfig)

我在上面将英语设置为默认值,但这不是必需的。之后您的原始查询

SELECT language, to_tsvector(language, 'hello world') FROM languages;

会工作得很好。

于 2014-02-24T18:16:16.520 回答