PostgreSQL教程(一):数据表详解

一、表的定义:

对于任何一种关系型数据库而言,表都是数据存储的最核心、最基础的对象单元。现在就让我们从这里起步吧。
    1. 创建表:
 

代码如下:

CREATE TABLE products (
        product_no integer,
        name text,
        price numeric
    );

    2. 删除表:
 

代码如下:

DROP TABLE products;

    3. 创建带有缺省值的表:
 

代码如下:

CREATE TABLE products (
        product_no integer,
        name text,
        price numeric DEFAULT 9.99 --DEFAULT是关键字,其后的数值9.99是字段price的默认值。
    );
   
    CREATE TABLE products (
        product_no SERIAL,            --SERIAL类型的字段表示该字段为自增字段,完全等同于Oracle中的Sequence。
        name text,
        price numeric DEFAULT 9.99
    );

输出为:
 

代码如下:

NOTICE:  CREATE TABLE will create implicit sequence "products_product_no_seq" for serial column "products.product_no"

4. 约束:
    检查约束是表中最为常见的约束类型,它允许你声明在某个字段里的数值必须满足一个布尔表达式。不仅如此,我们也可以声明表级别的检查约束。
 

代码如下:

CREATE TABLE products (
        product_no integer,
        name text,
        --price字段的值必须大于0,否则在插入或修改该字段值是,将引发违规错误。还需要说明的是,该检查约束
        --是匿名约束,即在表定义时没有显示命名该约束,这样PostgreSQL将会根据当前的表名、字段名和约束类型,
        --为该约束自动命名,如:products_price_check。
        price numeric CHECK (price > 0)
    );
 
    CREATE TABLE products (
        product_no integer,
        name text,
        --该字段的检查约束被显示命名为positive_price。这样做好处在于今后维护该约束时,可以根据该名进行直接操作。
        price numeric CONSTRAINT positive_price CHECK (price > 0)
    );

下面的约束是非空约束,即约束的字段不能插入空值,或者是将已有数据更新为空值。
 

代码如下:

CREATE TABLE products (
        product_no integer NOT NULL,
        name text NOT NULL,
        price numeric
    );

如果一个字段中存在多个约束,在定义时可以不用考虑约束的声明顺序。
 

代码如下:

CREATE TABLE products (
        product_no integer NOT NULL,
        name text NOT NULL,
        price numeric NOT NULL CHECK (price > 0)
    );

唯一性约束,即指定的字段不能插入重复值,或者是将某一记录的值更新为当前表中的已有值。
 

代码如下:

CREATE TABLE products (
        product_no integer UNIQUE,
        name text,
        price numeric
    );

CREATE TABLE products (
        product_no integer,
        name text,
        price numeric,
        UNIQUE (product_no)
    );

为表中的多个字段定义联合唯一性。
 

代码如下:

CREATE TABLE example (
        a integer,
        b integer,
        c integer,
        UNIQUE (a, c)
    );

为唯一性约束命名。
 

代码如下:

CREATE TABLE products (
        product_no integer CONSTRAINT must_be_different UNIQUE,
        name text,
        price numeric
    );

在插入数据时,空值(NULL)之间被视为不相等的数据,因此对于某一唯一性字段,可以多次插入空值。然而需要注意的是,这一规则并不是被所有数据库都遵守,因此在进行数据库移植时可能会造成一定的麻烦。
    
    5. 主键和外键:
    从技术上来讲,主键约束只是唯一约束和非空约束的组合。
 

代码如下:

CREATE TABLE products (
        product_no integer PRIMARY KEY,  --字段product_no被定义为该表的唯一主键。
        name text,
        price numeric
    );

和唯一性约束一样,主键可以同时作用于多个字段,形成联合主键:
 

代码如下:

CREATE TABLE example (
        a integer,
        b integer,
        c integer,
        PRIMARY KEY (b, c)
    );

外键约束声明一个字段(或者一组字段)的数值必须匹配另外一个表中某些行出现的数值。 我们把这个行为称做两个相关表之间的参考完整性。
 

代码如下:

CREATE TABLE orders (
        order_id integer PRIMARY KEY, --该表也可以有自己的主键。
        --该表的product_no字段为上面products表主键(product_no)的外键。
        product_no integer REFERENCES products(product_no),
        quantity integer
    );
   
    CREATE TABLE t1 (
        a integer PRIMARY KEY,
        b integer,
        c integer,
        --该外键的字段数量和被引用表中主键的数量必须保持一致。
        FOREIGN KEY (b, c) REFERENCES example (b, c)
    );

当多个表之间存在了主外键的参考性约束关系时,如果想删除被应用表(主键表)中的某行记录,由于该行记录的主键字段值可能正在被其引用表(外键表)中某条记录所关联,所以删除操作将会失败。如果想完成此操作,一个显而易见的方法是先删除引用表中和该记录关联的行,之后再删除被引用表中的该行记录。然而需要说明的是,PostgreSQL为我们提供了更为方便的方式完成此类操作。
 

代码如下:

CREATE TABLE products (
        product_no integer PRIMARY KEY,
        name text,
        price numeric
    );
   
    CREATE TABLE orders (
        order_id integer PRIMARY KEY,
        shipping_address text
    );
   
    CREATE TABLE order_items (
        product_no integer REFERENCES products ON DELETE RESTRICT, --限制选项
        order_id integer REFERENCES orders ON DELETE CASCADE, --级联删除选项
        quantity integer,
        PRIMARY KEY (product_no, order_id)
    );

限制和级联删除是两种最常见的选项。RESTRICT 禁止删除被引用的行。 NO ACTION 的意思是如果在检查约束的时候,如果还存在任何引用行,则抛出错误; 如果你不声明任何东西,那么它就是缺省的行为。(这两个选择的实际区别是,NO ACTION 允许约束检查推迟到事务的晚些时候,而 RESTRICT 不行。) CASCADE声明在删除一个被引用的行的时候,引用它的行也会被自动删除掉。 在外键字段上的动作还有两个选项: SET NULL 和 SET DEFAULT。 这样会导致在被引用行删除的时候,引用它们的字段分别设置为空或者缺省值。 请注意这些选项并不能让你逃脱被观察和约束的境地。比如,如果一个动作声明 SET DEFAULT,但是缺省值并不能满足外键,那么动作就会失败。类似ON DELETE,还有ON UPDATE 选项,它是在被引用字段修改(更新)的时候调用的。可用的动作是一样的。

二、系统字段:

PostgreSQL的每个数据表中都包含几个隐含定义的系统字段。因此,这些名字不能用于用户定义的字段名。这些系统字段的功能有些类似于Oracle中的rownum和rowid等。
    oid: 行的对象标识符(对象ID)。这个字段只有在创建表的时候使用了WITH OIDS,或者是设置了配置参数default_with_oids时出现。这个字段的类型是oid(和字段同名)。
    tableoid: 包含本行的表的OID。这个字段对那些从继承层次中选取的查询特别有用,因为如果没有它的话,我们就很难说明一行来自哪个独立的表。tableoid可以和pg_class的oid字段连接起来获取表名字。
    xmin: 插入该行版本的事务的标识(事务ID)。
    cmin: 在插入事务内部的命令标识(从零开始)。
    xmax: 删除事务的标识(事务ID),如果不是被删除的行版本,那么是零。
    cmax: 在删除事务内部的命令标识符,或者是零。
    ctid: 一个行版本在它所处的表内的物理位置。请注意,尽管ctid可以用于非常快速地定位行版本,但每次VACUUM FULL之后,一个行的ctid都会被更新或者移动。因此ctid是不能作为长期的行标识符的。   
    OID是32位的量,是在同一个集群内通用的计数器上赋值的。对于一个大型或者长时间使用的数据库,这个计数器是有可能重叠的。因此,假设OID是唯一的是非常错误的,除非你自己采取了措施来保证它们是唯一的。如果你需要标识表中的行,我们强烈建议使用序列号生成器。     
   
三、表的修改:

1. 增加字段:
 

代码如下:

ALTER TABLE products ADD COLUMN description text;

新增的字段对于表中已经存在的行而言最初将先填充所给出的缺省值(如果你没有声明DEFAULT子句,那么缺省是空值)。
    在新增字段时,可以同时给该字段指定约束。
 

代码如下:

ALTER TABLE products ADD COLUMN description text CHECK(description <> '');

    2. 删除字段:
 

代码如下:

ALTER TABLE products DROP COLUMN description;

如果该表为被引用表,该字段为被引用字段,那么上面的删除操作将会失败。如果要想在删除被引用字段的同时级联的删除其所有引用字段,可以采用下面的语法形式。
 

代码如下:

ALTER TABLE products DROP COLUMN description CASCADE;

    3. 增加约束:
 

代码如下:

ALTER TABLE products ADD CHECK(name <> '');  --增加一个表级约束
    ALTER TABLE products ADD CONSTRAINT some_name UNIQUE(product_no);--增加命名的唯一性约束。
    ALTER TABLE products ADD FOREIGN KEY(pdt_grp_id) REFERENCES pdt_grps; --增加外键约束。
    ALTER TABLE products ALTER COLUMN product_no SET NOT NULL; --增加一个非空约束。

    4. 删除约束:
 

代码如下:

ALTER TABLE products DROP CONSTRAINT some_name;

对于显示命名的约束,可以根据其名称直接删除,对于隐式自动命名的约束,可以通过psql的\d tablename来获取该约束的名字。和删除字段一样,如果你想删除有着被依赖关系地约束,你需要用CASCADE。一个例子是某个外键约束依赖被引用字段上的唯一约束或者主键约束。如:
 

代码如下:

MyTest=# \d products
         Table "public.products"
       Column     |  Type   | Modifiers
     ------------+---------+-----------
     product_no | integer |
     name          | text    |
     price           | numeric |
     Check constraints:
        "positive_price" CHECK (price > 0::numeric)

和其他约束不同的是,非空约束没有名字,因此只能通过下面的方式删除:
 

代码如下:

ALTER TABLE products ALTER COLUMN product_no DROP NOT NULL;

    5. 改变字段的缺省值:
    在为已有字段添加缺省值时,不会影响任何表中现有的数据行, 它只是为将来INSERT命令改变缺省值。
 

代码如下:

ALTER TABLE products ALTER COLUMN price SET DEFAULT 7.77;

下面为删除缺省值:
 

代码如下:

ALTER TABLE products ALTER COLUMN price DROP DEFAULT

    6. 修改字段的数据类型:
    只有在字段里现有的每个项都可以用一个隐含的类型转换转换成新的类型时才可能成功。比如当前的数据都是整型,而转换的目标类型为numeric或varchar,这样的转换一般都可以成功。与此同时,PostgreSQL还将试图把字段的缺省值(如果存在)转换成新的类型, 还有涉及该字段的任何约束。但是这些转换可能失败,或者可能生成奇怪的结果。 在修改某字段类型之前,你最好删除那些约束,然后再把自己手工修改过的添加上去。
 

代码如下:

ALTER TABLE products ALTER COLUMN price TYPE numeric(10,2);

    7. 修改字段名:
 

代码如下:

ALTER TABLE products RENAME COLUMN product_no TO product_number;

    8. 修改表名:
 

代码如下:

ALTER TABLE products RENAME TO items;

四、权限:

只有表的所有者才能修改或者删除表的权限。要赋予一个权限,我们使用GRANT命令,要撤销一个权限,使用REVOKE命令。
    需要指出的是,PUBLIC是特殊"用户"可以用于将权限赋予系统中的每一个用户。在声明权限的位置写ALL则将所有的与该对象类型相关的权限都赋予出去。
 

代码如下:

GRANT UPDATE ON table_name TO user;  --将表的更新权限赋予指定的user。
    GRANT SELECT ON table_name TO GROUP group; --将表的select权限赋予指定的组。
    REVOKE ALL ON table_name FROM PUBLIC; --将表的所有权限从Public撤销。

最初,只有对象所有者(或者超级用户)可以赋予或者撤销对象的权限。但是,我们可以赋予一个"with grant option"权限,这样就给接受权限的人以授予该权限给其它人的权限。如果授予选项后来被撤销,那么所有那些从这个接受者接受了权限的用户(直接或者通过级连的授权)都将失去该权限。

这里需要特别说明的是,该博客中的大部分案例和段落均取自于PostgreSQL中文文档,如转载本系列博客,请同样注明该出处。

(0)

相关推荐

  • PostgreSQL教程(十三):数据库管理详解

    一.概述: 数据库可以被看成是SQL对象(数据库对象)的命名集合,通常而言,每个数据库对象(表.函数等)只属于一个数据库.不过对于部分系统表而言,如pg_database,是属于整个集群的.更准确地说,数据库是模式的集合,而模式包含表.函数等SQL对象.因此完整的对象层次应该是这样的:服务器.数据库.模式.表或其他类型的对象. 在与数据库服务器建立连接时,该连接只能与一个数据库形成关联,不允许在一个会话中进行多个数据库的访问.如以postgres用户登录,该用户可以访问的缺省数据库为postgr

  • PostgreSQL教程(三):表的继承和分区表详解

    一.表的继承: 这个概念对于很多已经熟悉其他数据库编程的开发人员而言会多少有些陌生,然而它的实现方式和设计原理却是简单易懂,现在就让我们从一个简单的例子开始吧.     1. 第一个继承表:   复制代码 代码如下: CREATE TABLE cities (   --父表         name        text,         population float,         altitude     int     );     CREATE TABLE capitals (

  • PostgreSQL教程(五):函数和操作符详解(1)

    一.逻辑操作符: 常用的逻辑操作符有:AND.OR和NOT.其语义与其它编程语言中的逻辑操作符完全相同. 二.比较操作符: 下面是PostgreSQL中提供的比较操作符列表: 比较操作符可以用于所有可以比较的数据类型.所有比较操作符都是双目操作符,且返回boolean类型.除了比较操作符以外,我们还可以使用BETWEEN语句,如:     a BETWEEN x AND y 等效于 a >= x AND a <= y        a NOT BETWEEN x AND y 等效于 a <

  • PostgreSQL教程(十):性能提升技巧

    一.使用EXPLAIN: PostgreSQL为每个查询都生成一个查询规划,因为选择正确的查询路径对性能的影响是极为关键的.PostgreSQL本身已经包含了一个规划器用于寻找最优规划,我们可以通过使用EXPLAIN命令来查看规划器为每个查询生成的查询规划.     PostgreSQL中生成的查询规划是由1到n个规划节点构成的规划树,其中最底层的节点为表扫描节点,用于从数据表中返回检索出的数据行.然而,不同的扫描节点类型代表着不同的表访问模式,如:顺序扫描.索引扫描,以及位图索引扫描等.如果查

  • PostgreSQL教程(六):函数和操作符详解(2)

    六.模式匹配: PostgreSQL中提供了三种实现模式匹配的方法:SQL LIKE操作符,更近一些的SIMILAR TO操作符,和POSIX-风格正则表达式.     1. LIKE:   复制代码 代码如下: string LIKE pattern [ ESCAPE escape-character ]     string NOT LIKE pattern [ ESCAPE escape-character ] 每个pattern定义一个字串的集合.如果该string包含在pattern代

  • PostgreSQL教程(九):事物隔离介绍

    在SQL的标准中事物隔离级别分为以下四种:     1. 读未提交(Read uncommitted)     2. 读已提交(Read committed)     3. 可重复读(Repeatable read)     4. 可串行化(Serializable)     然而PostgreSQL在9.1之前的版本中只是实现了其中两种,即读已提交和可串行化,如果在实际应用中选择了另外两种,那么PostgreSQL将会自动向更严格的隔离级别调整.在PostgreSQL v9.1的版本中提供了三

  • PostgreSQL教程(十一):服务器配置

    一.服务器进程的启动和关闭: 下面是pg_ctl命令的使用方法和常用选项,需要指出的是,该命令是postgres命令的封装体,因此在使用上比直接使用postgres更加方便. 复制代码 代码如下: pg_ctl init[db] [-D DATADIR] [-s] [-o "OPTIONS"]     pg_ctl start     [-w] [-t SECS] [-D DATADIR] [-s] [-l FILENAME] [-o "OPTIONS"]    

  • PostgreSQL教程(二):模式Schema详解

    一个数据库包含一个或多个命名的模式,模式又包含表.模式还包含其它命名的对象,包括数据类型.函数,以及操作符.同一个对象名可以在不同的模式里使用而不会导致冲突: 比如,schema1和myschema都可以包含叫做mytable的表.和数据库不同,模式不是严格分离的:一个用户可以访问他所连接的数据库中的任意模式中的对象,只要他有权限. 我们需要模式有以下几个主要原因: 1). 允许多个用户使用一个数据库而不会干扰其它用户.     2). 把数据库对象组织成逻辑组,让它们更便于管理.     3)

  • PostgreSQL教程(十二):角色和权限管理介绍

    PostgreSQL是通过角色来管理数据库访问权限的,我们可以将一个角色看成是一个数据库用户,或者一组数据库用户.角色可以拥有数据库对象,如表.索引,也可以把这些对象上的权限赋予其它角色,以控制哪些用户对哪些对象拥有哪些权限.     一.数据库角色: 1. 创建角色:   复制代码 代码如下: CREATE ROLE role_name; 2. 删除角色:   复制代码 代码如下: DROP ROLE role_name; 3. 查询角色: 检查系统表pg_role,如:   复制代码 代码如

  • PostgreSQL教程(七):函数和操作符详解(3)

    九.序列操作函数: 序列对象(也叫序列生成器)都是用CREATE SEQUENCE创建的特殊的单行表.一个序列对象通常用于为行或者表生成唯一的标识符.下面序列函数,为我们从序列对象中获取最新的序列值提供了简单和并发读取安全的方法. 函数 返回类型 描述 nextval(regclass) bigint 递增序列对象到它的下一个数值并且返回该值.这个动作是自动完成的.即使多个会话并发运行nextval,每个进程也会安全地收到一个唯一的序列值. currval(regclass) bigint 在当

  • PostgreSQL教程(四):数据类型详解

    一.数值类型: 下面是PostgreSQL所支持的数值类型的列表和简单说明: 1. 整数类型: 类型smallint.integer和bigint存储各种范围的全部是数字的数,也就是没有小数部分的数字.试图存储超出范围以外的数值将导致一个错误.常用的类型是integer,因为它提供了在范围.存储空间和性能之间的最佳平衡.一般只有在磁盘空间紧张的时候才使用smallint.而只有在integer的范围不够的时候才使用bigint,因为前者(integer)绝对快得多.     2. 任意精度数值:

  • PostgreSQL教程(十四):数据库维护

    一.恢复磁盘空间: 在PostgreSQL中,使用delete和update语句删除或更新的数据行并没有被实际删除,而只是在旧版本数据行的物理地址上将该行的状态置为已删除或已过期.因此当数据表中的数据变化极为频繁时,那么在一段时间之后该表所占用的空间将会变得很大,然而数据量却可能变化不大.要解决该问题,需要定期对数据变化频繁的数据表执行VACUUM操作. VACUUM命令存在两种形式,VACUUM和VACUUM FULL,它们之间的区别见如下表格:   无VACUUM VACUUM VACUUM

  • PostgreSQL教程(八):索引详解

    一.索引的类型: PostgreSQL提供了多 种索引类型:B-Tree.Hash.GiST和GIN,由于它们使用了不同的算法,因此每种索引类型都有其适合的查询类型,缺省时,CREATE INDEX命令将创建B-Tree索引.         1. B-Tree:   复制代码 代码如下: CREATE TABLE test1 (         id integer,         content varchar     );     CREATE INDEX test1_id_index

随机推荐