草庐IT

PostgreSQL11 | pgsql建表、改表与删表

红星编程实验室 2023-12-22 原文

上一篇文章

PostgreSQL11 | pgadmin4基本使用http://t.csdn.cn/IFZpx已经讲解了最简单的pgadmin的数据库创建、外键等可视化的操作,以及对应的pgsql语句

这一篇文章将讲解基础的pgsql语句

建表、改表与删表

目录

建表、改表与删表

创建数据表

单字段主键

多字段联合主键

外键约束

非空约束(Not Null Constraint)

唯一性约束(Unique Constraint)

默认约束(Default Constraint)

修改数据表

修改表名

修改字段的数据类型

修改字段名

添加字段

删除字段

删除表的外键约束

删除数据表

删除没有关联的表

IF EXISTS用法

删除被其他表关联的主表

postgresql11版本的新特性


创建数据表

创建数据表的关键字是CREATE

在为表名起名时,不区分大小写、不能起sql语句关键字(例如:DROP,CREATE等)

在为数据表中每一个列起名时,每个列之间使用英文逗号隔开

CREATE TABLE <表名>
(
    字段名1 数据类型 [列级别约束条件][默认值],
    字段名2 数据类型 [列级别约束条件][默认值],
    .....

    [表级别约束条件]
(

例:在pgtest数据库中创建员工表tb_emp1

字段名称数据类型备注
idINT员工编号
nameVARCHAR(25)员工名称
deptidINT所在部门编号
salaryFLOAT工资

CREATE TABLE tb_emp1
(
 	id INT,
	name VARCHAR(25),
	deptid INT,
	salary FLOAT
);

单字段主键

还可以在创建数据库表的时候对某一属性作主键约束,使得每条数据该属性的值表内唯一且不能为空,这与唯一约束不同。

创建一个数据表tb_emp2,id作为主键

CREATE TABLE tb_emp2
(
	id	INT PRIMARY KEY,
	name VARCHAR(25),
	deptid INT,
	salary FLOAT
);

 还可以在字段全部定义完,在最后加上主键指定

CREATE TABLE tb_emp3
(
	id INT,
	name VARCHAR(25),
	deptid INT,
	salary FLOAT,
	PRIMARY KEY(id)
);

多字段联合主键

当我想设计一个表中,name字段和deptid字段的值同步唯一的时候,就可以一次设置两个字段作为联合主键

create table tb_emp4
(
	name varchar(25),
	deptid int,
	salary float,
	primary key(name,deptid)
);

我们可以先存入一条数据

insert into tb_emp4 values ('小明',1,2000);

 通过pgadmin查表按钮之间查出表以便于我们快速输入测试数据看效果

 然后我们直接插入一条新数据,名字重复但部门id不重复

提示我们存储是成功的,反过来也是一样的,但如果当我们两个值全部与已存数据重复之后

 就会报错,所以当开发过程中有这种两个值做主键的需求时就会用到联合唯一

外键约束

用途:外键用来在两张表之间的数据建立链接,可以是一列或者多列。

定义:表中的一个字段,可以不是本表的主键,但必须是应对的另一表的主键。

对于外键来说,两张链接起来的表是有关联关系的

主表(父表):对于两个具有关联关系的表而言,相关联的字段中主键所在的哪个表就是主键。

从表(子表):对于两个具有关联关系的表而言,相关联字段中外键所在的哪个表就是从表。

对于图形化工具pgadmin来说,只需要图形化操作即可,这一部分为了节省篇幅,请读者购买原教材(《postgresql11从入门到精通》清华大学出版社)对照第49页操作,我这里只总结sql语句操作。

先创建一个主表

create table tb_dept1
(
	id int primary key,
	name varchar(22) not null,
	location varchar(50)
);
字段名称数据类型备注
idint部门id
namevarchar(22)部门名称
locationvarchar(50)部门位置

之后再创建从表,从表中需要员工id、员工姓名、薪资之外,还有用于存储外键id的部门id字段

这个部门id字段要与主表中的主键(id)关联依赖,在建表时从表的建表sql如下

create table tb_emp5
(
	id int primary key,
	name varchar(25),
	deptid int,
	salary float,
	constraint fk_emp_dept1 foreign key(deptid) references tb_dept1(id)
);

关联公式解析:

constraint fk_emp_dept1 foreign key(deptid) references tb_dept1(id)
   约束      <约束名>       外键(字段名)      参照(依赖)  <主表表名>(主表主键字段)
                     (从表中存储主表id的字段)          

非空约束(Not Null Constraint)

用途:如果一张表中没有指定任何一个字段非空约束的话,有可能在存储的时候存储大量的全空的废数据,我们需要对表接收的数据进行约束,每条数据至少有一个值是存在的,这样存储的数据才有意义,所以

定义:被指定的字段的值不能为空

创建一个新表tb_emp6并指定员工的名称不能为空

create table tb_emp6
(
	id int primary key,
	name varchar(25) not null,
	deptid int,
	salary float,
	constraint fk_emp_dept2 foreign key(deptid) references tb_dept1(id)
);

当我们再次存储数据的时候,如果不给名字的值就会报错

唯一性约束(Unique Constraint)

定义:唯一性约束要求添加该约束的列字段的值唯一,允许为空,但只能出现一个空值。唯一性约束可以确保一列或多列不出现重复值。

唯一性约束(unique)与主键(primary key)的区别:一个表中可以有多个字段声明为unique,但只能由一个primary key声明;声明为primary key的列不允许有空值,但是声明为unique的字段允许有空值(NULL)的存在。

可视化操作在原教材书中第51页图片指导。

创建一个新的部门表tb_dept2并指定部门名称为唯一约束

有两种定义方式:

第一种,定义完列直接指定

create table tb_dept2
(
	id int primary key,
	name varchar(22) unique,
	location varchar(50)
);

<字段名> 数据类型 unique

第二种,定义完所有列后指定唯一约束

create table tb_dept3
(
	id int primary key,
	name varchar(22),
	location varchar(50),
	constraint sth unique(name)
);

constraint <约束名> unique(<字段名>)

默认约束(Default Constraint)

定义:默认约束指定某列的默认值

被指定默认约束的列,在插入或修改数据的时候,如果新结果没有传入用户的值,则会默认保存建表时指定的默认值,这个默认值可以通过修改数据表来修改默认值

定义一个新表tb_emp7,指定员工的部门编号默认为1111,为了方便展示这里与原教材不同,不再做主从表的关联

create table tb_emp7
(
	id int primary key,
	name varchar(25) not null,
	deptid int default 1111,
	salary float
);

创建表后插入一条只传id和name值的数据,其他两个值为空

insert into tb_emp7(id,name) values (1,'小明');

 可以看到虽然并没有传入deptid的值,但由于设置了默认约束,所以pgsql自动存储的预设的默认值。

修改数据表

修改数据表是指修改数据库中已经存在的数据库表的表结构。

常用的修改表的操作有:修改表名、修改字段数据类型或字段名、增加和删除字段、修改字段的排列位置、更改表的存储引擎、删除表的外键约束等。

修改表名

alter table <旧表名> rename to <新表名>;

例如我希望把前面创建的表tb_dept3修改成

alter table tb_dept3 rename to tb_department3;

 

修改字段的数据类型

对于创建好的字段,也可以修改它的数据类型。

alter table <表名> alter column <字段名> type <数据类型>;

例如,将表tb_dept1中的name字段的数据类型varchar(22)修改为text类型

alter table tb_dept1 alter column name type text;

但当表中该字段已经存有数据的时候,不可轻易修改数据类型。

举一个便于理解的例子。

我们可以对表中插入一条数据

insert into tb_dept1(id,name,location) values (1,'小王','shanghai');

当前name类型是text类型的,如果我们尝试修改回varchar(22),是没有问题的,因为值是在新类型的允许范围内的。

alter table tb_dept1 alter column name type varchar(22);

我们存储的数据是在varchar(22)的范围内的数据,但假如对已存数据不了解,贸然修改类型

返回上一状态,我们将名字修改成一串话

 再把数据类型修改为varchar(4)

alter table tb_dept1 alter column name type varchar(4);

对于varchar(4) 来说,已存在的值是超过范围的。

所以,不是不允许有值条件修改数据类型,而是需要对数据类型范围和已存值数据都了解的前提下修改,或者将数据清空后再修改字段的类型。有一些软件框架为了安全开发甚至直接不允许有值改类型的操作,所以最好是清理数据后改类型。

修改字段名

使用图形工具修改很简单,但下面讲如何通过sql来修改

alter table <表名> rename <待改名字段> to <新字段名><新数据类型,不写默认原类型>;

如果我想把表tb_dept1中的location修改字段名为loc,但数据类型不变

alter table tb_dept1 rename location to loc;

添加字段

表中的字段增减是正常的,现展示已存表增加字段的方法

alter table <表名> add column <新字段名,必填> <数据类型,必填>;

1.添加无完整性约束条件的字段

假如,现在对表tb_dept1增加新字段,一个没有完整性约束的int类型字段managerid(部门经理编号),sql如下

alter table tb_dept1 add column managerid int;

 2.添加有完整性约束条件的字段

在增加一个完整性约束条件的字段时,分为两个情况,一个是有默认值的一个是无默认值的。

假设再增加一个完整性约束的字段column1的话,sql如下

alter table tb_dept1 add column column1 varchar(12) not null default 'foo';

 这里需注意,我所展示的sql与原教材上的sql不同,完整性约束要求的字段在定义时有默认值,这个默认值在当前表中已有数据,但我们后加了新的完整性约束字段的话就会出现以下报错

 若我们不希望后续添加的完整性约束字段有默认值,就必须先将表中数据清理后再增加这一字段

delete from tb_dept1;

然后再运行这一sql

alter table tb_dept1 add column column2 varchar(12) not null;

删除字段

将表中的无用字段进行删除

alter table <表名> drop <字段名>;

例如将上面增加的字段managerid删掉,sql如下

alter table tb_dept1 drop managerid;

删除表的外键约束

对于数据库中定义的外键,如果不再需要,可以将其删除。外键一旦删除,就会解除主从表的关联关系。

alter table <表名> drop constraint <外键名>;

先新建一个新表tb_emp9,然后在该表以deptid字段创建一个外键关联tb_dept1表中的主键id

create table tb_emp9
(
	id int primary key,
	name varchar(25),
	deptid int,
	salary float,
	constraint fk_emp_dept foreign key(deptid) references tb_dept1(id)
);

 可以看到约束已经随表创建了,我们再对这一外键删除

alter table tb_emp9 drop constraint fk_emp_dept;

删除数据表

删除数据表是指将数据库中已经存在的表从数据库中删除。

删除没有关联的表

drop table <表名>;

例如,我要删除tb_emp2表

drop table tb_emp2;

IF EXISTS用法

在删除表时也有删除了一个不存在的表的时候,对于错误的sql,pgsql有一个提示警告而并非中断运行报错的方法

用法:

drop table if exists <表名>;

例如,同样的我们都是删除一个不存在的表xiaoming,使用前后

drop table xiaoming;

drop table if exists xiaoming;

删除被其他表关联的主表

在数据表中存在关联的主从表,如果直接删除主表的话,就会提示报错,这是因为主表的消失会破坏子表与主表的关联关系,如果必须删除主表则必须先删除所有有关联的子表外键之后再删除主表。

例如如下例子:

先创建一个表tb_dept3

create table tb_dept3
(
	id int primary key,
	name varchar(22),
	location varchar(50)
);

再创建子表

create table tb_emp10
(
	id int primary key,
	name varchar(25),
	deptid int,
	salary float,
	constraint fk_emp_dept foreign key(deptid) references tb_dept3(id)
);

如果这时贸然去删除主表则会报错

 就是因为子表外键导致的,所以要想要删掉主表就必须先删除子表的外键

alter table tb_emp10 drop constraint fk_emp_dept;

 然后再删除主表即可

drop table tb_dept3;

postgresql11版本的新特性

有关postgresql11版本的新特性——新增带默认值的字段不再重写数据表的相关内容请通过原教材《postgresql11从入门到精通》(清华大学出版社)第63页开始了解,属于11版本的新增功能,为了文章有普适性该部分作为自由了解范围,感谢理解。

作者的话(Alvin):

以上是有关原书第四章的总结与拓展,为提问与解答可以帮助更多人,本博客模拟GitHub的issue方案,所以私信已关,有问题请在评论区直接指正与提问,允许转发、复制或引用本文章,必须遵守开源法则注释来源与作者,感谢您的阅读。

有关PostgreSQL11 | pgsql建表、改表与删表的更多相关文章

  1. ruby - 安装libv8(3.11.8.13)出错,Bundler无法继续 - 2

    运行bundleinstall后出现此错误:Gem::Package::FormatError:nometadatafoundin/Users/jeanosorio/.rvm/gems/ruby-1.9.3-p286/cache/libv8-3.11.8.13-x86_64-darwin-12.gemAnerroroccurredwhileinstallinglibv8(3.11.8.13),andBundlercannotcontinue.Makesurethat`geminstalllibv8-v'3.11.8.13'`succeedsbeforebundling.我试试gemin

  2. ruby-on-rails - 如何让 datamapper 与 postgresql 数据库一起工作? - 2

    我已经找到了几个使用datamapper的示例,并且能够让它们正常工作。不过,所有这些示例都是针对sqlite数据库的。我正在尝试将数据映射器与postgresql一起使用。我将datamapper中的调用从sqlite3更改为postgres,并且我已经安装了dm-postgres-adapter。但它仍然不起作用。我还需要做什么? 最佳答案 与SQLite不同,PostgreSQL不将数据库存储在单个文件中。在你拥有createdyourdatabase之后,尝试这样的事情:DataMapper.setup:default,{:

  3. ruby - ri 有空文件 – Ubuntu 11.10, Ruby 1.9 - 2

    我正在运行Ubuntu11.10并像这样安装Ruby1.9:$sudoapt-getinstallruby1.9rubygems一切都运行良好,但ri似乎有空文档。ri告诉我文档是空的,我必须安装它们。我执行此操作是因为我读到它会有所帮助:$rdoc--all--ri现在,当我尝试打开任何文档时:$riArrayNothingknownaboutArray我搜索的其他所有内容都是一样的。 最佳答案 这个呢?apt-getinstallri1.8编辑或者试试这个:(非rvm)geminstallrdocrdoc-datardoc-da

  4. sql - 在 Rails Console for PostgreSQL 的表中显示数据 - 2

    我找到了这样的东西:Rails:Howtolistdatabasetables/objectsusingtheRailsconsole?这一行没问题:ActiveRecord::Base.connection.tables并返回所有表但是ActiveRecord::Base.connection.table_structure("users")产生错误:ActiveRecord::Base.connection.table_structure("projects")我认为table_structure不是Postgres方法。如何列出Postgres数据库的Rails控制台中表中的所有

  5. ruby-on-rails - Rails 迁移中的 PostgreSQL 点类型 - 2

    我想使用PostgreSQL中的point类型。我已经完成了:railsgmodelTestpoint:point最终的迁移是:classCreateTests当我运行时:rakedb:migrate结果是:==CreateTests:migrating====================================================--create_table(:tests)rakeaborted!Anerrorhasoccurred,thisandalllatermigrationscanceled:undefinedmethod`point'for#/hom

  6. ruby-on-rails - Ruby on Rails 单表继承(STI)和单元测试问题(使用 PostgreSQL) - 2

    我正在使用带有单个“帐户”表的STI模型来保存用户和技术人员的信息(即用户...8)错误:test_the_truth(用户测试):ActiveRecord::StatementInvalid:PGError:ERROR:关系“技术人员”不存在:从“技术人员”中删除...从本质上讲,标准框架不承认Technicians和Users表(或PostgreSQL称它们为“关系”)不存在,事实上,应该别名为Accounts。有什么想法吗?我对RoR比较陌生,不知道如何解决这个问题而又不完全删除STI。 最佳答案 原来问题是由于存在:./te

  7. ruby - rails 3.2.2(或 3.2.1)+ Postgresql 9.1.3 + Ubuntu 11.10 连接错误 - 2

    我正在使用PostgreSQL9.1.3(x86_64-pc-linux-gnu上的PostgreSQL9.1.3,由gcc-4.6.real(Ubuntu/Linaro4.6.1-9ubuntu3)4.6.1,64位编译)和在ubuntu11.10上运行3.2.2或3.2.1。现在,我可以使用以下命令连接PostgreSQLsupostgres输入密码我可以看到postgres=#我将以下详细信息放在我的config/database.yml中并执行“railsdb”,它工作正常。开发:adapter:postgresqlencoding:utf8reconnect:falsedat

  8. ruby-on-rails - Rails 2.3.11 DateTime BigDecimal 精度 - 2

    我目前有一个运行Ruby1.8.7和Rails2.3.2的RubyonRails项目我有一些从数据库中读取数据的单元测试,特别是两个连续项目的日期时间列,这两个项目应该相隔24小时。在一项测试中,我将项目2的日期时间设置为与项目1的日期时间相同。当我执行断言以确保两个值相等时,测试在rails2.3.2下工作正常。当我升级到rails2.3.11时,测试失败显示两次之间的差异将关闭并出现以下错误:expectedbutwas.这两个版本的rails中似乎存在浮点转换问题。如何解决float问题? 最佳答案 这也发生在我身上,我最终这

  9. ruby-on-rails - 如何在文本字段rails postgresql中查询json数据 - 2

    我有一个数据库表列(collection),datatypetext我在collection中插入了json数据这是我的json数据{"name":"test","age":"25","country":"xxx"}但是现在我该如何查询这个json数据。有没有如下选项User.where(collection::name)#Herenamedenotestest 最佳答案 由于JSON是一个字符串,您只能使用SQLite/MySQL(或任何其他数据库)进行字符串比较。此外,尽量将数据类型保持为二进制。您可以执行:LIKE操作以在您存

  10. ruby-on-rails - Rails Postgresql 多个模式和相同的表名 - 2

    我在两个不同的模式中有两个表,例如案例和事件。在每个模式中我都有基本表events.basiccases.basic这个表有关系:events.basic有一个cases.basic(cases.basic有多个events.basic)我的尝试失败了:文件cases_basic.rbclassCasesBasic'EventsBasic',:foreign_key=>'case_id'end文件events_basic.rbclassEventsBasic'CasesBasic',:foreign_key=>'case_id'end环境:Ruby1.9.3、Rails3.1.3、ge

随机推荐