Postgres触发器不能插入包含数字或特殊字符的值

时间:2018-01-24 17:34:12

标签: postgresql database-trigger

我想请求您帮助解决我的问题。我想在插入之前创建一个触发器。如果有人想插入包含数字或特殊字符的名称,它将无法使用。有效值只能包含a-zA-Z字母。

if (performance.navigation.type == 1) {
    // reloaded
  }

1 个答案:

答案 0 :(得分:2)

LIKE支持的唯一通配符%形成多个字符,_表示单个字符。

Quote from the manual

  

如果pattern不包含百分号或下划线,则该模式仅表示字符串本身;在这种情况下,LIKE的行为类似于equals运算符。模式中的下划线(_)代表(匹配)任何单个字符;百分号(%)匹配零个或多个字符的任何序列。

所以,LIKE '%[a-zA-Z]%'只是意味着:任何包含字符串[a-zA-z]的值

例如,以下查询:

select 'foobar' LIKE '%[a-zA-Z]%' as one,
       'this [a-zA-Z] matches' LIKE '%[a-zA-Z]%' as two;

返回

one   | two 
------+-----
false | true

如果您想与regular expression匹配,则需要使用~SIMILAR TO

CREATE OR REPLACE FUNCTION fnc_control_value()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $function$
BEGIN
   IF NEW.name ~ '^[a-zA-Z]*$' and NEW.surname ~ '^[a-zA-Z]*$' THEN 
     return new;
   ELSE
     RAISE WARNING 'INVALID CHARACTERS IN ENTERING VALUE';
     Return null;
   END IF;
END;
$function$;

但是,然后默默地(!)忽略插入或更新,我会抛出一个异常,它将显示为执行插入的会话的错误:

CREATE OR REPLACE FUNCTION fnc_control_value()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $function$
BEGIN
   IF NEW.name ~ '^[a-zA-Z]*$' and NEW.surname ~ '^[a-zA-Z]*$' THEN 
     return new;
   ELSE
     RAISE 'Only characters from A to Z allowed!';
   END IF;
END;
$function$;

请注意,您必须在BEFORE触发器中使用它,否则这不起作用。

create trigger ugly_check_constraint_trigger()
    BEFORE insert or update on the_table
    for each row 
    execute procedure fnc_control_value();

但是再次:使用检查约束更好。