华为云用户手册

  • 客户端差异 GaussDB (DWS) gsql相较于PostgreSQL psql做了如下安全加固变更: 取消通过元命令\password设置用户密码。 新增元命令\i+、 \ir+、\include_relative+和输入输出参数-k,以支持给导入导出的文件加密。 取消打印命令行历史到文件的元命令\s。 涉及敏感操作SQL历史不再记录,如含有密码操作。即用户通过翻页/上下键查阅SQL历史将不能查到对应的记录。 支持连接后在屏幕上给出用户密码过期提示以及版本信息。 gsql在psql基础上还增加了如下功能: 新增输出格式参数-r。支持用户输入命令时的tab补齐和方向键调整焦点。 新增并行操作元命令\parallel,以提升执行性能。 新增\set RETRY支持语句出错重试。 新增PLSQL默认结束符功能,将“/”作为PLSQL语句(create or replace function/procedure)的默认结束符,增加便利性。 libpq:
  • 什么是SQL SQL是用于访问和处理数据库的标准计算机语言。 SQL提供了各种任务的语句,包括: 查询数据。 在表中插入、更新和删除行。 创建、替换、更改和删除对象。 控制对数据库及其对象的访问。 保证数据库的一致性和完整性。 SQL语言由用于处理数据库和数据库对象的命令和函数组成。该语言还会强制实施有关数据类型、表达式和文本使用的规则。因此在SQL参考章节,除了SQL语法参考外,还会看到有关数据类型、表达式、函数和操作符等信息。
  • SQL语法文本格式约定 为了方便对语法使用的理解,在文档中对SQL语法文本按如下格式进行表述。 格式 意义 大写 语法关键字(语句中保持不变、必须与语法格式一致的部分)采用大写表示。 小写 参数(语句中必须由实际值进行替代的部分)采用小写表示。 [ ] 可选语法项。表示用“[ ]”括起来的部分是可选的。 { } 必选语法项。 ... 表示前面的元素可重复出现。 [ x | y | ... ] 表示从两个或多个选项中选取一个或者不选。 { x | y | ... } 表示从两个或多个选项中选取一个。 [x | y | ... ] [ ... ] 表示可选多个参数或者不选,如果选择多个参数,则参数之间用空格分隔。 [ x | y | ... ] [ ,... ] 表示可选多个参数或者不选,如果选择多个参数,则参数之间用逗号分隔。 { x | y | ... } [ ... ] 表示可选多个参数,至少选一个,如果选择多个参数,则参数之间以空格分隔。 { x | y | ... } [ ,... ] 表示可选多个参数,至少选一个,如果选择多个参数,则参数之间用逗号分隔。
  • SQL发展简史 SQL发展简史如下: 1986年,ANSI X3.135-1986,ISO/IEC 9075:1986,SQL-86 1989年,ANSI X3.135-1989,ISO/IEC 9075:1989,SQL-89 1992年,ANSI X3.135-1992,ISO/IEC 9075:1992,SQL-92(SQL2) 1999年,ISO/IEC 9075:1999,SQL:1999(SQL3) 2003年,ISO/IEC 9075:2003,SQL:2003(SQL4) 2011年,ISO/IEC 9075:200N,SQL:2011(SQL5)
  • 构造复合值 要把复合值写作文字常量,可以将字段值括在圆括号中,并用逗号分隔。可以在任何字段值加上双引号,如果字段值包含逗号或括号则必须这样做。复合常量的一般格式如下: 1 '( val1 , val2 , ... )' 上文中的'("fuzzy dice",42,1.99)'便属于inventory_item类型的一个合法值。 要让一个字段为NULL,在列表中对应位置上空出即可。如果需要一个字段为空字符串,使用引号即可。例如下列示例,第一个字段是非NULL空字符串,第三个是NULL: 1 '("",42,)' ROW表达式也能被用来构建组合值。例如: 1 2 ROW('fuzzy dice', 42, 1.99) ROW('', 42, NULL)
  • 复合类型的声明 GaussDB(DWS)支持用户使用CREATE TYPE定义复合类型: 1 2 3 4 5 6 7 8 9 10 CREATE TYPE complex AS ( r double precision, i double precision ); CREATE TYPE inventory_item AS ( name text, supplier_id integer, price numeric ); 定义复合类型之后,可用来创建表或函数: 1 2 3 4 5 6 CREATE TABLE on_hand ( item inventory_item, count integer ); INSERT INTO on_hand VALUES (ROW('fuzzy dice', 42, 1.99), 1000); 1 2 3 4 CREATE FUNCTION price_extension(inventory_item, integer) RETURNS numeric AS 'SELECT $1.price * $2' LANGUAGE SQL; SELECT price_extension(item, 10) FROM on_hand;
  • 范围的输入/输出 范围值的输入必须遵循下列模式之一: (lower-bound,upper-bound) (lower-bound,upper-bound] [lower-bound,upper-bound) [lower-bound,upper-bound] empty 圆括号或方括号指示上下界是否为排除的或者包含的。最后一个模式是empty,它表示一个空范围(一个不包含点的范围)。 lower-bound可以作为子类型的合法输入的一个字符串,或者是空,表示没有下界。同样,upper-bound可以是作为子类型的合法输入的一个字符串,或者是空,表示没有上界。 每个界限值可以使用双引号引用。如果界限值包含圆括号、方括号、逗号、双引号或反斜线时,则必须使用双引号引用,否则这些符号会被认作范围语法的一部分。要想把双引号或反斜线放在被引用的界限值中,需要在双引号或反斜线前面加一个反斜线(在双引号引用的界限值中的一对双引号表示一个双引号字符,这与SQL字符串中的单引号规则类似)。此外,可以避免引用并且使用反斜线转义来保护所有数据字符,否则它们会被当做返回语法的一部分。什么都不写则表示一个无限界限,因此,要表示空字符串的界限值,可以写成""。 范围值前后允许有空格,但是圆括号或方括号之间的任何空格会被当做上下界值的一部分(取决于元素类型,它可能是有意义的也可能是无意义的)。 示例 查询包括3,不包括7,并且包括3和7之间的所有点: SELECT '[3,7)'::int4range; int4range ----------- [3,7) (1 row) 查询既不包括3也不包括 7,但是包括之间的所有点: SELECT '(3,7)'::int4range; int4range ----------- [4,7) (1 row) 查询只包括单独一个点4: SELECT '[4,4]'::int4range; int4range ----------- [4,5) (1 row) 查询不包括点(并且将被标准化为 '空'): SELECT '[4,4)'::int4range; int4range ----------- empty (1 row)
  • 离散范围类型 离散范围是指其元素类型具有定义明确的“步长”的范围,如integer或date。在这些类型中,当两个元素之间没有有效值时,它们可以被说成是相邻。 离散范围类型的每个元素值都有一个明确的“下一个”或“上一个”值。这样就可以通过选择下一个或上一个元素值,在范围界限的包含和排除表达之间转换。例如,在整数范围类型中,[4,8]和(3,9)表示相同的值集合,但对于超过numeric的范围,情况并非如此。 离散范围类型应具有识别元素类型所需步长的规范函数。规范化函数负责将范围类型的等价值转换为具有相同的表示,特别是与包含或者排除界限一致。如果未指定规范化函数,则具有不同格式的范围将始终被视为不相等,即使它们实际上是表达相同的一组值。 内置范围类型int4range、int8range和daterange都使用规范形式,该形式包括下界并且排除上界,也就是[)。但是,用户定义的范围类型可以使用其他约定。
  • 包含和排除边界 每一个非空范围都有两个界限:下界和上界。这些值之间的所有点都被包括在范围内。包含界限意味着边界点本身也被包括在范围内,而排除边界意味着边界点不被包括在范围内。 在范围的文本形式中,包含下界用“[”表示,排除下界用“(”表示。同样,包含上界用“]”表示,排除上界用“)”表示。 函数lower_inc(anyrange)和lower_inc(anyrange)分别测试一个范围值的上下界。
  • 无限(无界)范围 范围的下界可以省略,这意味着所有小于上界的值都包括在范围中,例如(,3]。同样,范围的上界被省略,则所有大于下界的值都包括在范围中。如果下界和上界都被省略,则该元素类型的所有值都被认为在范围内。如果缺失的边界指定为包含则自动将包含转换为排除,例如[,]将转换为(,)。可以将这些缺失的值视为+/-无穷大,但它们是特殊的范围类型值,并且被视为超出任何范围元素类型的+/-无穷大值。 具有“无穷大”概念的元素类型可以将其作为显式边界值。例如,在时间戳范围,[today,infinity)不包括特殊的timestamp值infinity,尽管[today,infinity]包括它,就好比 [today,)和[today,]。 函数lower_inf(anyrange)和upper_inf(anyrange)分别测试一个范围的无限上下界。
  • 构造范围 每一种范围类型都有一个与其同名的构造器函数。使用构造器函数比写一个范围文字常数更方便,因为它避免了对界限值的额外引用。构造器函数接受两个或三个参数。两个参数的形式以标准的形式构造一个范围(包含下界,排除上界),而三个参数的形式按照第三个参数指定的界限形式构造一个范围。第三个参数必须是下列字符串之一: “()”、 “(]”、 “[)”或者 “[]”。 例如: 完整形式是:下界、上界以及指示界限包含性/排除性的文本参数: SELECT numrange(1.0, 14.0, '(]'); numrange ------------ (1.0,14.0] (1 row) 如果第三个参数被忽略,则假定为 '[)': SELECT numrange(1.0, 14.0); numrange ------------ [1.0,14.0) (1 row) 尽管这里指定了'(]',单返回结果时该值将被转换成标准形式,因为int8range是一种离散范围类型: SELECT int8range(1, 14, '(]'); int8range ----------- [2,15) (1 row) 界限使用NULL导致范围是无界的: SELECT numrange(NULL, 2.2); numrange ---------- (,2.2) (1 row)
  • 枚举类型的声明 枚举类型可以使用CREATE TYPE命令创建,例如: 1 CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy'); 枚举类型被创建后,可以在表和函数定义中使用: 1 2 3 4 5 6 7 8 CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy'); CREATE TABLE person (name text, current_mood mood); INSERT INTO person VALUES ('Moe', 'happy'); SELECT * FROM person WHERE current_mood = 'happy'; name | current_mood ------+-------------- Moe | happy (1 row)
  • 枚举类型的安全性 每一种枚举数据类型都是独立的并且不能和其他枚举类型相比较。 1 2 3 4 5 6 7 8 9 10 11 12 CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic'); CREATE TABLE holidays (num_weeks integer, happiness happiness); INSERT INTO holidays(num_weeks,happiness) VALUES (4, 'happy'); INSERT INTO holidays(num_weeks,happiness) VALUES (6, 'very happy'); INSERT INTO holidays(num_weeks,happiness) VALUES (8, 'ecstatic'); INSERT INTO holidays(num_weeks,happiness) VALUES (2, 'sad'); ERROR: invalid input value for enum happiness: "sad" SELECT person.name, holidays.num_weeks FROM person, holidays WHERE person.current_mood = holidays.happiness; ERROR: operator does not exist: mood = happiness 如果需要作比较,可以使用自定义的操作符或者在查询中加上显式类型: 1 2 3 4 5 6 SELECT person.name, holidays.num_weeks FROM person, holidays WHERE person.current_mood::text = holidays.happiness::text; name | num_weeks ------+----------- Moe | 4 (1 row)
  • 数组类型的定义 一个数组数据类型可以通过在数组元素的数据类型名称后面加上方括号([])来命名。 例如,创建表books,其中表示书本价格的列price的类型为一维integer类型数组,表示书本标签的列tag的类型为二维text类型数组。 1 CREATE TABLE books (id SERIAL PRIMARY KEY, title VARCHAR(100), price_by_quarter int[], tags TEXT[][]); CREATE TABLE语法可以指定数组的大小,例如: 1 CREATE TABLE test ( a int[3]); 当前的数据库实现会忽略语句中数组的大小限制,即其行为与未指定长度的数组相同。同时,也不会强制所声明的维度数。一个特定元素类型的数组全部被当作是相同的类型,而忽略其大小或维度数。 也可以使用关键词ARRAY来定义一维数组。表books中的列price使用ARRAY定义并指定数组大小,如下所示: 1 price_by_quarter int ARRAY[4] 使用ARRAY定义,不指定数组尺寸: 1 price_by_quarter int ARRAY
  • 语法格式 1 ARRAY [ param ] 或 1 '{ param }' 其中参数param说明如下: param :数组包含的值,允许出现零个或多个,多个值之间用逗号分隔,没有值可填写为NULL。 以'{ param }' 这种格式作为数组常量时,其中的字符串类型的元素不能再以单引号开始和结束,需要使用双引号。两个连续单引号转换为一个单引号。 以第一个元素的数据类型作为数组的数据类型,要求数组中所有元素的类型相同,或者能够相互转换。
  • 修改数组 更新数组 更新整个数组数据: UPDATE books SET price_by_quarter = '{30,30,30,30}' WHERE title = 'Robinson Crusoe'; 使用ARRAY表达式语法更新整个数组数据: UPDATE books SET price_by_quarter = ARRAY[30,30,30,30] WHERE title = 'Robinson Crusoe'; 更新数组中的一个元素: UPDATE books SET price_by_quarter[4] = 35 WHERE title = 'Robinson Crusoe'; 更新数组中的一个切片元素: UPDATE books SET price_by_quarter[1:2] = '{27,27}' WHERE title = 'Robinson Crusoe'; 一个已存储的数组值可以被通过对其还不存在的元素赋值来扩大大小。任何位于已存在的元素和新元素之间的位置都将被空值填充。例如,如果数组myarray目前有4个元素,使用UPDATE对myarray[6]赋值后它将有6个元素,其中myarray[5]为空值。目前,采用这种方式扩大数组只允许使用在一维数组上。 构建新数组 新的数组值也可以通过串接操作符“||”构建。串接操作符允许把一个单独的元素加入到一个一维数组的开头或末尾。也可接受两个N维数组,或者一个N维数组和一个N+1维数组。 SELECT ARRAY[1,2] || ARRAY[3,4]; ?column? ----------- {1,2,3,4} (1 row) SELECT ARRAY[5,6] || ARRAY[[1,2],[3,4]]; ?column? --------------------- {{5,6},{1,2},{3,4}} (1 row) 使用函数array_prepend、array_append或array_cat构建数组。 SELECT array_prepend(1, ARRAY[2,3]); array_prepend --------------- {1,2,3} (1 row) SELECT array_append(ARRAY[1,2], 3); array_append -------------- {1,2,3} (1 row) SELECT array_cat(ARRAY[1,2], ARRAY[3,4]); array_cat ----------- {1,2,3,4} (1 row) SELECT array_cat(ARRAY[[1,2],[3,4]], ARRAY[5,6]); array_cat --------------------- {{1,2},{3,4},{5,6}} (1 row) SELECT array_cat(ARRAY[5,6], ARRAY[[1,2],[3,4]]); array_cat --------------------- {{5,6},{1,2},{3,4}} (1 row)
  • 数组值输入 输入数组值时要把一个数组值写成一个文字常数,将元素值用花括号包围并用逗号分隔。一个数组常量的一般格式如下: 1 '{ val1 delim val2 delim ... }' 其中,delim是类型的定界符,每个val可以是数组元素类型的一个常量或子数组。 一个数组常量的例子如下: 1 '{{1,2,3},{4,5,6},{7,8,9}}' 该常量是一个二维的,3乘3数组,它由3个整数子数组构成。 向表books插入数据并查询表books: 1 2 3 4 5 6 7 8 9 10 11 12 INSERT INTO books VALUES (1, 'One Hundred years of Solitude','{25,25,25,25}','{{"fiction"}, {"adventure"}}'), (2, 'Robinson Crusoe', '{30,32,32,32}', '{{"adventure"}, {"fiction"}}'), (3, 'Gone with the Wind', '{27,27,29,28}', '{{"romance"}, {"fantasy"}}'); SELECT * FROM books; id | title | price_by_quarter | tags ----+-------------------------------+------------------+------------------------- 1 | One Hundred years of Solitude | {25,25,25,25} | {{fiction},{adventure}} 2 | Robinson Crusoe | {30,32,32,32} | {{adventure},{fiction}} 3 | Gone with the Wind | {27,27,29,28} | {{romance},{fantasy}} (3 rows) 插入多维数组数据时,多维数组的每一维都必须有相匹配的长度。 使用ARRAY关键字插入数据: INSERT INTO books VALUES (1, 'One Hundred years of Solitude',ARRAY[25,25,25,25],ARRAY['fiction', 'adventure']), (2, 'Robinson Crusoe', ARRAY[30,32,32,32], ARRAY['adventure', 'fiction']), (3, 'Gone with the Wind', ARRAY[27,27,29,28], ARRAY['romance', 'fantasy']);
  • pg_lifecycle_node_data_distribute() 描述:查看所有冷热表数据分布情况。 返回值:record 示例:数据库中当前存在两个冷热表,其数据分布情况如下。 1 2 3 4 5 6 SELECT * FROM pg_catalog.pg_lifecycle_node_data_distribute(); schemaname | tablename | nodename | hotpartition | coldpartition | switchablepartition | hotdatasize | colddatasize | switchabledatasize ------------+-----------+----------+--------------+---------------+---------------------+-------------+--------------+-------------------- public | w1 | dn_1 | p2 | p1 | | 81920 | 0 | 0 public | w2 | dn_1 | p2 | p1 | | 81920 | 0 | 0 (2 rows)
  • pg_refresh_storage() 描述:切换所有冷热表,将符合冷热切换规则的数据由热数据切换至冷数据(OBS中)。 返回值类型:int 返回值字段: success_count int:切换成功的表个数 failed_count int:切换失败的表个数 示例: 1 2 3 4 5 SELECT * FROM pg_refresh_storage(); success_count | failed_count ---------------+-------------- 1 | 0 (1 row)
  • pg_lifecycle_table_data_distribute(table_name) 描述:查看某个冷热表的数据分布情况。 table_name为表名,不可缺省。 返回值:record 示例:根据节点数量形成多条记录,如下示例为只有一个dn节点时w1表数据分布情况。 1 2 3 4 5 SELECT * FROM pg_catalog.pg_lifecycle_table_data_distribute('w1'); schemaname | tablename | nodename | hotpartition | coldpartition | switchablepartition | hotdatasize | colddatasize | switchabledatasize ------------+-----------+----------+--------------+---------------+---------------------+-------------+--------------+-------------------- public | w1 | dn_1 | p2 | p1 | | 80 KB | 0 bytes | 0 bytes (1 row)
  • pg_obs_cold_refresh_time(table_name, time) 描述:用来修改冷热表的冷数据切换至OBS上的时间,默认为每日0点。 table_name为冷热表表名,类型为name,time为数据切换任务调度时间,类型为Time。 返回值:SUC CES S,任务时间修改成功。 示例: 1 2 3 4 5 SELECT * FROM pg_obs_cold_refresh_time('lifecycle_table', '06:30:00'); pg_obs_cold_refresh_time -------------------------- SUCCESS (1 row)
  • jsonb_exists_all(jsonb, text[]) 描述:同操作符?&,字符串数组$2里面是否所有的元素,都在$1的顶层以key\elem\scalar的形式存在。 返回类型: bool 示例: 1 2 3 4 5 SELECT jsonb_exists_all('["1","2",3]', '{1, 2}'); jsonb_exists_all ------------------ t (1 row)
  • jsonb_pretty(jsonb) 描述:以缩进的JSON文本形式返回。 返回类型:jsonb 示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 SELECT jsonb_pretty('{"a":{"b":{"c":1, "d":2}}, "e":3}'::jsonb); jsonb_pretty --------------------- { + "a": { + "b": { + "c": 1,+ "d": 2 + } + }, + "e": 3 + } (1 row)
  • jsonb_exists_any(jsonb, text[]) 描述:同操作符?|,字符串数组$2里面是否存在的元素,在$1的顶层以key\elem\scalar的形式存在。 返回类型: 示例: 1 2 3 4 5 SELECT jsonb_exists_any('["1","2",3]', '{1, 2, 4}'); jsonb_exists_any ------------------ t (1 row)
  • jsonb_concat(jsonb, jsonb) 描述:连接两个jsonb对象为一个jsonb。 返回类型:jsonb 示例: 1 2 3 4 5 SELECT jsonb_concat('{"a":1, "b":2}'::jsonb, '{"c":3, "d":4}'::jsonb); jsonb_concat ---------------------------------- {"a": 1, "b": 2, "c": 3, "d": 4} (1 row)
  • jsonb_delete_path(jsonb, text[]) 描述:删除jsonb数组中指定路径的元素。 返回类型:jsonb 示例: 1 2 3 4 5 SELECT jsonb_delete_path('{"a":{"b":{"c":1, "d":2}}, "e":3}'::jsonb , array['a', 'b']); jsonb_delete_path ------------------- {"a": {}, "e": 3} (1 row)
  • jsonb_to_record(object-json) 描述:正如所有返回record的函数一样,调用者必须用一个AS子句显式地定义记录的结构。会将object-json的键值对进行拆分重组,把键当做列名,去匹配填充AS显示指定的记录的结构。 返回类型:record 示例: 1 2 3 4 5 SELECT * FROM jsonb_to_record('{"a":1,"b":"foo","c":"bar"}'::jsonb) as x(a int, b text, d text); a | b | d ---+-----+--- 1 | foo | (1 row)
  • jsonb_delete_array(jsonb, VARIADIC text[]) 描述:删除jsonb数组中的多个元素。 返回类型:jsonb 示例: 1 2 3 4 5 SELECT jsonb_delete_array('["a", "b", "c"]'::jsonb , 'a', 'b'); jsonb_delete_array -------------------- ["c"] (1 row)
  • jsonb_set(target jsonb, path text[], new_value jsonb [, create_missing boolean]) 描述:返回target,用path指定的部分被new_value替换,或者如果create_missing为true(默认值为true)且path指定的项不存在,则添加new_value。与面向路径的运算符一样,path中出现的负整数从JSON数组的末尾开始计数。 返回类型:jsonb 示例: 1 2 3 4 5 SELECT jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}','[2,3,4]', false); jsonb_set --------------------------------------------- [{"f1": [2, 3, 4], "f2": null}, 2, null, 3] (1 row)
  • jsonb_populate_record_set(anyelement, array-jsonb [, bool]) 描述:参考上述函数json_populate_record、jsonb_populate_record,对$2数组的每一个元素进行上述参数函数的操作,因此这也要求$2数组的每个元素都是object-json类型。 返回类型:setof anyelement 示例: 1 2 3 4 5 6 SELECT * FROM json_populate_recordset(null::jpop, '[{"a":1,"b":2},{"a":3,"b":4}]'); a | b | c ---+---+--- 1 | 2 | 3 | 4 | (2 rows)
共100000条