PostgreSQL 数据类型手册【serial, timestamp,text....】

一、数值类型:

    下面是PostgreSQL所支持的数值类型的列表和简单说明:

名字存储空间描述范围
smallint2 字节小范围整数-32768 到 +32767
integer4 字节常用的整数-2147483648 到 +2147483647
bigint8 字节大范围的整数-9223372036854775808 到 9223372036854775807
decimal变长用户声明精度,精确无限制
numeric变长用户声明精度,精确无限制
real4 字节变精度,不精确6 位十进制数字精度
double8 字节变精度,不精确15 位十进制数字精度
serial4 字节自增整数1 到 +2147483647
bigserial8 字节大范围的自增整数1 到 9223372036854775807

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

    2. 任意精度数值:
    类型numeric可以存储最多1000位精度的数字并且准确地进行计算。因此非常适合用于货币金额和其它要求计算准确的数量。不过,numeric类型上的算术运算比整数类型或者浮点数类型要慢很多。
    numeric字段的最大精度和最大比例都是可以配置的。要声明一个类型为numeric的字段,你可以用下面的语法:
    NUMERIC(precision,scale)
    比如数字23.5141的精度为6,而刻度为4。
    在目前的PostgreSQL版本中,decimalnumeric是等效的。
   
    3. 浮点数类型:
    数据类型real和double是不准确的、牺牲精度的数字类型。不准确意味着一些数值不能准确地转换成内部格式并且是以近似的形式存储的,因此存储后再把数据打印出来可能显示一些缺失。
    
   4. Serial(序号)类型:
    serial和bigserial类型不是真正的类型,只是为在表中设置唯一标识做的概念上的便利。
    CREATE TABLE tablename (
        colname SERIAL
    );
    等价于
    CREATE SEQUENCE tablename_colname_seq;
    CREATE TABLE tablename(
        colname integer DEFAULT nextval('tablename_colname_seq') NOT NULL
    );
    这样,我们就创建了一个整数字段并且把它的缺省数值安排为从一个序列发生器取值。应用了一个NOT NULL约束以确保空值不会被插入。在大多数情况下你可能还希望附加一个UNIQUE或者PRIMARY KEY约束避免意外地插入重复的数值,但这个不是自动发生的。因此,如果你希望一个序列字段有一个唯一约束或者一个主键,那么你现在必须声明,就像其它数据类型一样。
    还需要另外说明的是,一个serial类型创建的序列在其所属字段被删除时,该序列也将被自动删除,但是其它情况下是不会被删除的。因此,如果你想用同一个序列发生器同时给几个字段提供数据,那么就应该以独立对象的方式创建该序列发生器。

二、字符类型:

    下面是PostgreSQL所支持的字符类型的列表和简单说明:

名字描述
varchar(n)变长,有长度限制
char(n)定长,不足补空白
text变长,无长度限制

    SQL 定义了两种基本的字符类型,varchar(n)和char(n),这里的n是一个正整数。两种类型都可以存储最多n个字符长的字串,试图存储更长的字串到这些类型的字段里会产生一个错误,除非超出长度的字符都是空白,这种情况下该字串将被截断为最大长度。如果没有长度声明,char等于char(1),而varchar则可以接受任何长度的字串。
    MyTest=> CREATE TABLE testtable(first_col varchar(2));
    CREATE TABLE
    MyTest=> INSERT INTO testtable VALUES('333');   --插入字符串的长度,超过其字段定义的长度,因此报错。
    ERROR:  value too long for type character varying(2)
    --插入字符串中,超出字段定义长度的部分是空格,因此可以插入,但是空白符被截断。
    MyTest=> INSERT INTO testtable VALUES('33 ');   
    INSERT 0 1
    MyTest=> SELECT * FROM testtable;
     first_col
    -----------
     33
    (1 row)
    这里需要注意的是,如果是将数值转换成char(n)或者varchar(n),那么超长的数值将被截断成n个字符,而不会抛出错误。
    MyTest=> select 1234::varchar(2);
     varchar
    ---------
     12
    (1 row)
    最后需要提示的是,这三种类型之间没有性能差别,只不过是在使用char类型时增加了存储尺寸。虽然在某些其它的数据库系统里,char(n)有一定的性能优势,但在PostgreSQL里没有。在大多数情况下,应该使用text或者varchar。
   
三、日期/时间类型:

    下面是PostgreSQL所支持的日期/时间类型的列表和简单说明:

名字存储空间描述最低值最高值分辨率
timestamp[无时区]8字节包括日期和时间4713 BC5874897AD1毫秒/14位
timestamp[含时区]8字节日期和时间,带时区4713 BC5874897AD1毫秒/14位
interval12字节时间间隔-178000000年178000000年1毫秒/14位
date4字节只用于日期4713 BC32767AD1天
time[无时区]8字节只用于一日内时间00:00:0024:00:001毫秒/14位


    1. 日期/时间输入:
    任何日期或者时间的文本输入均需要由单引号包围,就象一个文本字符串一样。
    1). 日期:
    以下为合法的日期格式列表:

例子描述
January 8, 1999在任何datestyle输入模式下都无歧义
1999-01-08ISO-8601格式,任何方式下都是1999年1月8号,(建议格式)
1/8/1999歧义,在MDY下是1月8号;在 DMY模式下读做8月1日
1/18/1999在MDY模式下读做1月18日,其它模式下被拒绝
01/02/03MDY模式下的2003年1月2日;DMY模式下的2003年2月1日;YMD 模式下的2001年2月3日
1999-Jan-08任何模式下都是1月8日
Jan-08-1999任何模式下都是1月8日
08-Jan-1999任何模式下都是1月8日
99-Jan-08在YMD模式下是1月8日,否则错误
08-Jan-991月8日,除了在YMD模式下是错误的之外
Jan-08-991月8日,除了在YMD模式下是错误的之外
19990108ISO-8601; 任何模式下都是1999年1月8日
990108ISO-8601; 任何模式下都是1999年1月8日

    2). 时间:
    以下为合法的时间格式列表:

例子描述
04:05:06.789ISO 8601
04:05:06ISO 8601
04:05ISO 8601
040506ISO 8601
04:05 AM与04:05一样;AM不影响数值
04:05 PM与16:05一样;输入小时数必须 <= 12
04:05:06.789-8ISO 8601
04:05:06-08:00ISO 8601
04:05-08:00ISO 8601
040506-08ISO 8601

    3). 时间戳:
    时间戳类型的有效输入由一个日期和时间的联接组成,后面跟着一个可选的时区。因此,1999-01-08 04:05:06和1999-01-08 04:05:06 -8:00都是有效的数值。
  
   2. 示例:
    1). 在插入数据之前先查看datestyle系统变量的值:
    MyTest=> show datestyle;
     DateStyle
    -----------
     ISO, YMD
    (1 row)
    2). 创建包含日期、时间和时间戳类型的示例表:
    MyTest=> CREATE TABLE testtable (id integer, date_col date, time_col time, timestamp_col timestamp);
    CREATE TABLE
    3). 插入数据:
    MyTest=> INSERT INTO testtable(id,date_col) VALUES(1, DATE'01/02/03'); --datestyle为YMD
    INSERT 0 1
    MyTest=> SELECT id, date_col FROM testtable;
     id   |  date_col
    ----+------------
      1  | 2001-02-03
    (1 row)
    
    MyTest=> set datestyle = MDY;
    SET
    MyTest=> INSERT INTO testtable(id,date_col) VALUES(2, DATE'01/02/03'); --datestyle为MDY
    INSERT 0 1
    MyTest=> SELECT id,date_col FROM testtable;
     id   |  date_col
    ----+------------
      1  | 2001-02-03
      2  | 2003-01-02 

    MyTest=> INSERT INTO testtable(id,time_col) VALUES(3, TIME'10:20:00'); --插入时间。
    INSERT 0 1
    MyTest=> SELECT id,time_col FROM testtable WHERE time_col IS NOT NULL;
     id   | time_col
    ----+----------
      3   | 10:20:00
    (1 row)

    MyTest=> INSERT INTO testtable(id,timestamp_col) VALUES(4, DATE'01/02/03');
    INSERT 0 1
    MyTest=> INSERT INTO testtable(id,timestamp_col) VALUES(5, TIMESTAMP'01/02/03 10:20:00');
    INSERT 0 1
    MyTest=> SELECT id,timestamp_col FROM testtable WHERE timestamp_col IS NOT NULL;
     id   |    timestamp_col
    ----+---------------------
      4  | 2003-01-02 00:00:00
      5  | 2003-01-02 10:20:00
    (2 rows)

四、布尔类型:

    PostgreSQL支持标准的SQL boolean数据类型。boolean只能有两个状态之一:真(True)或 假(False)。该类型占用1个字节。
    "真"值的有效文本值是:
    TRUE
    't'
    'true'
    'y'
    'yes'
    '1'
    而对于"假"而言,你可以使用下面这些:
    FALSE
    'f'
    'false'
    'n'
    'no'
    '0'
  见如下使用方式:
    MyTest=> CREATE TABLE testtable (a boolean, b text);
    CREATE TABLE
    MyTest=> INSERT INTO testtable VALUES(TRUE, 'sic est');
    INSERT 0 1
    MyTest=> INSERT INTO testtable VALUES(FALSE, 'non est');
    INSERT 0 1
    MyTest=> SELECT * FROM testtable;
     a  |    b
    ---+---------
     t  | sic est
     f  | non est
    (2 rows)   
    MyTest=> SELECT * FROM testtable WHERE a;
     a  |    b
    ---+---------
     t  | sic est
    (1 row)   
    MyTest=> SELECT * FROM testtable WHERE a = true;
     a  |    b
    ---+---------
     t  | sic est
    (1 row)
   
五、位串类型:

    位串就是一串1和0的字串。它们可以用于存储和视觉化位掩码。我们有两种类型的SQL位类型:bit(n)和bit varying(n); 这里的n是一个正整数。bit类型的数据必须准确匹配长度n; 试图存储短些或者长一些的数据都是错误的。类型bit varying数据是最长n的变长类型;更长的串会被拒绝。写一个没有长度的bit等效于bit(1),没有长度的bit varying相当于没有长度限制。
    针对该类型,最后需要提醒的是,如果我们明确地把一个位串值转换成bit(n),那么它的右边将被截断或者在右边补齐零,直到刚好n位,而不会抛出任何错误。类似地,如果我们明确地把一个位串数值转换成bit varying(n),如果它超过n位,那么它的右边将被截断。 见如下具体使用方式:    
    MyTest=> CREATE TABLE testtable (a bit(3), b bit varying(5));
    CREATE TABLE
    MyTest=> INSERT INTO testtable VALUES (B'101', B'00');
    INSERT 0 1
    MyTest=> INSERT INTO testtable VALUES (B'10', B'101');
    ERROR:  bit string length 2 does not match type bit(3)
    MyTest=> INSERT INTO testtable VALUES (B'10'::bit(3),B'101');
    INSERT 0 1
    MyTest=> SELECT * FROM testtable;
      a  |  b
    -----+-----
     101 | 00
     100 | 101
    (2 rows)
    MyTest=> SELECT B'11'::bit(3);
     bit
    -----
     110
    (1 row)


六、数组:

    1. 数组类型声明:
    1). 创建字段含有数组类型的表。
    CREATE TABLE sal_emp (
        name            text,
        pay_by_quarter  integer[] --还可以定义为integer[4]integer ARRAY[4]
    );
    2). 插入数组数据:
    MyTest=# INSERT INTO sal_emp VALUES ('Bill', '{11000, 12000, 13000, 14000}');
    INSERT 0 1
    MyTest=# INSERT INTO sal_emp VALUES ('Carol',ARRAY[21000, 22000, 23000, 24000]);
    INSERT 0 1
    MyTest=# SELECT * FROM sal_emp;
     name  |      pay_by_quarter
    --------+---------------------------
     Bill     | {11000,12000,13000,14000}
     Carol  | {21000,22000,23000,24000}
    (2 rows)    

    2. 访问数组:
    和其他语言一样,PostgreSQL中数组也是通过下标数字(写在方括弧内)的方式进行访问,只是PostgreSQL中数组元素的下标是从1开始n结束。
    MyTest=# SELECT pay_by_quarter[3] FROM sal_emp;
     pay_by_quarter
    ----------------
              13000
              23000
    (2 rows)
    MyTest=# SELECT name FROM sal_emp WHERE pay_by_quarter[1] <> pay_by_quarter[2];
     name
    ------
     Bill
     Carol
    (2 rows)
    PostgreSQL中还提供了访问数组范围的功能,即ARRAY[脚标下界:脚标上界]。
    MyTest=# SELECT name,pay_by_quarter[1:3] FROM sal_emp;
     name  |   pay_by_quarter
    --------+---------------------
     Bill     | {11000,12000,13000}
     Carol  | {21000,22000,23000}
    (2 rows)
    
    3. 修改数组:
    1). 代替全部数组值:
    --UPDATE sal_emp SET pay_by_quarter = ARRAY[25000,25000,27000,27000] WHERE name = 'Carol'; 也可以。
    MyTest=# UPDATE sal_emp SET pay_by_quarter = '{31000,32000,33000,34000}' WHERE name = 'Carol';
    UPDATE 1
    MyTest=# SELECT * FROM sal_emp;
     name  |      pay_by_quarter
    --------+---------------------------
     Bill     | {11000,12000,13000,14000}
     Carol  | {31000,32000,33000,34000}
    (2 rows)
    2). 更新数组中某一元素:
    MyTest=# UPDATE sal_emp SET pay_by_quarter[4] = 15000 WHERE name = 'Bill';
    UPDATE 1
    MyTest=# SELECT * FROM sal_emp;
     name  |      pay_by_quarter
    --------+---------------------------
     Carol  | {31000,32000,33000,34000}
     Bill     | {11000,12000,13000,15000}
    (2 rows)
    3). 更新数组某一范围的元素:
    MyTest=# UPDATE sal_emp SET pay_by_quarter[1:2] = '{37000,37000}' WHERE name = 'Carol';
    UPDATE 1
    MyTest=# SELECT * FROM sal_emp;
     name  |      pay_by_quarter
    --------+---------------------------
     Bill     | {11000,12000,13000,15000}
     Carol  | {37000,37000,33000,34000}
    (2 rows)
    4). 直接赋值扩大数组:
    MyTest=# UPDATE sal_emp SET pay_by_quarter[5] = 45000 WHERE name = 'Bill';
    UPDATE 1
    MyTest=# SELECT * FROM sal_emp;
     name  |         pay_by_quarter
    --------+---------------------------------
     Carol  | {37000,37000,33000,34000}
     Bill     | {11000,12000,13000,15000,45000}
    (2 rows)

    4. 在数组中检索:
    1). 最简单直接的方法:
    SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR
                            pay_by_quarter[2] = 10000 OR
                            pay_by_quarter[3] = 10000 OR
                            pay_by_quarter[4] = 10000; 
   
    2). 更加有效的方法:
    SELECT * FROM sal_emp WHERE 10000 = ANY (pay_by_quarter);--数组元素中有任何一个等于10000,where条件将成立。
    SELECT * FROM sal_emp WHERE 10000 = ALL (pay_by_quarter);--只有当数组中所有的元素都等于10000时,where条件才成立。

七、复合类型:

    PostgreSQL中复合类型有些类似于C语言中的结构体,也可以被视为Oracle中的记录类型,但是还是感觉复合类型这个命名比较贴切。它实际上只是一个字段名和它们的数据类型的列表。PostgreSQL允许像简单数据类型那样使用复合类型。比如,表字段可以声明为一个复合类型。
    1. 声明复合类型:
    下面是两个简单的声明示例:
    CREATE TYPE complex AS (
        r double,
        i double
    );  
    CREATE TYPE inventory_item AS (
        name           text,
        supplier_id   integer,
        price            numeric
    );
    和声明一个数据表相比,声明类型时需要加AS关键字,同时在声明TYPE时不能定义任何约束。下面我们看一下如何在表中指定复合类型的字段,如:
    CREATE TABLE on_hand (
        item      inventory_item,
        count    integer
    );
    最后需要指出的是,在创建表的时候,PostgreSQL也会自动创建一个与该表对应的复合类型,名字与表字相同,即表示该表的复合类型。
   
    2. 复合类型值输入:
    我们可以使用文本常量的方式表示复合类型值,即在圆括号里包围字段值并且用逗号分隔它们。你也可以将任何字段值用双引号括起,如果值本身包含逗号或者圆括号,那么就用双引号括起,对于上面的inventory_item复合类型的输入如下:
    '("fuzzy dice",42,1.99)'
    如果希望类型中的某个字段为NULL,只需在其对应的位置不予输入即可,如下面的输入中price字段的值为NULL,
    '("fuzzy dice",42,)'
    如果只是需要一个空字串,而非NULL,写一对双引号,如:
    '("",42,)'
    在更多的场合中PostgreSQL推荐使用ROW表达式来构建复合类型值,使用该种方式相对简单,无需考虑更多标识字符问题,如:
    ROW('fuzzy dice', 42, 1.99)
    ROW('', 42, NULL)
    注:对于ROW表达式,如果里面的字段数量超过1个,那么关键字ROW就可以省略,因此以上形式可以简化为:
    ('fuzzy dice', 42, 1.99)
    ('', 42, NULL)
   
    3. 访问复合类型:
    访问复合类型中的字段和访问数据表中的字段在形式上极为相似,只是为了对二者加以区分,PostgreSQL设定在访问复合类型中的字段时,类型部分需要用圆括号括起,以避免混淆,如:
    SELECT (item).name FROM on_hand WHERE (item).price > 9.99;
    如果在查询中也需要用到表名,那么表名和类型名都需要被圆括号括起,如:
    SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9.99;
   
    4. 修改复合类型:
    见如下几个示例:
    --直接插入复合类型的数据,这里是通过ROW表达式来完成的。
    INSERT INTO on_hand(item) VALUES(ROW("fuzzy dice",42,1.99));
    --在更新操作中,也是可以通过ROW表达式来完成。
    UPDATE on_hand SET item = ROW("fuzzy dice",42,1.99) WHERE count = 0;
    --在更新复合类型中的一个字段时,我们不能在SET后面出现的字段名周围加圆括号,
    --但是在等号右边的表达式里引用同一个字段时却需要圆括号。

    UPDATE on_hand SET item.price = (item).price + 1 WHERE count = 0;
    --可以在插入中,直接插入复合类型中字段。
    INSERT INTO on_hand (item.supplier_id, item.price) VALUES(100, 2.2);
 

    该篇博客是对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"权限,这样就给接受权限的人以授予该权限给其它人的权限。如果授予选项后来被撤销,那么所有那些从这个接受者接受了权限的用户(直接或者通过级连的授权)都将失去该权限。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值