将部分Error降级为Warning的Hint

功能描述

指定执行INSERT、UPDATE语句时可将部分Error降级为Warning,且不影响语句执行完成的hint。

该hint不支持列存表,无法在列存表中生效。

将部分Error降级为Warning的Hint - 图1 注意: 与其他hint不同,此hint仅影响执行器遇到部分Error时的处理方式,不会对执行计划有任何影响。

使用该hint时,Error会被降级的场景有:

  • 违反非空约束时

    若执行的SQL语句违反了表的非空约束,使用此hint可将Error降级为Warning,并根据GUC参数sql_ignore_strategy的值采用以下策略的一种继续执行:

    • sql_ignore_startegy为ignore_null时,忽略违反非空约束的行的INSERT/UPDATE操作,并继续执行剩余数据操作。

    • sql_ignore_startegy为overwrite_null时,将违反约束的null值覆写为目标类型的默认值,并继续执行剩余数据操作。

      将部分Error降级为Warning的Hint - 图2 说明:

    GUC参数sql_ignore_strategy相关信息请参考sql_ignore_strategy

  • 违反唯一约束时

    若执行的SQL语句违反了表的唯一约束,使用此hint可将Error降级为Warning,忽略违反约束的行的INSERT/UPDATE操作,并继续执行剩余数据操作。

  • 分区表无法匹配到合法分区时

    在对分区表进行INSERT/UPDATE操作时,若某行数据无法匹配到表格的合法分区,使用此hint可将Error降级为Warning,忽略该行操作,并继续执行剩余数据操作。

  • 更新/插入值向目标列类型转换失败时

    执行INSERT/UPDATE语句时,若发现新值与目标列类型不匹配,使用此hint可将Error降级为Warning,并根据新值与目标列的具体类型采取以下策略的一种继续执行:

    • 当新值类型与列类型同为数值类型时:

      若新值在列类型的范围内,则直接进行插入/更新;若新值在列类型范围外,则以列类型的最大/最小值替代。

    • 当新值类型与列类型同为字符串类型时:

      若新值长度在列类型限定范围内,则以直接进行插入/更新;若新值长度在列类型的限定范围外,则保留列类型长度限制的前n个字符。

    • 若遇到新值类型与列类型不可转换时:

      插入/更新列类型的默认值。

语法格式

  1. ignore_error

示例

为使用ignore_error hint,需要创建B兼容模式的数据库,名称为db_ignore。

  1. create database db_ignore dbcompatibility 'B';
  2. \c db_ignore
  • 忽略非空约束
  1. db_ignore=# create table t_not_null(num int not null);
  2. CREATE TABLE
  3. -- 采用忽略策略
  4. db_ignore=# set sql_ignore_strategy = 'ignore_null';
  5. SET
  6. db_ignore=# insert /*+ ignore_error */ into t_not_null values(null), (1);
  7. WARNING: null value in column "num" violates not-null constraint
  8. DETAIL: Failing row contains (null).
  9. INSERT 0 1
  10. db_ignore=# select * from t_not_null ;
  11. num
  12. -----
  13. 1
  14. (1 row)
  15. db_ignore=# update /*+ ignore_error */ t_not_null set num = null where num = 1;
  16. WARNING: null value in column "num" violates not-null constraint
  17. DETAIL: Failing row contains (null).
  18. UPDATE 0
  19. db_ignore=# select * from t_not_null ;
  20. num
  21. -----
  22. 1
  23. (1 row)
  24. -- 采用覆写策略
  25. db_ignore=# delete from t_not_null;
  26. db_ignore=# set sql_ignore_strategy = 'overwrite_null';
  27. SET
  28. db_ignore=# insert /*+ ignore_error */ into t_not_null values(null), (1);
  29. WARNING: null value in column "num" violates not-null constraint
  30. DETAIL: Failing row contains (null).
  31. INSERT 0 2
  32. db_ignore=# select * from t_not_null ;
  33. num
  34. -----
  35. 0
  36. 1
  37. (2 rows)
  38. db_ignore=# update /*+ ignore_error */ t_not_null set num = null where num = 1;
  39. WARNING: null value in column "num" violates not-null constraint
  40. DETAIL: Failing row contains (null).
  41. UPDATE 1
  42. db_ignore=# select * from t_not_null ;
  43. num
  44. -----
  45. 0
  46. 0
  47. (2 rows)
  • 忽略唯一约束
  1. db_ignore=# create table t_unique(num int unique);
  2. NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_unique_num_key" for table "t_unique"
  3. CREATE TABLE
  4. db_ignore=# insert into t_unique values(1);
  5. INSERT 0 1
  6. db_ignore=# insert /*+ ignore_error */ into t_unique values(1),(2);
  7. WARNING: duplicate key value violates unique constraint in table "t_unique"
  8. INSERT 0 1
  9. db_ignore=# select * from t_unique;
  10. num
  11. -----
  12. 1
  13. 2
  14. (2 rows)
  15. db_ignore=# update /*+ ignore_error */ t_unique set num = 1 where num = 2;
  16. WARNING: duplicate key value violates unique constraint in table "t_unique"
  17. UPDATE 0
  18. db_ignore=# select * from t_unique ;
  19. num
  20. -----
  21. 1
  22. 2
  23. (2 rows)
  • 忽略分区表无法匹配到合法分区
  1. db_ignore=# CREATE TABLE t_ignore
  2. db_ignore-# (
  3. db_ignore(# col1 integer NOT NULL,
  4. db_ignore(# col2 character varying(60)
  5. db_ignore(# ) WITH(segment = on) PARTITION BY RANGE (col1)
  6. db_ignore-# (
  7. db_ignore(# PARTITION P1 VALUES LESS THAN(5000),
  8. db_ignore(# PARTITION P2 VALUES LESS THAN(10000),
  9. db_ignore(# PARTITION P3 VALUES LESS THAN(15000)
  10. db_ignore(# );
  11. CREATE TABLE
  12. db_ignore=# insert /*+ ignore_error */ into t_ignore values(20000);
  13. WARNING: inserted partition key does not map to any table partition
  14. INSERT 0 0
  15. db_ignore=# select * from t_ignore ;
  16. col1 | col2
  17. ------+------
  18. (0 rows)
  19. db_ignore=# insert into t_ignore values(3000);
  20. INSERT 0 1
  21. db_ignore=# select * from t_ignore ;
  22. col1 | col2
  23. ------+------
  24. 3000 |
  25. (1 row)
  26. db_ignore=# update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000;
  27. WARNING: fail to update partitioned table "t_ignore".new tuple does not map to any table partition.
  28. UPDATE 0
  29. db_ignore=# select * from t_ignore ;
  30. col1 | col2
  31. ------+------
  32. 3000 |
  33. (1 row)
  • 更新/插入值向目标列类型转换失败
  1. -- 当新值类型与列类型同为数值类型
  2. db_ignore=# create table t_tinyint(num tinyint);
  3. CREATE TABLE
  4. db_ignore=# insert /*+ ignore_error */ into t_tinyint values(10000);
  5. WARNING: tinyint out of range
  6. CONTEXT: referenced column: num
  7. INSERT 0 1
  8. db_ignore=# select * from t_tinyint;
  9. num
  10. -----
  11. 255
  12. (1 row)
  13. -- 当新值类型与列类型同为字符类型时
  14. db_ignore=# create table t_varchar5(content varchar(5));
  15. CREATE TABLE
  16. db_ignore=# insert /*+ ignore_error */ into t_varchar5 values('abcdefghi');
  17. WARNING: value too long for type character varying(5)
  18. CONTEXT: referenced column: content
  19. INSERT 0 1
  20. db_ignore=# select * from t_varchar5 ;
  21. content
  22. ---------
  23. abcde
  24. (1 row)