华为云用户手册

  • 命令示例 初始化配置 health config add -d xxx -u xxx -w xxx -i xxx -r cn-north-4 -o obs.cn-north-4.myhuaweicloud.com -a xxx -s xxx -D https://xxx -q xxx –f -m xxx -e xxx -t xxx # 执行成功返回结果如下 add ak successfully! add sk successfully! add region successfully! add platform-id successfully! add user-name successfully! add password successfully! add domain-name successfully! add obs-endpoint successfully! add obs_install_path successfully! add obs_down_load_url successfully! add iam-endpoint successfully! add health-endpoint successfully! add swr-endpoint successfully! 初始化配置 health config add -d xxx -u xxx -w xxx -i xxx -r cn-north-4 -a xxx -s xxx -D https://xxx -q xxx # 执行成功返回结果如下 add ak successfully! add sk successfully! add region successfully! add platform-id successfully! add user-name successfully! add password successfully! add domain-name successfully! add obs_install_path successfully! add obs_down_load_url successfully! 图1 命令示例 初始化配置并设置日志存储路径 health config add -d xxx -u xxx -w xxx -i xxx -r cn-north-4 -o obs.cn-north-4.myhuaweicloud.com -a xxx -s xxx -D https://xxx -q xxx --log-path D:\log\eihealth.log –f -m xxx -e xxx -t xxx # 执行成功返回结果如下 add ak successfully! add sk successfully! add region successfully! add platform-id successfully! add user-name successfully! add password successfully! add domain-name successfully! add obs-endpoint successfully! add obs_install_path successfully! add obs_down_load_url successfully! add log-path successfully! add iam-endpoint successfully! add health-endpoint successfully! add swr-endpoint successfully! 初始化配置并设置日志存储路径 health config add -d xxx -u xxx -w xxx -i xxx -r cn-north-4 -a xxx -s xxx -D https://xxx -q xxx --log-path D:\log\eihealth.log # 执行成功返回结果如下 add ak successfully! add sk successfully! add region successfully! add platform-id successfully! add user-name successfully! add password successfully! add domain-name successfully! add obs_install_path successfully! add obs_down_load_url successfully! add log-path successfully! 清空配置请执行health config clear命令 在Notebook中使用命令行工具 在 EIHealth 开发环境Notebook中使用命令行工具时,请依据以下步骤配置代理。 打开Notebook,并选择Terminal,打开Notebook的命令行界面。 执行以下命令下载命令行工具,并获取配置Notebook代理所需的域名和端口信息。 示例中下载的版本为Linux ARM 64位。 wget https://eihealth-cli.obs.cn-north-4.myhuaweicloud.com/current/health-linux-aarch64.tar 初始化配置时,添加--http-proxy命令,用于配置代理。 health config add --http-proxy http://域名:端口号 执行以上命令,会在系统所在的用户目录下自动生成“.health”文件夹,文件夹中包含config.ini配置文件,用于存储任务执行所涉及到的配置,如密钥、区域、当前项目等信息。 生成的配置文件不建议直接修改,如需改动请使用命令行工具修改。 配置文件中保存有用户的AK、SK信息,为了避免密钥泄露,会对文件中的SK进行加密以保护密钥安全。 初始化配置时,如果命令同时填写了AK/SK和密码,默认AK/SK方式登录。 初始化配置命令会在history中暴露ak、sk,建议使用set +o history命令关闭history再执行。执行后可使用set -o history命令恢复。
  • 清理命令记录 为防止配置文件中的敏感信息泄露,建议使用health config clear命令定时清除本地配置文件。 对于执行的历史命令,可通过以下方法清除。 Linux:执行history -c命令清除历史记录,重新登录命令行工具后,记录可恢复。执行rm -f $HOME/.bash_history命令,可删除记录文件,清空历史。 macOS系统:执行ps -p $$命令检查shell类型。 类型为bash:操作与Linux系统相同。 类型为zsh:执行history -p命令清除历史记录,重新登录命令行工具后,记录可恢复。执行rm -rf ~/.zsh_history命令,退出终端后再次执行history -p命令可删除记录文件,清空历史。 windows系统:对于当前执行的命令,可通过关闭cmd窗口实现历史命令的清理。
  • 命令结构 执行health config add命令进行初始化配置。 health config add [flags] 表1 参数说明 参数 简写 是否必选 说明 --domain-name -d 是 与管理员(购买平台的帐户)的帐号名一致。 --user-name -u 是 子用户的用户名。 管理员(购买平台的账户)登录时,user-name和domain-name一致。 --password -w 是 密码。 --ak -a 是 AK(Access Key ID):访问密钥ID。 --sk -s 是 SK(Secret Access Key):与访问密钥ID结合使用的密钥。 --region -r 是 服务区域名称。依据购买服务所在的区域进行选择,可选cn-north-4、cn-east-3、cn-south-1 --platform-id -i 是 平台ID,获取方法请参见获取认证信息。 --iam-endpoint -m 否 IAM 终端节点名称,请在地区与终端节点中获取。 --health-endpoint -e 否 EIHealth终端节点名称,请在地区与终端节点中获取。 --swr-endpoint -t 否 SWR镜像仓库地址。 获取方式: 登录 容器镜像服务 管理控制台。 单击界面右侧“登录指令”,获取内网登录指令末尾的SWR镜像仓库地址。例如100.78.15.50:20202。 --log-path -l 否 日志路径,不填写时默认为命令行工具当前路径下healthcli.log文件。 路径设置格式: Windows系统为“路径\文件名”。 Linux系统格式为“路径/文件名”。 --http-proxy -p 否 HTTP代理配置,格式为“http://username:password@your-proxy:your-port”。 --obs-endpoint -o 否 OBS终端节点名称,请在地区与终端节点中获取。 --obs-install-path -q 否 设置obsutil安装路径,默认安装在当前运行目录。 设置时,该路径必须为obsutil运行文件名,如/home/path/obsutil、/home/path/obsutil-1.1.1 --obs_down_load_url -D 否 obsutil下载链接,obsutil将下载到obs-install-path上。 参数有改动时才会触发下载。 下载链接的内容可以是zip、tar.gz文件、二进制文件,如果是压缩文件,文件夹内的obsutil必须命名为obsutil(和obsutil官方链接保持一致)。 --force -f 否 强制操作。如果下载obsutil时,指定的obs-install-path上已经有同名文件,不带-f时会提示用户,带上-f会直接覆盖原文件。
  • 扩展 除上述场景会出现存在多个collation造成冲突,以下两种场景也会出现多个collation,报错不同但解决方法相同。 场景一 SELECT语句中比较表达式a=b存在多个collation造成冲突,执行报错could not determine which collation to use for string comparison。 1 2 3 SELECT a=b FROM t; ERROR: dn_6001_6002: could not determine which collation to use for string comparison HINT: Use the COLLATE clause to set the collation explicitly. 执行SELECT时,指定表达式a=b的排序规则为case_insensitive。 1 2 3 4 5 SELECT a=b COLLATE case_insensitive FROM t; ?column? ---------- f (1 row) 场景二 SELECT语句中表达式 instr(a,b)存在多个collation造成冲突,执行报错could not determine which collation to use for string searching。 1 2 3 SELECT instr(a,b) FROM t; ERROR: dn_6005_6006: could not determine which collation to use for string searching HINT: Use the COLLATE clause to set the collation explicitly. 执行SELECT时,指定字段a的排序规则为case_insensitive或者指定字段b的排序规则为C来保证字段排序规则的统一。 1 2 3 4 5 6 7 8 9 10 11 SELECT instr(a collate case_insensitive,b) FROM t; instr ------- 0 (1 row) SELECT instr(a,b collate "C") FROM t; instr ------- 0 (1 row)
  • 问题现象 执行SELECT查询时报错could not determine which collation to use for string hashing. 1 2 3 4 5 6 CREATE TABLE t(a text collate "C", b text collate case_insensitive); INSERT INTO t VALUES('Hello','world'); ——计算ifnull(a,b)的值的哈希值 SELECT hashtext(ifnull(a,b)) FROM t; ERROR: dn_6005_6006: could not determine which collation to use for string hashing. HINT: Use the COLLATE clause to set the collation explicitly. hashtext函数用于计算适当数据类型的值的哈希值。此处仅用作示例说明出现collate冲突时应该如何解决。
  • 处理方法 当字符串表达式中collation有多个时,可手动指定COLLATE collation_name。 执行SELECT时,指定表达式ifnull(a,b)的排序规则为C或者case_insensitive。 1 2 3 4 5 6 7 8 9 10 11 SELECT hashtext(ifnull(a,b) collate "C") FROM t; hashtext ----------- 820977155 (1 row) SELECT hashtext(ifnull(a,b) collate case_insensitive) FROM t; hashtext ----------- 238052143 (1 row)
  • 问题现象 创建分区表索引HR_staffS_p1_index1,不指定索引分区的名字。 1 CREATE INDEX HR_staffS_p1_index1 ON HR.staffS_p1 (staff_ID) LOCAL; 创建分区索引HR_staffS_p1_index2,并指定索引分区的名字。 1 2 3 4 5 6 CREATE INDEX HR_staffS_p1_index2 ON HR.staffS_p1 (staff_ID) LOCAL ( PARTITION staff_ID1_index, PARTITION staff_ID2_index TABLESPACE example3, PARTITION staff_ID3_index TABLESPACE example4 ) TABLESPACE example; 修改索引分区staff_ID1_index的表空间为example1: 调用“ALTER INDEX HR_staffS_p1_index2 MOVE PARTITION staff_ID2_index TABLESPACE example1;”提示索引不存在。
  • 原因分析 重新创建索引CREATE INDEX HR_staffS_p1_index2 MOVE PARTITION staff_ID2_index TABLESPACE example1,提示索引已存在,然后执行以下SQL命令或者gsql客户端元命令\d+ HR.staffS_p1 查询索引时发现索引已存在。 1 SELECT * FROM DBA_INDEXES WHERE index_name = HR.staffS_p1 ; 推测是当前模式是public模式,而不是hr模式,导致检索不到该索引。 使用“ALTER INDEX hr.HR_staffS_p1_index2 MOVE PARTITION staff_ID2_index TABLESPACE example1;”验证推测,发现调用成功。 接着调用ALTER SESSION SET CURRENT_SCHEMA TO hr;再次调用“ALTER INDEX HR_staffS_p1_index2 MOVE PARTITION staff_ID2_index TABLESPACE example1;”发现设置成功。
  • 处理方法 以上述问题现象中的“字符串类型varchar直接转换为整数型integer”报错为例,可以先将字段类型修改为decimal(任意精度型)再进行转换来处理。 具体的操作步骤如下: 假设报错表名为product,表定义如下: 1 SELECT * FROM PG_GET_TABLEDEF('product'); 将查询结果转换为整数型。 1 SELECT CAST(price AS integer) FROM product; 出现如下报错: 修改表字段的数据类型为decimal。 1 ALTER TABLE product ALTER COLUMN price TYPE decimal(10,1); 成功转换字段为整数型。 1 SELECT CAST(price AS integer) FROM product;
  • 原因分析 以UTF-8编码为例,一个中文占3~4个字节,即8个中文占24~32字节,超出VARCHAR(18)的最大18字节限制。 当表中某一字段包含有中文字符时,可使用char_length或length函数来查询字段字符长度,使用lengthb函数来查询字段字节长度。 1 2 3 4 5 SELECT length('数据库database'); length -------- 11 (1 row) 1 2 3 4 5 SELECT lengthb('数据库database'); length -------- 17 (1 row)
  • 处理方法 方法一:检查数据冲突,修改插入数据。例如,修改示例重复字段UA502为UA509。 1 2 INSERT INTO films VALUES ('UA509', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes'); INSERT 0 1 方法二:删除表films主键约束。 1 2 3 4 ALTER TABLE films DROP CONSTRAINT films_pkey; ALTER TABLE INSERT INTO films VALUES ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes'); INSERT 0 1
  • 问题现象 向表中插入数据报错:duplicate key value violates unique constraint "%s". 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CREATE TABLE films ( code char(5) PRIMARY KEY, title varchar(40) NOT NULL, did integer NOT NULL, date_prod date, kind varchar(10), len interval hour to minute ); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "films_pkey" for table "films" CREATE TABLE INSERT INTO films VALUES ('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes'); INSERT INTO films VALUES ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes'); ERROR: dn_6003_6004: duplicate key value violates unique constraint "films_pkey" DETAIL: Key (code)=(UA502) already exists.
  • 问题现象 创建范围分区表后增加新的分区,使用ALTER TABLE ADD PARTITION语句报错upper boundary of adding partition MUST overtop last existing partition. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ——创建范围分区表studentinfo CREATE TABLE studentinfo (stuno smallint, sname varchar(20), score varchar(20), examate timestamp) PARTITION BY RANGE (examate) ( PARTITION p1 VALUES LESS THAN ('2022-10-10 00:00:00+08'), PARTITION p2 VALUES LESS THAN ('2022-10-11 00:00:00+08'), PARTITION p3 VALUES LESS THAN ('2022-10-12 00:00:00+08'), PARTITION p4 VALUES LESS THAN (maxvalue) ); ——添加边界值为2022-10-9 00:00:00+08的分区p0 ALTER TABLE studentinfo ADD PARTITION p0 values less than ('2022-10-9 00:00:00+08'); ERROR: the boundary of partition "p0" is less than previous partition's boundary ——添加边界值为2022-10-13 00:00:00+08的分区p5 ALTER TABLE studentinfo ADD PARTITION p5 values less than ('2022-10-13 00:00:00+08'); ERROR: the boundary of partition "p5" is equal to previous partition's boundary
  • 原因分析 增加分区时需同时满足以下条件: 新增分区名不能与已有分区名相同。 新增分区的边界值必须大于最后一个分区的上边界。 新增分区的边界值要和分区表的分区键的类型一致。 已有分区p1的边界为(-∞,20221010),而新增分区p0的上边界为20221009,落在分区p1内;已有分区p4的边界为[20221012,+∞),而新增分区p5的上界为20221013,落在分区p4内。新增分区p0、p5不满足使用ADD PARTITION增加分区的条件,因此执行新增分区语句报错。
  • 处理方法 使用ALTER TABLE SPLIT PARTITION分割已有分区,也能达到新增分区的目的。同样, SPLIT PARTITION的新分区名称也不能与已有分区相同。 使用split子句分割p4分区[20221012,+∞)为p4a分区范围为[20221012,20221013)和p4b分区范围为[20221013,+∞)。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ——SPLIT PARTITION分割前的分区 SELECT relname, boundaries FROM pg_partition p where p.parentid='studentinfo'::regclass ORDER BY 1; relname | boundaries -------------+------------------------- p1 | {"2022-10-10 00:00:00"} p2 | {"2022-10-11 00:00:00"} p3 | {"2022-10-12 00:00:00"} p4 | {NULL} studentinfo | (5 rows) ALTER TABLE studentinfo SPLIT PARTITION p1 AT('2022-10-09 00:00:00+08') INTO (PARTITION P1a,PARTITION P1b); ALTER TABLE studentinfo SPLIT PARTITION p4 AT('2022-10-13 00:00:00+08') INTO (PARTITION P4a,PARTITION P4b); ——执行SPLIT PARTITION分割后的分区 SELECT relname, boundaries FROM pg_partition p where p.parentid='studentinfo'::regclass ORDER BY 1; relname | boundaries -------------+------------------------- p1a | {"2022-10-09 00:00:00"} p1b | {"2022-10-10 00:00:00"} p2 | {"2022-10-11 00:00:00"} p3 | {"2022-10-12 00:00:00"} p4a | {"2022-10-13 00:00:00"} p4b | {NULL} studentinfo | (7 rows) 如果对分区名称有要求,可以在分割后再使用rename partition统一分区名。 ALTER TABLE studentinfo RENAME PARTITION p1a to p0;
  • 问题现象 新建一个数据库表,某个表字段使用character类型,在Java中读取character类型的字段时返回类型为什么是byte? 例如,创建如下所示的表: 1 2 3 4 CREATE TABLE IF NOT EXISTS table01( msg_id character(36), msg character varying(50) ); 在Java中,读取character类型的字段代码如下: 1 ColumnMetaInfo(msg_id,1,Byte,true,false,1,true);
  • 处理方法 应根据数据实际情况规划分区,以保证插入的数据都在规划好的分区中。 如果已规划的分区无法满足实际应用条件,可以增加分区后再插入数据。针对上述案例,可以增加分区c2,分区范围介于5000和MAXVALUE之间: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ALTER TABLE startend_pt ADD PARTITION P6 VALUES LESS THAN (MAXVALUE); SELECT partition_name,high_value FROM dba_tab_partitions WHERE table_name='startend_pt'; partition_name | high_value ----------------+------------ p1_0 | 1 p1_1 | 201 p1_2 | 401 p1_3 | 601 p1_4 | 801 p1_5 | 1000 p2 | 2000 p3 | 2500 p4 | 3000 p5_1 | 4000 p5_2 | 5000 p6 | MAXVALUE (12 rows) INSERT INTO startend_pt VALUES (1,5001); SELECT * FROM startend_pt; c1 | c2 ----+------ 1 | 5001 (1 row)
  • 问题现象 给范围分区表插入数据报错:inserted partition key does not map to any table partition。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 CREATE TABLE startend_pt (c1 INT, c2 INT) DISTRIBUTE BY HASH (c1) PARTITION BY RANGE (c2) ( PARTITION p1 START(1) END(1000) EVERY(200) , PARTITION p2 END(2000), PARTITION p3 START(2000) END(2500) , PARTITION p4 START(2500), PARTITION p5 START(3000) END(5000) EVERY(1000) ); SELECT partition_name,high_value FROM dba_tab_partitions WHERE table_name='startend_pt'; partition_name | high_value ----------------+------------ p1_0 | 1 p1_1 | 201 p1_2 | 401 p1_3 | 601 p1_4 | 801 p1_5 | 1000 p2 | 2000 p3 | 2500 p4 | 3000 p5_1 | 4000 p5_2 | 5000 (11 rows) INSERT INTO startend_pt VALUES (1,5001); ERROR: dn_6003_6004: inserted partition key does not map to any table partition
  • 解决办法 为防止出现分区间隙,需要将ADD PARTITION的START值前移。 示例:对于分区表partitiontest 1 2 3 4 5 6 7 8 9 10 CREATE TABLE partitiontest ( c_int integer, c_time TIMESTAMP WITHOUT TIME ZONE ) PARTITION BY range (c_int) ( partition p1 start(100)end(108), partition p2 start(108)end(120) ); 使用如下两种语句会发生报错: 1 2 ALTER TABLE partitiontest ADD PARTITION p3 start(120)end(130), DROP PARTITION p2; ERROR: start value of partition "p3" NOT EQUAL up-boundary of last partition. 1 2 ALTER TABLE partitiontest DROP PARTITION p2,ADD PARTITION p3 start(120)end(130) ; ERROR: start value of partition "p3" NOT EQUAL up-boundary of last partition. 可以修改语句为: 1 ALTER TABLE partitiontest ADD PARTITION p3 start(108)end(130), DROP PARTITION p2; 1 ALTER TABLE partitiontest DROP PARTITION p2,ADD PARTITION p3 start(108)end(130) ;
  • 处理方法 String_agg中增加order by,语句修改为如下格式保证ename字段是按照相同的顺序来拼接的,从而满足查询结果是稳定的。 1 2 3 4 select count(*) from (select deptno, string_agg(ename, ',' order by ename desc) from employee group by deptno) t1 , (select deptno, string_agg(ename, ',' order by ename desc) from employee group by deptno) t2 where t1.string_agg = t2.string_agg;
  • 原因分析 客户的SQL语句中使用了string_agg函数,语句逻辑如下: 执行如下SQL语句: 1 2 3 4 select count(*) from (select deptno, string_agg(ename, ',') from employee group by deptno) t1 , (select deptno, string_agg(ename, ',') from employee group by deptno) t2 where t1.string_agg = t2.string_agg;
  • 处理方法 8.0以下版本集群清理系统表需要先执行DELETE FROM,再执行VACUUM FULL。 此处仅以gs_wlm_session_info系统表为例: 1 2 DELETE FROM pg_catalog.gs_wlm_session_info; VACUUM FULL pg_catalog.gs_wlm_session_info; 8.0及以上(8.0.x/8.1.1/8.1.3)版本集群可执行以下命令清理系统表: 1 TRUNCATE TABLE dbms_om.gs_wlm_session_info; 此系统表的schema是dbms_om。
  • 处理方法 通过Function的exception方式屏蔽该报错,将大小统一到一个值,对于不存在的表,可以用大小为-1来表示,函数如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 CREATE OR REPLACE FUNCTION public.pg_t_size(tab_oid OID,OUT retrun_code text) RETURNS text LANGUAGE plpgsql AS $$ DECLARE v_sql text; ts text; BEGIN V_SQL:='select pg_size_pretty(pg_table_size('||tab_oid||'))'; EXECUTE IMMEDIATE V_SQL into ts; IF ts IS NULL THEN RETRUN_CODE:=-1; ELSE return ts; END IF; EXCEPTION WHEN OTHERS THEN RETRUN_CODE:=-1; END$$; 执行如下命令查询结果: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 call public.pg_t_size('1',''); retrun_code ------------- -1 (1 row) select oid from pg_class limit 2; oid ------ 2662 2659 (2 rows) call public.pg_t_size('2662',''); retrun_code ------------- 120 KB (1 row)
  • 处理方法 故障构造场景 使用客户端连接DWS数据库。 执行以下SQL语句。 1 2 3 4 5 6 7 8 9 10 11 12 CREATE TABLE t1(a int, b timestamp); CREATE TABLE CREATE TABLE t2(a int, b text); CREATE TABLE INSERT INTO t1 select 1, current_date; INSERT 0 1 INSERT INTO t2 select 1, current_date; INSERT 0 1 SELECT * FROM t1 UNION SELECT * FROM t2; ERROR: UNION types timestamp without time zone and text cannot be matched LINE 1: SELECT * FROM t1 UNION SELECT * FROM t2; ^ 解决办法 示例中,t1表和t2表在b列上类型不同,导致在UNION操作时出现类型不匹配的报错,应保证UNION各分支相同位置的输出列类型匹配。 t2表b列是text类型,插入的数据是current_date,在插入时发生了隐式类型转换,所以插入不报错;但是在查询时,不会自动进行隐式转换,因此会报错。 解决以上问题,需保证UNION各分支的输出列类型匹配,不满足要求时可以对输出列强制类型转化。 1 2 3 4 5 6 SELECT a,b::text FROM t1 UNION SELECT a,b FROM t2; a | b ---+--------------------- 1 | 2023-02-16 1 | 2023-02-16 00:00:00 (2 rows)
  • 问题现象 向表中插入数据报错:null value in column '%s' violates not-null constraint,此处s%指报错的列(字段)名。 1 2 3 4 CREATE TABLE t1(a int, b int not null); INSERT INTO t1 VALUES (1); ERROR: dn_6001_6002: null value in column "b" violates not-null constraint
  • 解决方案 针对上述案例,有两种解决方案: 方案一:使用ALTER TABLE删除字段b的非空(not null)约束 1 2 3 4 5 ALTER TABLE t1 ALTER COLUMN b DROP NOT NULL; ALTER TABLE INSERT INTO t1 VALUES (1); INSERT 0 1 方案二:保持字段b的非空(not null)约束,字段b不再插入空值 在实际业务中,可根据实际情况选择解决方案。
  • 解决方案 方案一:设置参数behavior_compat_options为merge_update_multi 当目标表匹配到多行满足条件时,该方案不会报错,而是会随机匹配一行数据,有数据遗漏风险。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 SET behavior_compat_options=merge_update_multi; MERGE INTO products p USING newproducts np ON (p.product_id = np.product_id) WHEN MATCHED THEN UPDATE SET p.product_name = np.product_name, p.category = np.category WHERE np.product_id = 1502; MERGE 1 SELECT * FROM products ; product_id | product_name | category ------------+----------------+----------- 1501 | vivitar 35mm | electrncs 1502 | olympus camera | electrncs 1600 | play gym | toys (3 rows) 方案二:修改MERGE INTO匹配条件 尽可能选择筛选结果唯一的表达式为匹配条件。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 MERGE INTO products p USING newproducts np ON (p.product_id = np.product_id) WHEN MATCHED THEN UPDATE SET p.product_name = np.product_name, p.category = np.category WHERE np.product_id != 1502; MERGE 1 SELECT * FROM products; product_id | product_name | category ------------+----------------+----------- 1501 | vivitar 35mm | electrncs 1502 | olympus camera | electrncs 1600 | lamaze | toys (3 rows)
  • 问题现象 执行MERGE INTO将源表内容根据匹配条件对目标表做更新报错unable to get a stable set of rows in the source table。 现有目标表products和源表newproducts,以源表newproducts中product_id为1502为匹配条件,对目标表进行更新报错: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 CREATE TABLE products (product_id INTEGER,product_name VARCHAR2(60),category VARCHAR2(60)); INSERT INTO products VALUES (1501, 'vivitar 35mm', 'electrncs'),(1502, 'olympus is50', 'electrncs'),(1600, 'play gym', 'toys'); CREATE TABLE newproducts (product_id INTEGER,product_name VARCHAR2(60),category VARCHAR2(60)); INSERT INTO newproducts VALUES (1502, 'olympus camera', 'electrncs'),(1600, 'lamaze', 'toys'),(1502, 'skateboard', 'toy'); MERGE INTO products p USING newproducts np ON (p.product_id = np.product_id) WHEN MATCHED THEN UPDATE SET p.product_name = np.product_name, p.category = np.category WHERE np.product_id = 1502; ERROR: dn_6003_6004: unable to get a stable set of rows in the source tables
  • 原因分析 源表newproducts中product_id为1502的数据有两条,且参数behavior_compat_options缺省,因此MERGE INTO时匹配到多条数据报错。 MERGE INTO的作用是将源表内容根据匹配条件对目标表做更新或插入,当目标表匹配到多行满足条件时, GaussDB (DWS)有以下两种行为: 业务报错:unable to get a stable set of rows in the source table 随机匹配一行数据,可能会导致实际与预期不符 这两种行为由参数behavior_compat_options控制,当参数behavior_compat_options缺省的情况下,匹配到多行会报错,如果behavior_compat_options被设置为merge_update_multi,则不会报错,而是会随机匹配一行数据。 因此,当出现merge into的结果与预期不符的情况时,需查看该参数是否被设置,同时排查是否匹配了多行数据,并根据实际情况修改业务逻辑。
  • 问题现象 某表table01中存在以大小写字母组合的名称为“ColumnA”的字段,使用SELECT语句查询该字段时,提示字段不存在,报错:column "columna" does not exist. 1 2 3 4 5 select ColumnA from table01 limit 100; ERROR: column "columna" does not exist LINE 1: select columna from TABLE_01; ^ CONTEXT: referenced column: columna
共100000条