百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

如何使用注释记录数据库对象(如何使用注释记录数据库对象的方法)

sinye56 2024-10-16 15:13 7 浏览 0 评论

不要再试图通过使用结构化的数据库模式文档来猜测数据库列的存在原因。

译自 How to Document Database Objects with Annotations,作者 Chris Saxon 是Oracle数据库的开发者倡导者,他的工作是帮助您充分利用它并享受SQL的乐趣。您可以在Twitter上找到他,账号为@ChrisRSaxon,也可以在他的博客"All Things SQL"上找到他。

每个数据库都有它们,一组列 —— 或者甚至整个表 —— 没有人能解释它们存在的原因。关于它们的任何文档(如果曾经存在过)都已经遗失在您公司的wiki中。

为了帮助您理解您的模式,最好记录在数据库内部的注释,理想情况下应该直接位于列和表旁边。这将允许您在工具中查看这些细节或通过查询数据字典来查看。

大多数数据库系统都允许您使用对象注释来实现这一点。例如,在Oracle数据库中,您可以使用COMMENT命令:

create table games ( 
  game_id         int primary key,
  home_team_id    int, 
  away_team_id    int, 
  game_datetime   timestamp,
  insert_datetime timestamp
);

comment on column games.insert_datetime
  is 'Audit log of when each row was inserted';
comment on table games 
  is 'Scheduled matches between teams';

然后,这些信息会出现在相应对象的注释字典视图中:

select comments from user_tab_comments
where  table_name = 'GAMES';

COMMENTS                           
Scheduled matches between teams 

select column_name, comments from user_col_comments
where  table_name = 'GAMES'
and    comments is not null;

COLUMN_NAME        COMMENTS                                   
INSERT_DATETIME    Audit log of when each row was inserted

这是帮助其他开发人员和数据库管理员(DBA)理解您的模式的好方法。

但是注释只是一个字符串。如果要存储有关对象的许多属性,则使用它们会很麻烦。

例如,数据库表通常包括一个INSERT_DATETIME列。这些列应该都是:

  • 系统生成的:数据库应该使用列默认值提供值。
  • 强制性的:不允许为空。
  • 仅插入:这些值永远不应更新。

这些信息涉及您使用数据的意图:不仅仅是为什么存在这些列,而是如何与它们交互。记录这些细节有助于将来的维护人员理解如何在应用程序中使用这些数据。

您可以将这些属性与注释中的其他注释一起存储。问题是您要使用哪种格式?JSON?XML?分隔键值对?

无论您选择哪种格式,您都需要所有未来的维护人员都遵循相同的格式。对于长期存活的系统来说,这变得具有挑战性。如果数据库本身对注释强制执行一些结构将会更好。

Oracle数据库23c通过添加使用注释来解决了这个问题。

通过注释改进数据库文档

注释是带有可选值的键。您可以使用它们记录有关所讨论对象的任何元数据。

例如,下面的内容使用上述列出的属性注释了INSERT_DATETIME列:

alter table games modify (
  insert_datetime annotations ( 
    mandatory, 
    system_generated, 
    allowed_writes '["insert"]',
    description 'Audit log of when each row was inserted'
  )
);

你可能会想为什么allowed_writes使用了一个JSON数组,即使只有一个值。为什么不只使用字符串“insert”?

您可能希望将此注释应用于许多列。这些列可能还支持更新或删除。将它们全部设置为数组比混合使用数组和普通字符串更易于处理。

添加了注释后,您可以在*_usage_annotations视图中查看它们:

COLUMN_NAME        ANNOTATION_NAME     ANNOTATION_VALUE                           
INSERT_DATETIME    MANDATORY           <null>                                     
INSERT_DATETIME    SYSTEM_GENERATED    <null>                                     
INSERT_DATETIME    ALLOWED_WRITES      ["insert"]                                 
INSERT_DATETIME    DESCRIPTION         Audit log of when each row was inserted   

这些视图显示了所有对象类型的注释。这意味着它们都可以在一个位置访问,这样如果您想要编程访问注释以生成单独的文档,就变得非常简单。

注释的键值结构使其比注释更强大。

但是,当您将它们用于常见值时,仍然存在挑战。模式中的大多数或所有表都将具有一个INSERT_DATETIME列。这些列应该都具有相同的注释。随着时间的推移,试图保持所有这些同步是很困难的!

与其将注释复制到每个INSERT_DATETIME列中,不如在共享对象中定义一次,然后将此对象应用于所有需要的列。这确保它们都具有相同的属性。

问题是:如何做到这一点?

使用域标准化注释

Oracle数据库23c通过添加使用域来解决了这个问题。这些域是在SQL标准中构建的。它们通过可选属性扩展了现有的数据类型,包括:

  • 约束
  • 默认值
  • 注释

使用CREATE DOMAIN语句来创建一个。这将创建一个带有上述注释的INSERT_DATETIME域:

create domain insert_timestamp as 
  timestamp 
  annotations ( 
    mandatory, 
    system_generated, 
    allowed_writes '["insert"]',
    description 'Audit log of when each row was inserted'
  );

然后,在创建或修改表时,可以将此域应用于列。通过在数据类型之后指定域,或者使用域子句替代数据类型,来执行此操作。这将注释从域复制到表列:

alter table games
  modify ( 
    insert_datetime domain insert_timestamp 
  );

create table teams ( 
  team_id          int, 
  team_name        varchar2(100), 
  insert_datetime domain insert_timestamp
);

select object_name, column_name, annotation_name, annotation_value 
from   user_annotations_usage
where  'INSERT_TIMESTAMP' in ( object_name, domain_name );

OBJECT_NAME         COLUMN_NAME         ANNOTATION_NAME     ANNOTATION_VALUE                           
INSERT_TIMESTAMP    INSERT_TIMESTAMP    MANDATORY           <null>                                     
INSERT_TIMESTAMP    INSERT_TIMESTAMP    SYSTEM_GENERATED    <null>                                     
INSERT_TIMESTAMP    INSERT_TIMESTAMP    ALLOWED_WRITES      ["insert"]                                 
INSERT_TIMESTAMP    INSERT_TIMESTAMP    DESCRIPTION         Audit log of when each row was inserted    
GAMES               INSERT_DATETIME     MANDATORY           <null>                                     
GAMES               INSERT_DATETIME     SYSTEM_GENERATED    <null>                                     
GAMES               INSERT_DATETIME     ALLOWED_WRITES      ["insert"]                                 
GAMES               INSERT_DATETIME     DESCRIPTION         Audit log of when each row was inserted    
TEAMS               INSERT_DATETIME     MANDATORY           <null>                                     
TEAMS               INSERT_DATETIME     SYSTEM_GENERATED    <null>                                     
TEAMS               INSERT_DATETIME     ALLOWED_WRITES      ["insert"]                                 
TEAMS               INSERT_DATETIME     DESCRIPTION         Audit log of when each row was inserted

要将域链接到列,它们都必须具有相同的基本数据类型。您只能将INSERT_DATETIME域与timestamp列关联,不能与date、number、varchar2等关联。

有了这个集中的定义,您可以确信使用域的所有列都具有相同的注释。即使将来要更改它们,也适用。

例如,您可能希望指定允许在插入时间戳上执行过滤和排序操作,这意味着可以安全地在WHERE和ORDER BY子句中使用这些列。

您可以修改域以添加这些注释:

alter domain insert_timestamp 
  annotations ( allowed_reads '["where", "order by"]');

数据库会自动将这些应用于相应的数据库列:

select object_name, object_type, column_name, domain_name, annotation_value 
from   user_annotations_usage
where  annotation_name = 'ALLOWED_READS'
order  by object_type, object_name;

OBJECT_NAME         OBJECT_TYPE    COLUMN_NAME        DOMAIN_NAME         ANNOTATION_VALUE         
INSERT_TIMESTAMP    DOMAIN         <null>             <null>              ["where", "order by"]    
GAMES               TABLE          INSERT_DATETIME    INSERT_TIMESTAMP    ["where", "order by"]    
TEAMS               TABLE          INSERT_DATETIME    INSERT_TIMESTAMP    ["where", "order by"]

文档数据意图

数据库模式可能会很复杂。理解每个部分的目的可能会有些棘手。通过在模式本身中记录这些信息,您可以帮助所有人了解每个部分的如何和为什么。

注释是记录这些细节的常用方式。它们的非结构化性质限制了它们的有用性。Oracle数据库23c中的注释的键值结构赋予了您更大的权力。

在Oracle数据库23c中,您还可以定义域。这些为您提供了一个用于常见数据值的单一定义点,例如插入时间戳。

结合域和注释,您可以简单地描述数据。它们共同形成了一种新的SQL语句类别:数据意图语言(DIL)。

随着模式的增长,使用这些DIL语句将是帮助其他开发人员理解如何以及为什么使用它的关键。

帮助您的同行开发人员和数据库管理员:使用域和注释记录您的数据库!

相关推荐

程序员:JDK的安装与配置(完整版)_jdk的安装方法

对于Java程序员来说,jdk是必不陌生的一个词。但怎么安装配置jdk,对新手来说确实头疼的一件事情。我这里以jdk10为例,详细的说明讲解了jdk的安装和配置,如果有不明白的小伙伴可以评论区留言哦下...

Linux中安装jdk并配置环境变量_linux jdk安装教程及环境变量配置

一、通过连接工具登录到Linux(我这里使用的Centos7.6版本)服务器连接工具有很多我就不一一介绍了今天使用比较常用的XShell工具登录成功如下:二、上传jdk安装包到Linux服务器jdk...

麒麟系统安装JAVA JDK教程_麒麟系统配置jdk

检查检查系统是否自带java在麒麟系统桌面空白处,右键“在终端打开”,打开shell对话框输入:java–version查看是否自带java及版本如图所示,系统自带OpenJDK,要先卸载自带JDK...

学习笔记-Linux JDK - 安装&amp;配置

前提条件#检查是否存在JDKrpm-qa|grepjava#删除现存JDKyum-yremovejava*安装OracleJDK不分系统#进入安装文件目...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

测试员必备:Linux下安装JDK 1.8你必须知道的那些事

1.简介在Oracle收购Sun后,Java的一系列产品就被整合到Oracle官网中,打开官网乍眼一看也不知道去哪里下载,还得一个一个的摸索尝试,而且网上大多数都是一些Oracle收购Sun前,或者就...

Linux 下安装JDK17_linux 安装jdk1.8 yum

一、安装环境操作系统:JDK版本:17二、安装步骤第一步:下载安装包下载Linux环境下的jdk1.8,请去官网(https://www.oracle.com/java/technologies/do...

在Ubuntu系统中安装JDK 17并配置环境变量教程

在Ubuntu系统上安装JDK17并配置环境变量是Java开发环境搭建的重要步骤。JDK17是Oracle提供的长期支持版本,广泛用于开发Java应用程序。以下是详细的步骤,帮助你在Ubuntu系...

如何在 Linux 上安装 Java_linux安装java的步骤

在桌面上拥抱Java应用程序,然后在所有桌面上运行它们。--SethKenlon(作者)无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序...

Windows和Linux环境下的JDK安装教程

JavaDevelopmentKit(简称JDK),是Java开发的核心工具包,提供了Java应用程序的编译、运行和开发所需的各类工具和类库。它包括了JRE(JavaRuntimeEnviro...

linux安装jdk_linux安装jdk软连接

JDK是啥就不用多介绍了哈,外行的人也不会进来看我的博文。依然记得读大学那会,第一次实验课就是在机房安装jdk,编写HelloWorld程序。时光飞逝啊,一下过了十多年了,挣了不少钱,买了跑车,娶了富...

linux安装jdk,全局配置,不同用户不同jdk

jdk1.8安装包链接:https://pan.baidu.com/s/14qBrh6ZpLK04QS8ogCepwg提取码:09zs上传文件解压tar-zxvfjdk-8u152-linux-...

运维大神教你在linux下安装jdk8_linux安装jdk1.7

1.到官网下载适合自己机器的版本。楼主下载的是jdk-8u66-linux-i586.tar.gzhttp://www.oracle.com/technetwork/java/javase/downl...

window和linux安装JDK1.8_linux 安装jdk1.8.tar

Windows安装JDK1.8的步骤:步骤1:下载JDK打开浏览器,找到JDK下载页面https://d.injdk.cn/download/oraclejdk/8在页面中找到并点击“下载...

最全的linux下安装JavaJDK的教程(图文详解)不会安装你来打我?

默认已经有了linux服务器,且有root账号首先检查一下是否已经安装过java的jdk任意位置输入命令:whichjava像我这个已经安装过了,就会提示在哪个位置,你的肯定是找不到。一般我们在...

取消回复欢迎 发表评论: