简体   繁体   English

tsvector更新中的PostgreSQL正则表达式

[英]Postgresql regex in tsvector update

I have the following update trigger for a tsvector column 我对tsvector列有以下更新触发器

CREATE TRIGGER tsvector_user_update
BEFORE INSERT OR UPDATE ON users
FOR EACH ROW EXECUTE PROCEDURE 
tsvector_update_trigger(user_tsv, 'pg_catalog.english', firstname, surname, email, card_id);

This works fine, however my card_id column (text) contains a pre-amble that the user is not aware of (it is added after the card is scanned), so I would like to strip out the pre-amble when the tsvector value is generated, I have tried the trigger function as a start 这可以正常工作,但是我的card_id列(文本)包含用户不知道的前同步码(在扫描卡后添加),因此我想在tsvector值为时去除前同步码生成后,我已尝试将触发器功能作为开始

CREATE FUNCTION user_change_trigger() RETURNS trigger AS $$
BEGIN
NEW.user_tsv = setweight(to_tsvector('pg_catalog.english', coalesce(NEW.firstname,'')), 'A') ||
    setweight(to_tsvector('pg_catalog.english', coalesce(NEW.surname,'')), 'A') ||
    setweight(to_tsvector('pg_catalog.english', coalesce(REGEXP_REPLACE(NEW.card_id, '^\d+PRE', ''),'')), 'B') ||
    setweight(to_tsvector('pg_catalog.english', coalesce(NEW.email,'')), 'C');
    return new;
END

$$ LANGUAGE plpgsql;

CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
ON users FOR EACH ROW EXECUTE PROCEDURE user_change_trigger();

Which executes, but I get the following: 执行,但我得到以下信息:

WARNING:  nonstandard use of escape in a string literal

And no updated tsvector 而且没有更新的tsvector

The pre-amble is an integer followed by 'PRE'. 前同步码是一个整数,后跟“ PRE”。

(PostgreSQL 9.0) (PostgreSQL 9.0)

Basic trigger design 基本触发设计

The problem is of principal nature. 问题是主要的。 In PostgreSQL you create a trigger function that does the work. 在PostgreSQL中,您可以创建一个触发函数来完成工作。 I don't see your trigger function in the question. 我没有在问题中看到您的触发功能。

Then you create a trigger which makes use of this function. 然后,创建一个使用此功能的触发器 You can only pass constants to a trigger function. 您只能将常量传递给触发函数。 Consider this quote from the manual about CREATE TRIGGER 考虑手册中有关CREATE TRIGGER引用

function_name function_name

A user-supplied function that is declared as taking no arguments and returning type trigger, which is executed when the trigger fires. 一个用户提供的函数,该函数声明为不带任何参数并返回类型触发器,该函数在触发器触发时执行。

arguments 论点

An optional comma-separated list of arguments to be provided to the function when the trigger is executed. 执行触发器时,将提供给函数的可选的逗号分隔参数列表。 The arguments are literal string constants . 参数是文字字符串常量 Simple names and numeric constants can be written here, too, but they will all be converted to strings. 简单名称和数字常量也可以在此处编写,但是它们都将转换为字符串。 Please check the description of the implementation language of the trigger function to find out how these arguments can be accessed within the function; 请检查对触发器函数的实现语言的描述,以了解如何在函数中访问这些参数。 it might be different from normal function arguments. 它可能与普通函数参数不同。

Bold emphasis mine. 大胆强调我的。

Use NEW to access the column values inside the trigger function. 使用NEW访问触发器函数中的列值。 You don't need to pass them as arguments. 您无需将它们作为参数传递。 Get a grip on the basic concept first. 首先掌握基本概念。 Start here. 从这里开始。

regexp_replace()

Use: 采用:

regexp_replace(card_id, '^\d+PRE', '')

.. since the leading characters are supposed to be digits only (and at least one of them). ..因为前导字符应仅是数字(并且至少是其中之一)。

Proper trigger & function 正确的触发和功能

The following test case works for me on PostgreSQL 9.1.6. 以下测试用例在PostgreSQL 9.1.6上对我有效 Your version looks basically good to me, I only made minor changes. 您的版本对我来说基本上不错,我只做了很小的更改。 But keep reading ... 但是继续阅读...

Create test environment (will be rolled back at the end): 创建测试环境(将在最后回滚):

BEGIN;
CREATE SCHEMA test;
SET search_path = test;

CREATE TABLE users (
    users_id serial primary key
   ,firstname text
   ,surname text
   ,card_id text
   ,email text
   ,user_tsv tsvector
   );

Trigger function: 触发功能:

CREATE FUNCTION user_change_trigger()
  RETURNS trigger AS
$func$
BEGIN

NEW.user_tsv :=
   setweight(to_tsvector('pg_catalog.english', coalesce(NEW.firstname,'')), 'A')
|| setweight(to_tsvector('pg_catalog.english', coalesce(NEW.surname,'')), 'A')
|| setweight(to_tsvector('pg_catalog.english', coalesce(regexp_replace(NEW.card_id, '^\d+PRE', ''),'')), 'B')
|| setweight(to_tsvector('pg_catalog.english', coalesce(NEW.email,'')), 'C');

RETURN NEW;
END

$func$ LANGUAGE plpgsql;

The assignment operator of plpgsql is := - unlike SQL where = is used. plpgsql赋值运算符是:= -与使用= SQL不同。

Trigger: 触发:

CREATE TRIGGER tsvectorupdate
BEFORE INSERT OR UPDATE ON users
FOR EACH ROW EXECUTE PROCEDURE user_change_trigger();

Tests: 测试:

INSERT INTO users (firstname, surname, card_id, email)
VALUES ('Erwin', 'Brandstetter', '123PRE456', 'foo@dummy.org')
RETURNING *;

-- looks good!

UPDATE users SET firstname = 'Walter' WHERE TRUE
RETURNING *;

-- looks good, too!

Clean up: 清理:

ROLLBACK;

standard_conforming_strings

Explore your setting of standard_conforming_strings . 探索您的standard_conforming_strings设置。 The WARNING suggests that you don't have this setting on, which would require that you double the backslash in: 警告建议您不要启用此设置,这需要将反斜杠加倍:

'^\\d+PRE'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM