根据传递给PostgreSQL函数的列名数组获取行值

Bil*_*ill 1 postgresql

我正在尝试在PostgreSQL 9.2中设置全文搜索。我创建了一个新表来保存要搜索的内容(以便可以搜索许多不同类型的项目),如下所示:

CREATE TABLE search (
    target_id bigint PRIMARY KEY,
    target_type text,
    fts tsvector
);

CREATE INDEX search_fts ON search USING gin(fts);
Run Code Online (Sandbox Code Playgroud)

每次将新项目插入(或更新)到我要搜索的各个表之一时,应将其自动添加到search表中。假设我的表如下所示:

CREATE TABLE item (id bigint PRIMARY KEY, name text NOT NULL, description text);
Run Code Online (Sandbox Code Playgroud)

我创建了一个触发器,该触发器传递了我希望能够搜索的列名:

CREATE TRIGGER insert_item_search BEFORE INSERT
    ON item FOR EACH ROW EXECUTE PROCEDURE
    insert_search('{name, description}'::text[]);
Run Code Online (Sandbox Code Playgroud)

然后创建一个新函数insert_search为:

CREATE OR REPLACE FUNCTION insert_search(cols text[]) RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO search (target_id, target_type, fts) VALUES (
      NEW.id, TG_TABLE_NAME, to_tsvector('english', 'foo')
    );
    RETURN NEW;
END;
$$ LANGUAGE PLPGSQL;
Run Code Online (Sandbox Code Playgroud)

我的问题是,我该如何在基于表值传递colsto_tsvector?目前,该函数正在被调用并正确插入idtype,但是我不知道基于cols参数动态获取其他值的正确方法。

Mat*_*sOl 5

首先,要传递参数,只需将其直接发送:

CREATE TRIGGER insert_item_search BEFORE INSERT
    ON item FOR EACH ROW EXECUTE PROCEDURE
    insert_search('name', 'description');
Run Code Online (Sandbox Code Playgroud)

并且,从PL / pgSQL中,您将以数组形式获取这些参数TG_ARGV。但是,问题在于PL / pgSQL无法NEW根据其名称从记录中获取值。为此,您可以使用允许您执行此操作的语言(例如PL / python或PL / perl)或使用hstore扩展名

我会坚持使用最后一种hstore语言(除非您已经使用其他一种语言来创建函数):

CREATE OR REPLACE FUNCTION insert_search() RETURNS TRIGGER AS $$
DECLARE
        v_new hstore;
BEGIN
        v_new = hstore(NEW); -- convert the record to hstore
        FOR i IN 0..(TG_NARGS-1) LOOP
                INSERT INTO search (target_id, target_type, fts) VALUES (
                  NEW.id, TG_TABLE_NAME, to_tsvector('english', v_new -> TG_ARGV[i])
                );
        END LOOP;
    RETURN NEW;
END;
$$ LANGUAGE PLPGSQL;
Run Code Online (Sandbox Code Playgroud)

如您在上面看到的,我使用hstore的运算符->根据名称(on TG_ARGV[i])获取值。