在使用PostgreSQL的过程中,已经积累了一百多个用于处理系统目录的函数:pg_class,pg_attribute,pg_constraints等。
该怎么办? 它们相对很少使用。 包括在任何项目中吗? 克拉斯诺亚尔斯克客户不会为这种“废话”付款。 但是,如果它们对作者以外的其他人有用,该怎么办? 然后,他决定将它们像看书一样放置在公共橱柜中,以备不时之需。
有人想在他们的工作中使用它们。 和对系统目录的经验感兴趣的人。
但是为了不使出版物变成无聊的枚举,不知道为什么要创建这些功能,我决定着重讨论那些可以实现共同目标的功能。 因此,选择用于显示任意数据库表特征的扩展列表的功能。
数据库表特征的扩展列表由
admtf_Table_ComplexFeatures函数返回,该函数在本文中称为head函数。 因此,本文将限于考虑在执行head函数的过程中调用的函数。
本文的前半部分提供了有关功能实现的评论。 第二个是函数的源代码。 对于只对源文本感兴趣的读者,我们建议立即继续阅读
附录 。
另请参阅
记录PostgreSQL数据库的功能。 第二部分 ;
记录PostgreSQL数据库的功能。 第三部分 。
记录PostgreSQL数据库的功能。 最后(第四部分) 。
我们在说什么高级功能?
为了了解数据库表的扩展特征的含义,我们首先考虑以下特征列表。 该列表包含
admtf_Table_ComplexFeatures( 'public' , 'street' )返回的Street数据库表的特征。
下表包含Street表功能的缩写列表。 附录2的补充材料中提供了此表的完整特性。
表1. Street表的高级功能。

图中表格的文本版本类别分类 | 不行 | 职称 | 评注 | 类型 | 基本类型 | ? 不为NULL |
---|
tbl | 0 | 街 | 定居点的街道清单 | | | |
att | 1个 | wcrccode | 国家区号 | wcrccode | Smallint | Ť |
att | 2 | 地区性 | 社区ID | 地区性 | 整数 | Ť |
att | 3 | 街头小贩 | 村ID街 | 街头小贩 | Smallint | Ť |
att | 4 | streettypeacrm | 街头缩写 | streettypeacrm | 人物(8) | ˚F |
att | 5 | 街道名 | 街道名称 | streettypeacrm | varchar(150) | Ť |
pk | 0 | xpkstreet | 街道表主键 | | | |
pkatt | 1个 | wcrccode | 国家区号 | wcrccode | Smallint | Ť |
fk01 | 1个 | fk_street_locality | 表外键 | | | |
fk02 | 2 | fk_street_streettype | 表外键 | | | |
idx01 | 1个 | xie1street | 按居民点类型和街道名称编制的索引 | | | |
idx02 | 2 | xie2street | 邮递区号 | | | |
idx03 | 3 | xie3street | 所有定居点的街道名称索引 | | | |
idx04 | 4 | xpkstreet | 街道表的唯一(主键)索引 | | | |
列举对这组字母和数字的敌意,您可以看到我们正在谈论数据库表的通常特征:
- 表名;
- 表属性及其类型的列表;
- 表的主键和外键列表,以及组成它们的表的属性;
- 表索引列表。
特性列表中每个条目的唯一性由“类别”字段的值和特性的序列号(“编号”)确保。
表2.表特征的类别。
图中表格的文本版本首字母缩写 | 预约时间 |
---|
待定 | 表特征 |
att | 表属性特征 |
序列 | 序列特征 |
pk | 主要关键特征 |
pkAtt | 主键属性特征 |
fk99 | 外键功能 |
fk99att | 外键属性特征 |
fk99rtbl | 外键引用表的特征 |
fk99ratt | 外键引用的表的属性特征 |
编号99 | 指标特征 |
Idx99att | 索引属性特征 |
Inhtbl99 | 生成表的特征 |
类别值是区分彼此不同的特征组所必需的。 序列号,以区分组内的特征。
可以在数据库表中声明几个外键(FOREIGN KEY)和索引。 因此,这些特征及其后代的类别值包含一个序列号。 例如,键为“ Category” = idx02att和“ No.” = 1的条目表示第二个索引的第一个属性。
在上面的类别列表中,序列号的位置表示为“ 99”。
备注1

图中操作员的源代码SELECT * FROM admtf_Table_ComplexFeatures('pg_catalog','pg_class');
本文提供了表特性的示例,这些示例在专门为演示功能而创建的辅助方案中进行了简要描述。 但是,已经在数据库中创建了该功能的读者可以将其方案和表的名称用作参数。 而且,例如,尽管在这种情况下发出了有限数量的特征,但是pg_class目录可以用作参数。
备注的结尾。
头功能结构
图 1.引起头部功能的功能。表3.功能分配。
图中表格的文本版本不行 | 职称 | 预约时间 |
---|
1个 | admtf_Table_Features | 该函数返回数据库表特征的列表 |
2 | admtf_Table_Attributes | 该函数返回数据库表属性及其特征的列表。 |
3 | admtf_Table_Constraintes | 该函数返回数据库表限制及其特征的列表。 |
4 | admtf_Table_Indexes | 该函数返回数据库表索引及其特征的列表。 |
5 | admtf_Table_InheritanceChildrens | 该函数返回由(IHERITS)从源数据库表生成的表的列表。 |
6 | admtf_Table_Sequences | 该函数返回该表所依赖的序列列表(SEQUENCE)。 |
7 | admtf_PrimaryKey_ComplexFeatures | 该函数返回数据库表的主键特征(PRIMARY KEY)的完整(扩展)列表。 |
8 | admtf_ForeignKey_ComplexFeatures | 该函数返回数据库表的外键特征(FOREIGN KEY)的完整(扩展)列表。 |
9 | admtf_Index_ComplexFeatures | 该函数返回数据库表索引特征的完整(扩展)列表。 |
10 | admtf_Table_ComplexFeatures | 该函数返回数据库表特征的完整(扩展)列表。 |
备注2。
功能描述将按上面显示的顺序排列。 原因是该文章将必须分为几个部分。 并且可以使用按此顺序排列的功能,而不管其中的某些功能仅在出版物的以下部分中进行描述的事实。
备注的结尾。
admtf_Table_Features函数列表数据库的表特征
admtf_Table_Features函数返回数据库表本身的特征列表。 可以在此处查看和下载源代码。
作为参数,此函数采用源表的名称(a_TableName )和在其中创建表的方案的名称( a_SchemaName )。
该函数从pg_class目录条目中提取主要数据,除表条目外,该条目还包含有关序列,视图,实例化视图和组合类型的记录。 因此,要选择表,使用条件relkind = 'r' 。
SELECT tbl.relname,dsc.description,tbl.relnatts::INTEGER,tbl.relchecks::INTEGER, tbl.relhaspkey,tbl.relhasindex,tbl.relhassubclass,tbl.reltuples::INTEGER FROM pg_class tbl INNER JOIN pg_namespace nspc ON tbl.relnamespace = nspc.oid LEFT OUTER JOIN pg_description dsc ON tbl.oid=dsc.objoid AND dsc.objsubid=0 WHERE LOWER( nspc.nspname)=LOWER(a_SchemaName) AND tbl.relkind='r' AND LOWER(tbl.relname) =LOWER(a_TableName);
另外,该函数访问目录数据pg_namespace和pg_description 。 第一个包含数据库模式的名称,第二个包含对所有数据库对象的注释。
重要的是要注意条件objsubid = 0 。 它定义了表的注释,因为表及其属性的objoid字段的值都相同。 关于表的属性的注释包含在objsubid与该属性的编号匹配的条目中。
表4.执行admtf_Table_Features函数(“ public”,“ Street”)的结果。职称 | 评注 | 属性数量 | 检查约束数 | ? 有主键吗 | ? 是声明的索引 | ? 有后裔吗 | 表中的条目数 |
---|
街 | 定居点的街道清单 | 22 | 0 | Ť | Ť | ˚F | 20150 |
备注3
注意街道表属性的数量。 它与辅助模式中指定的属性数量明显不同。
表5. Street表的其他属性。
姓名 | tty | Attnum | 注意事项 |
---|
in | 29日 | -4 | 系统属性 |
最小 | 28 | -3 | 系统属性 |
ctid | 27 | -1 | 系统属性 |
wcrccode | 795369 | 1个 | 有效属性 |
地区性 | 795352 | 2 | 有效属性 |
街头小贩 | 795364 | 3 | 有效属性 |
streettypeacrm | 1919168 | 4 | 有效属性 |
街道名 | 1043 | 5 | 有效属性 |
..... pg.dropped.6 ........ | 0 | 6 | 远程属性 |
..... pg.dropped.7 ........ | 0 | 7 | 远程属性 |
事实是,除了主要属性外,PostgreSQL还考虑了几个系统属性,甚至删除了属性。
结束语
数据库表属性及其特征的函数admtf_Table_Attributes列表
admtf_Table_Attributes函数返回数据库表属性的列表。 可以在此处查看和下载源代码。
该函数将源表的名称( a_TableName )和在其中创建表的方案的名称( a_SchemaName )作为参数。
该函数从pg_attribute和pg_type目录条目中检索主要数据。 第一个记录包含有关表,视图,实例化视图,组合类型甚至函数的属性的数据记录。 第二点是关于属性类型的特征。
可能需要通过在函数中定义用户和基本类型的方式进行一些说明。
如果在相应的pg_type目录条目中的typbasetype字段大于 0,则使用自定义类型声明表属性,否则,该属性为基本类型。 因此,在FROM子句中两次涉及pg_type目录。 在第一个目录条目中,确定用户类型的存在,如果未定义( typebasetype = 0 ),则从该条目中生成基本类型值。 否则,从btyp.OID = typ.typbasetype的记录中确定基本类型。
使用系统目录FORMAT_TYPE(type_oid,typemod)的功能直接形成基本类型的行。 其第一个参数是基本类型OID记录。 第二个参数是包含大小的类型的修饰符值。 例如,VARCHAR(100)或NUMERIC(4,2),DECIMAL(4,2)。 如果属性是用户类型,则从typ.typtypmod中获取typemod参数的值,否则从attr.atttypmod中获取 ,即 直接从属性记录。

图中操作员的源代码 SELECT attr.attnum, attr.attname::VARCHAR(100), CASE WHEN COALESCE(typ.typbasetype,0)>0 THEN typ.typname::VARCHAR(100) ELSE '' END, FORMAT_TYPE(COALESCE(NULLIF(typ.typbasetype,0),typ.oid), COALESCE(NULLIF(typ.typtypmod,-1),attr.atttypmod))::VARCHAR(256), attr.attnotnull, dsc.description FROM pg_attribute attr INNER JOIN pg_class tbl ON tbl.oid = attr.attrelid INNER JOIN pg_namespace nspc ON tbl.relnamespace = nspc.oid INNER JOIN pg_type typ ON attr.atttypid=typ.oid LEFT OUTER JOIN pg_description dsc ON dsc.objoid=attr.attrelid AND dsc.objsubid=attr.attnum WHERE LOWER( nspc.nspname)=LOWER(a_SchemaName) AND LOWER(tbl.relname) =LOWER(a_TableName) AND tbl.relkind='r' AND attr.attnum>0 AND attr.atttypID>0 ORDER BY tbl.relname,attr.attnum;
另外,该函数访问目录数据pg_class , pg_namespace和pg_description 。 第一和第二目录用于通过模式和数据库表的名称搜索属性。
第三个目录用于检索表属性的注释。
关于表属性的注释在条目中,其中dsc.objoid包含源表的OID,而dsc.objsubid是表中属性的序列号,即 attr.attnum 。
为了防止该函数返回系统和远程属性,WHERE子句将条件设置为attr.attnum> 0和attr.atttypID> 0 。
表6.执行admtf_Table_Attributes函数(“ public”,“ Street”)的结果。不行 | 职称 | 自订类型 | 基本类型 | ? 不为空 | 评注 |
---|
1个 | wcrccode | wcrccode | Smallint | Ť | 国家区号 |
2 | 地区性 | 地区性 | 整数 | Ť | 社区ID |
3 | 街头小贩 | 街头小贩 | Smallint | Ť | 村ID街 |
4 | streettypeacrm | streettypeacrm | 人物(8) | ˚F | 街头缩写 |
5 | 街道名 | | varchar(150) | Ť | 定居点的街道名称 |
使用regclass别名作为oid类型的函数版本
PostgreSQL对象标识符(OID)与OID的类型相同,OID当前被实现为无符号的四字节整数。 但是由于存在这种别名,因此可以将整数表示为对象的名称。 反之亦然-将对象名称转换为OID类型的整数。
作为示例,请看下面的SELECT语句 。 它会异常地检索属性表的名称及其类型的名称-而不是使用这些特征的名称来访问相应的目录字段,而是使用它们:
- attrelid :: regclass(attrelid :: regclass:NAME) ,
- atttypid :: regtype(atttypid :: regtype:NAME)
- typbasetype :: regtype(typbasetype :: regtype:NAME) 。
SELECT attr.attname,attr.attrelid::regclass, attr.atttypid::regtype, typ.typbasetype::regtype,attr.attrelid::regclass::name, attr.atttypid::regtype::name,typ.typbasetype::regtype::name FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid WHERE attr.attrelid=('public'||'.'||'Street')::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum;
以下是执行此查询的结果。

在使用OID类型的别名进行转换之前的SELECT运算符的输出值列表中,除属性名称之外的所有值都是数字,因此,将显示表名称和属性类型。 可以在表标题的第二行中考虑输出值的类型。
另外,在该语句的WHERE子句中,条件attr.attrelid =('public'||'。'||'Street'):: regclass位于 ,其左侧是一个数字值,而右侧是一个字符串,该字符串被转换为带有使用别名regclass 。

图中操作员的源代码 SELECT attr.attnum, attr.attname::VARCHAR(100), CASE WHEN COALESCE(typ.typbasetype,0)>0 THEN typ.typname::VARCHAR(100) ELSE '' END, FORMAT_TYPE(COALESCE(NULLIF(typ.typbasetype,0),typ.oid), COALESCE(NULLIF(typ.typtypmod,-1),attr.atttypmod))::VARCHAR(256), attr.attnotnull, dsc.description FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid LEFT OUTER JOIN pg_description dsc ON dsc.objoid=attr.attrelid AND dsc.objsubid=attr.attnum WHERE attr.attrelid=( a_SchemaName ||'.'|| a_TableName)::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum;
使用main语句中的别名regclass,可以删除与两个目录的连接。 但是这种改进几乎对功能的性能没有影响-在两个版本中,该功能都在11毫秒内执行。 可能由于测试表几乎没有属性的事实。
备注4当数据库中存在具有异常名称的模式和/或表时,就会表现出attr.attrelid =(a_SchemaName ||'。'|| a_TableName):: regclass形式的条件中的严重缺陷。 例如, “我的模式”和/或“我的表” 。 此类值必须使用双引号括起来或使用QUOTE_IDENT函数进行传输,否则该函数将因系统错误而失败。

图中操作员的源代码 SELECT attr.attname,attr.attrelid::regclass, attr.atttypid::regtype,typ.typbasetype::regtype, attr.attrelid::regclass::name, attr.atttypid::regtype::name,typ.typbasetype::regtype::name FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid WHERE attr.attrelid=(' '||'.'||' ')::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum; SELECT attr.attname,attr.attrelid::regclass, attr.atttypid::regtype,typ.typbasetype::regtype, attr.attrelid::regclass::name, attr.atttypid::regtype::name,typ.typbasetype::regtype::name FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid WHERE attr.attrelid=('" "'||'.'||'" "')::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum;
因此,我更喜欢使用
LOWER(nspc.nspname)= LOWER(a_SchemaName)和LOWER(tbl.relname)= LOWER(a_TableName)形式的条件 ,这不会导致系统错误。
结束语附录1.脚本
创建admtf_Table_Features函数
有关功能源代码的注释,请参见此处。函数源代码 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Features (a_SchemaName NAME,a_TableName NAME); CREATE OR REPLACE FUNCTION admtf_Table_Features (a_SchemaName NAME default 'public', a_TableName NAME default NULL ) RETURNS TABLE (rs_TableName NAME,rs_TableDescription TEXT,rs_NumberOfAttribute INTEGER,rs_NumberOfChecks INTEGER,rs_hasPKey BOOLEAN,rs_hasIndex BOOLEAN,rs_hasSubClass BOOLEAN,rs_NumberOfRow INTEGER) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; v_TableOID OID; v_TableName NAME; v_TableDescription TEXT; v_TableNumberOfRowCalc INTEGER;
创建admtf_Table_Attributes函数
有关功能源代码的注释,请参见此处。函数源代码 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Attributes (a_SchemaName NAME,a_TableName NAME); CREATE OR REPLACE FUNCTION admtf_Table_Attributes (a_SchemaName NAME default 'public', a_TableName NAME default NULL ) RETURNS TABLE (r_AttributeNumber SMALLINT,r_AttributeName NAME,r_UserTypeName NAME,r_TypeName NAME,r_isNotNULL BOOLEAN, r_Description Text) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; v_Scale INTEGER;
使用Regclass别名创建admtf_Table_Attributes函数
有关功能源代码的注释,请参见此处。函数源代码 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Attributes (a_SchemaName NAME,a_TableName NAME); CREATE OR REPLACE FUNCTION admtf_Table_Attributes (a_SchemaName NAME default 'public', a_TableName NAME default NULL ) RETURNS TABLE (r_AttributeNumber SMALLINT,r_AttributeName NAME,r_UserTypeName NAME,r_TypeName NAME,r_isNotNULL BOOLEAN, r_Description Text) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; v_Scale INTEGER;
附录2.其他材料
辅助数据库架构

- 国家 -世界国家分类-OKSM(世界国家的全俄分类);
- HOUSEADDR-定居点街道上的门牌号码列表;
- LCLTYTYPE-结算类型目录;
- 地点 -和解清单;
- STREET — ;
- STREETTYPE — ;
- TERRITORY — (, , , ..);
- TERRITORYTYPE — .
Street ()
.1. Street ().
类别分类 | 不行 | 职称 | 评注 | 类型 | 基本类型 | ? 不为空 |
---|
tbl | 0 | 街 | 定居点的街道清单 | | | |
att | 1个 | wcrccode | 国家区号 | wcrccode | Smallint | Ť |
att | 2 | 地区性 | 社区ID | 地区性 | 整数 | Ť |
att | 3 | 街头小贩 | 村ID街 | 街头小贩 | Smallint | Ť |
att | 4 | streettypeacrm | 街头缩写 | streettypeacrm | 人物(8) | ˚F |
att | 5 | 街道名 | 街道名称 | streettypeacrm | varchar(150) | Ť |
pk | 0 | xpkstreet | 街道表主键 | | | |
pkatt | 1个 | wcrccode | 国家区号 | wcrccode | Smallint | Ť |
pkatt | 2 | 地区性 | 社区ID | 地区性 | 整数 | Ť |
pkatt | 3 | 街头小贩 | 村ID街 | 街头小贩 | Smallint | Ť |
fk01 | 1个 | fk_street_locality | 表外键 | | | |
fk01att | 1个 | wcrccode | 国家区号 | wcrccode | Smallint | Ť |
fk01att | 2 | 地区性 | 社区ID | 地区性 | 整数 | Ť |
fk01rtbl | 0 | 地区 | 和解清单 | | | |
fk01ratt | 1个 | wcrccode | 国家区号 | wcrccode | Smallint | Ť |
fk01ratt | 2 | 地区性 | 社区ID | 地区性 | 整数 | Ť |
fk02 | 2 | fk_street_streettype | 表外键 | | | |
fk02att | 1个 | streettypeacrm | 街头缩写 | streettypeacrm | 人物(8) | ˚F |
fk02rtbl | 0 | 街道型 | 街道类型参考 | | | |
fk02ratt | 1个 | streettypeacrm | 街头缩写 | streettypeacrm | 人物(8) | Ť |
idx01 | 1个 | xie1street | | | | |
idx01att | 1个 | wcrccode | | wcrccode | smallint | Ť |
idx01att | 2 | localityid | | localityid | integer | Ť |
idx01att | 3 | streettypeacrm | | streettypeacrm | character(8) | ˚F |
idx01att | 4 | streetname | | | varchar(150) | Ť |
idx02 | 2 | xie2street | | | | |
idx02att | 1个 | wcrccode | | wcrccode | smallin | Ť |
idx02att | 2 | localityid | | localityid | integer | Ť |
idx02att | 3 | streetname | | | varchar(150) | Ť |
idx03 | 3 | xie3street | | | | |
idx03att | 1个 | streetname | | | varchar(150) | Ť |
idx04 | 4 | xpkstreet | ( ) street | | | |
idx04att | 1个 | wcrccode | | wcrccode | smallint | Ť |
idx04att | 2 | localityid | | localityid | integer | Ť |
idx04att | 3 | streetid | | streetid | smallint | Ť |
另请参阅
记录PostgreSQL数据库的功能。 ;记录PostgreSQL数据库的功能。 第三部分 。记录PostgreSQL数据库的功能。 最后(第四部分) 。