当前位置: 首页 > news >正文

那个旅游网站可以做行程千万不要学网络营销

那个旅游网站可以做行程,千万不要学网络营销,如何做网站商城,模板手机网站建设公司一、简介 在之前的章节里我们已经涉及了使用SQL在PostgreSQL中存储和访问数据的基础知识。现在我们将要讨论SQL中一些更高级的特性,这些特性有助于简化管理和防止数据丢失或损坏。最后,我们还将介绍一些PostgreSQL扩展。 本章有时将引用教程&#xff0…

一、简介

在之前的章节里我们已经涉及了使用SQL在PostgreSQL中存储和访问数据的基础知识。现在我们将要讨论SQL中一些更高级的特性,这些特性有助于简化管理和防止数据丢失或损坏。最后,我们还将介绍一些PostgreSQL扩展。

本章有时将引用教程(三)中的例子并对其进行改变或改进以便于阅读本章。本章中的某些例子可以在教程目录的advanced.sql文件中找到。该文件也包含一些样例数据,在这里就不在赘述(查看教程(三)第一节了解如何使用该文件)。


二、视图

回想一下教程(三)第六节中的查询。假设天气记录和城市位置的组合列表对我们的应用有用,但我们又不想每次需要使用它时都敲入整个查询。我们可以在该查询上创建一个视图,这会给该查询一个名字,我们可以像使用一个普通表一样来使用它:

创建视图:CREATE VIEW myview AS SELECT city, temp_lo, temp_hi, prcp, date, location FROM weather, cities WHERE city = name;

查看当前数据库的表:\d

查询视图的数据:select * from myview;

对视图的使用是成就一个好的SQL数据库设计的关键方面。视图允许用户通过始终如一的接口封装的结构细节,这样可以避免表结构随着应用的进行而变化。

视图几乎可以用在任何可以使用表的地方。在其他视图基础上创建视图也并不少见。


三、外键

回想教程(三)中的weather和cities表。考虑以下问题:我们希望确保在cities表中有相应项之前任何人都不能在weather表中插入行。这叫做维持数据的引用完整性。在过分简化的数据库系统中,可以通过线检查cities表中是否有匹配的记录存在,然后决定应该接受还是拒绝即将插入weather表的行。这种方法有一些问题且并不方便,于是PostgreSQL可以为我们来解决。

新的表定义如下:

创建cities表:CREATE TABLE cities (city     varchar(80) primary key,location point
);创建weather表:CREATE TABLE weather (city      varchar(80) references cities(city),temp_lo   int,temp_hi   int,prcp      real,date      date
);查看表:\d

现在尝试插入一个非法的记录:

INSERT INTO weather VALUES ('Berkeley', 45, 53, 0.0, '1994-11-28');

报错信息为:

ERROR:  insert or update on table "weather" violates foreign key constraint "weather_city_fkey"
DETAIL:  Key (city)=(Berkeley) is not present in table "cities".

外键的行为可以很好地根据应用来调整。我们不会再这个教程里更深入地介绍,读者可以参考第 5 章中的信息。正确使用外键无疑会提高数据库应用的质量,因此强烈建议用户学会如何使用它们。


四、事务

事务是所有数据库系统的基础概念。事务最重要的一点是它将多个步骤捆绑成了一个单一的、要么全完成要么全不完成的操作。步骤之间的中间状态对于其他并发事务是不可见的,并且如果有某些错误发生导致事务不能完成,则其中任何一个步骤都不会对数据库造成影响。

例如,考虑一个保存着多个客户账户余额和支行总存款额的银行数据库。假设我们希望记录一笔从Alice的账户到Bob的账户的额度为100美金的转账。在最大程度地简化后,涉及到的SQL命令是:

UPDATE accounts SET balance = balance - 100.00WHERE name = 'Alice';
UPDATE branches SET balance = balance - 100.00WHERE name = (SELECT branch_name FROM accounts WHERE name = 'Alice');
UPDATE accounts SET balance = balance + 100.00WHERE name = 'Bob';
UPDATE branches SET balance = balance + 100.00WHERE name = (SELECT branch_name FROM accounts WHERE name = 'Bob');

这些命令的细节在这里并不重要,关键点是为了完成这个相当简单的操作涉及到多个独立的更新。我们的银行职员希望确保这些更新要么全部发生,或者全部不发生。当然不能发生因为系统错误导致Bob收到100美元而Alice并未被扣款的情况。Alice当然也不希望自己被扣款而Bob没有收到钱。我们需要一种保障,当操作中途某些错误发生时已经执行的步骤不会产生效果。将这些更新组织成一个事务就可以给我们这种保障。一个事务被称为是原子的:从其他事务的角度来看,它要么整个发生要么完全不发生。

我们同样希望能保证一旦一个事务被数据库系统完成并认可,它就被永久地记录下来且即便其后发生崩溃也不会被丢失。例如,如果我们正在记录Bob的一次现金提款,我们当然不希望他刚走出银行大门,对他账户的扣款就消失。一个事务型数据库保证一个事务在被报告为完成之前它所做的所有更新都被记录在持久存储(即磁盘)

事务型数据库的另一个重要性质与原子更新的概念紧密相关:当多个事务并发运行时,每一个都不能看到其他事务未完成的修改。例如,如果一个事务正忙着总计所有支行的余额,它不会只包括Alice的支行的扣款而不包括Bob的支行的存款,或者反之。所以事务的全做或全不做并不只体现在它们对数据库的持久影响,也体现在它们发生时的可见性。一个事务所做的更新在它完成之前对于其他事务是不可见的,而之后所有的更新将同时变得可见

在PostgreSQL中,开启一个事务需要将SQL命令用BEGINCOMMIT命令包围起来。因此我们的银行事务看起来会是这样:

BEGIN;
UPDATE accounts SET balance = balance - 100.00WHERE name = 'Alice';
-- etc etc
COMMIT;

如果,在事务执行中我们并不想提交(或许是我们注意到Alice的余额不足),我们可以发出ROLLBACK命令,而不是COMMIT命令,这样所有目前的更新将会被取消。

PostgreSQL实际上将每一个SQL语句都作为一个事务来执行。如果我们没有发出BEGIN命令,则每个独立的语句都会被加上一个隐式的BEGIN以及(如果成功)COMMIT来包围它。一组被BEGINCOMMIT包围的语句也被称为一个事务块


Notes:

某些客户端库会自动发出BEGIN和COMMIT命令,因此我们可能会在不被告知的情况下得到事务块的效果。具体请查看所使用的接口文档。


也可以利用保存点来以更细的粒度开控制一个事务中的语句。保存点允许我们有选择性地放弃事务的一部分而提交剩下的部分。在使用SAVEPOINT定义一个保存点后,我们可以在必要时利用ROLLBACK TO回滚到该保存点该事务中位于保存点和回滚点之间的数据库修改都会被放弃,但是早于该保存点的修改则会被保存

在回滚到保存点之后,它的定义依然存在,因此我们可以多次回滚到它。反过来,如果确定不再需要回滚到特定的保存点,它可以被释放以便系统释放一些资源。记住不管是释放保存点还是回滚到保存点都会释放定义在该保存点之后的所有其他保存点。

所有这些都发生在一个事务块内,因此这些对于其他数据库会话都不可见。当提交整个事务块时,被提交的动作将作为一个单元变得对其他会话可见,而被回滚的动作则永远不会变得可见。

记住那个银行数据库,假设我们从Alice的账户扣款100美元,然后存款到Bob的账户,结果直到最后才发现我们应该存到Wally的账户。我们可以通过使用保存点来做这件事:

BEGIN;
UPDATE accounts SET balance = balance - 100.00WHERE name = 'Alice';
SAVEPOINT my_savepoint;
UPDATE accounts SET balance = balance + 100.00WHERE name = 'Bob';
-- oops ... forget that and use Wally's account
ROLLBACK TO my_savepoint;
UPDATE accounts SET balance = balance + 100.00WHERE name = 'Wally';
COMMIT;

当然,这个例子是被过度简化的,但是在一个事务块中使用保存点存在很多种控制可能性。此外,ROLLBACK TO是唯一的途径来重新控制一个由于错误被系统置为中断状态的事务块,而不是完全回滚它并重新启动。


五、窗口函数

一个窗口函数在一系列与当前行有某种关联的表行上执行一种计算。这与一个聚集函数所完成的计算有可比之处。但是窗口函数并不会使多行被聚集成一个单独的输出行,这与通常的非窗口聚集函数不同。取而代之,行保留它们独立的标识。在这些现象背后,窗口函数可以访问的不仅仅是查询结果的当前行。

下面是一个例子用于展示如何将每一个员工的薪水与他/她所在部门的平均薪水进行比较:

SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM empsalary;
  depname  | empno | salary |          avg
-----------+-------+--------+-----------------------develop   |    11 |   5200 | 5020.0000000000000000develop   |     7 |   4200 | 5020.0000000000000000develop   |     9 |   4500 | 5020.0000000000000000develop   |     8 |   6000 | 5020.0000000000000000develop   |    10 |   5200 | 5020.0000000000000000personnel |     5 |   3500 | 3700.0000000000000000personnel |     2 |   3900 | 3700.0000000000000000sales     |     3 |   4800 | 4866.6666666666666667sales     |     1 |   5000 | 4866.6666666666666667sales     |     4 |   4800 | 4866.6666666666666667
(10 rows)

最开始的三个输出列直接来自于表empsalary,并且表中每一行都有一个输出行。第四列表示对与当前行具有相同depname值的所有表行取得平均值(这实际和非窗口avg聚集件数是相同的函数,但是OVER子句使得它被当做一个窗口函数处理并在一个格式的窗口帧上计算。)。

一个窗口函数调用总是包含一个直接跟在窗口函数名及其参数之后的OVER子句。这使得它从句法上和一个普通函数或非窗口函数区分开来。OVER子句决定究竟查询中的哪些行被分离出来由窗口函数处理。OVER子句中的PARTITION BY子句指定了将具有相同PARTITION BY表达式值的行分到组或者分区。对于每一行,窗口函数都会在当前行同一分区的行上进行计算。

我们可以通过OVER上的ORDER BY控制窗口函数处理行的顺序(窗口的ORDER BY并不一定要符合行输出的顺序。)。下面是一个例子:

SELECT depname, empno, salary,rank() OVER (PARTITION BY depname ORDER BY salary DESC) FROM empsalary;
 depname  | empno | salary | rank
-----------+-------+--------+------develop   |     8 |   6000 |    1develop   |    10 |   5200 |    2develop   |    11 |   5200 |    2develop   |     9 |   4500 |    4develop   |     7 |   4200 |    5personnel |     2 |   3900 |    1personnel |     5 |   3500 |    2sales     |     1 |   5000 |    1sales     |     4 |   4800 |    2sales     |     3 |   4800 |    2
(10 rows)

如上所示,rank函数在当前行的分区内按照ORDER BY子句的顺序为每一个可区分的ORDER BY值产生了一个数字等级。rank不需要显式的参数,因为它的行为完全决定于OVER子句

一个窗口函数所考虑的行属于那些通过查询的FROM子句产生并通过WHEREGROUP BYHAVING过滤的“虚拟表”。例如,一个由于不满足WHERE条件被删除的行是不会被任何窗口函数所见的。在一个查询中可以包含多个窗口函数,每个窗口函数都可以用不同的OVER子句来按不同方式划分数据,但是它们都作用在由虚拟表定义的同一个行集上。

我们已经看到如果行的顺序不重要时ORDER BY可以忽略。PARTITION BY同样也可以被忽略,在这种情况下会产生一个包含所有行的分区。

SELECT salary, sum(salary) OVER () FROM empsalary;
 salary |  sum
--------+-------5200 | 471005000 | 471003500 | 471004800 | 471003900 | 471004200 | 471004500 | 471004800 | 471006000 | 471005200 | 47100
(10 rows)

如上所示,由于在OVER子句中没有ORDER BY,窗口帧和分区一样,而如果缺少PARTITION BY则和整个表一样。换句话说,每个合计都会在整个表上进行,这样我们为每一个输出行得到的都是相同的结果。但是如果我们加上一个ORDER BY子句,我们会得到非常不同的结果:

SELECT salary, sum(salary) OVER (ORDER BY salary) FROM empsalary;
 salary |  sum
--------+-------3500 |  35003900 |  74004200 | 116004500 | 161004800 | 257004800 | 257005000 | 307005200 | 411005200 | 411006000 | 47100
(10 rows)

这里的合计是从第一个(最低的)薪水一直到当前行,包括任何与当前行相同的行(注意相同薪水行的结果)。

窗口函数只允许出现在查询的SELECT列表和ORDER BY子句中。它们不允许出现在其他地方,例如GROUP BYHAVINGWHERE子句中。这是因为窗口函数的执行逻辑是在处理完这些子句之后。另外,窗口函数在非窗口聚集函数之后执行。这意味着可以在窗口函数的参数中包括一个聚集函数,但反过来不行。

如果需要在窗口计算执行后进行过滤或者分组,我们可以使用子查询。例如:

SELECT depname, empno, salary, enroll_date
FROM(SELECT depname, empno, salary, enroll_date,rank() OVER (PARTITION BY depname ORDER BY salary DESC, empno) AS posFROM empsalary) AS ss
WHERE pos < 3;

上述查询仅仅显示了内层查询中rank低于3的结果。

当一个查询涉及到多个窗口函数时,可以将每一个分别写在一个独立的OVER子句中。但如果多个函数要求同一个窗口行为时,这种做法是冗余的而且容易出错的。替代方案是,每一个窗口行为可以被放在一个命名的WINDOW子句中,然后在OVER中引用它。例如:

SELECT sum(salary) OVER w, avg(salary) OVER wFROM empsalaryWINDOW w AS (PARTITION BY depname ORDER BY salary DESC);
http://www.hengruixuexiao.com/news/12452.html

相关文章:

  • 国家新闻出版署期刊查询入口泉州seo
  • 小程序二维码seo黑帽技术有哪些
  • 湛江网站建设开发大数据网络营销
  • 免费源代码网站做seo如何赚钱
  • 建筑资源网站电商网站模板
  • 短视频seo优化排名上海网站搜索引擎优化
  • 国内装饰行业网站制作网络营销的基本职能
  • 中央调查甘肃疫情最新消息seo小白入门
  • 如何给网站做app网站怎样优化seo
  • 唐山建网站公司企业培训课程开发
  • 专业网站制作公司时事新闻最新消息
  • 商城网站建设经验java培训机构十强
  • 网站登录页面模板 下载seo关键词排名教程
  • 南雄市建设局网站山东做网站公司
  • 东莞网站建设基础百度推广竞价托管
  • 站长素材音效网培训机构营业执照如何办理
  • 绵阳网站开发公司网站设计流程
  • 佛山市企业网站建设报价创意营销
  • 手机版crm免费的郑州网站seo服务
  • 卖东西怎么推广seo工程师
  • 城乡住房和建设厅官网南宁seo公司
  • 南昌网站关键词排名营销手段和营销方式
  • wordpress 头像设置seo优化好做吗
  • 一级域名网站全网线报 实时更新
  • 单页淘宝客网站模板西安seo服务
  • 花都建站百度联盟怎么赚钱
  • 网站里+动效是用什么做的99个创意营销方案
  • 网站如何测试有无未做链接的文件百度开户怎么开
  • 网上做任务网站有哪些内容广东短视频seo营销
  • 用vs2012做网站首页b站黄页推广