# 我遇到的面试题

说说 union和union all的区别

union all只是合并查询结果,并不会进行去重和排序操作,在没有去重的前提下,使用union all的执行效率要比union高

# 概念

常用的数据类型有:

  • 整数
  • 浮点
  • 日期/时间
  • 字符串
  • 二进制

数据库系统有3个组成部分

  • 数据库
  • 数据库管理系统
  • 数据库应用系统

# SQL

SQL是对数据库进行查询和修改的语言

4个部分

  • DDL: DROP/CREATE/ALTER
  • DML:INSERT/UPDATE/DELETE
  • DQL:SELECT
  • DCL:GRANT/REVOKE...

# 常用的数据库访问技术

目前流行的数据库访问技术

  • ODBC: Open Database Connectivity
  • JDBC
  • ADO.NET
  • PDO

# PostgreSQL介绍

# 发展历程

# 主要特点

  • 免费
  • 速度快
  • 平台可移植性
  • 丰富的接口
  • 面向对象特性
  • 安全性
  • 配置的开源软件很多

# psql语法

# 空值排序


-- 相当于 order by emanager asc nulls last
select * from emp_test order by emanager;

-- 默认
select * from emp_test order by emanager asc nulls last;

-- nulls first: 空值排在前面
select * from emp_test order by emanager asc nulls first;

# exists

where exists xxxxx

exists 是真,则执行前面的查询

select exists(select * from (select 'true' where 1=1) as b);
select exists(select * from (select 'true' where 1=1) as b);

# some、any、all 查询

一. ANY/SOME

WHERE expression operator ANY (subquery) WHERE expression operator SOME (subquery)

其实ANY和SOME在这里是同等效的,子查询的结果集只能是一个字段,左边表达式使用operator对结果集的每一行进行一次比较运算,如果有一个运算结果是'TRUE',则表达式结果为'TRUE',如果比较结果全部是'FALSE'表达式结果才是'FALSE'。

> ANY 大于子查询结果中的某个值

< ANY 小于子查询结果中的某个值

>= ANY 大于或等于子查询结果中的某个值

<= ANY 小于或等于子查询结果中的某个值

= ANY 等于子查询结果中的某个值,相当于IN

!= ANY 不等于子查询结果中的某个值

示例1.查询tbl_insert表,条件是字段a大于表tbl_test字段f某一行中的值

test=# select * from tbl_insert where a > any(select f from tbl_test);
 a | b |   c   
---+---+-------
 2 | 2 | 22
 3 | 3 | 33
 4 | 4 | 44
 5 | 5 | 51
 6 | 6 | 1
 6 | 6 | 61
 6 | 6 | 661
 7 | 7 | 3%1
 8 | 8 | 3%_1
 8 | 8 | 3_%_1
 7 | 7 | abc
 7 | 7 | ABc
 7 | 7 | aBC
(13 rows)

二. ALL

WHERE expression operator ALL(subquery)

同样子查询中仍只能返回一个字段,与子查询结果集每一行进行比较结果全部是'TRUE'表达式结果才是'TRUE',否则为'FALSE'。

> ALL 大于子查询结果中的所有值

< ALL 小于子查询结果中的所有值

>= ALL 大于或等于子查询结果中的所有值

<= ALL 小于或等于子查询结果中的所有值

= ALL 等于子查询结果中所有值(除非子查询的结果全部相等,所以实际上没什么意义)

!= ALL 不等于子查询结果中的任何一个值,相当于NOT IN

示例1.查询tbl_insert表中a最大的行

test=# select * from tbl_insert where a = (select max(a) from tbl_insert);
 a | b |   c   
---+---+-------
 8 | 8 | 3%_1
 8 | 8 | 3_%_1
(2 rows)

test=# select * from tbl_insert where a >= all(select a from tbl_insert);
 a | b |   c   
---+---+-------
 8 | 8 | 3%_1
 8 | 8 | 3_%_1
(2 rows)

示例2.查询tbl_insert表中a最小的行

test=# select * from tbl_insert where a <= all(select a from tbl_insert);
 a | b | c  
---+---+----
 1 | 1 | 11
(1 row)

test=# select * from tbl_insert where a = (select min(a) from tbl_insert);
 a | b | c  
---+---+----
 1 | 1 | 11
(1 row)

# 左外连接

left outer join 怎么理解? 左外连接就是做连接。只是相对inner join 而言

CREATE TABLE employee
(
  id integer primary key,
  name varchar(50),
  dept_id integer
);

insert into employee values (1, '张三', 1);
insert into employee values (2, '李四', 2);
insert into employee values (3, '王五', 3);
insert into employee values (4, '李洋', null);
insert into employee values (5, 'Marry', null);
insert into employee values (6, 'lily', null);
insert into employee values (7, 'Larry', null);


CREATE TABLE department
(
  id integer primary key,
  dept text,
  fac_id integer
);


-- 插入数据
INSERT INTO department VALUES(1,'IT', 1);
INSERT INTO department VALUES(2,'Engineering', 2);
INSERT INTO department VALUES(3,'HR', 7);


-- 这两写法结果相同
select * from employee e left join department d on e.dept_id = d.id;
select * from employee e left outer join department d on e.dept_id = d.id;

# unoin 和unoin all

unoin 执行速度慢。unoin all执行速度快,因为不会去除重复

select id,name from employee where id > 3 union (select id,name from employee where id < 5);

select id,name from employee where id > 3 union all (select id,name from employee where id < 5);

# update returning

更新是返回更新后该行的数据

update dummy_table set age=30 returning age as age_no,name,address;

# view的相关操作

create or replace view vi as select * from dummy_table where age is not NULL;

此时删除v2(视图)中的数据,也会删除dummy_table中的数据。


insert into test_table values(10,'A1','CEO',null);
insert into test_table values(11, 'B1', 'VP', 10);
insert into test_table values(12, 'B2', 'VP', 10);
insert into test_table values(13, 'B3', 'VP', 10);
insert into test_table values(14, 'C1', 'DIRECTOR', 13);
insert into test_table values(15, 'C2', 'DIRECTOR', 13);
insert into test_table values(16, 'D1', 'MANAGER', 15);
insert into test_table values(17 ,'E1', 'ENGINEER', 11);
insert into test_table values(18, 'E2', 'ENGINEER', 11);

# psql常用指令

\c db_name: 连接数据库

\dt: 列出所有表

创建schema create schema schame_name;

show search_path: 现实搜索路径,即schema的搜索路径,默认为public

set search_path='demo',$user,'public'设置搜索路径

\l 列出所有的数据库

\?帮助

\d+ table_name 显示表结构

\dt 列出所有表

# 递归查询

查询出管理的所有人

CREATE TABLE emp_test (
  id int,
  ename varchar(255),
  emanager int
);

INSERT INTO emp_test VALUES (1, 'abc', null);
INSERT INTO emp_test VALUES (2, 'xyz', 1);
INSERT INTO emp_test VALUES (3, 'def', 2);
INSERT INTO emp_test VALUES (4, 'cde', 1);
INSERT INTO emp_test VALUES (5, 'qrs', 2);
INSERT INTO emp_test VALUES (9, 'iop', 3);
INSERT INTO emp_test VALUES (10, 'klm', 4);

-- 查询所有下属
WITH RECURSIVE emp_testnew  AS (
  SELECT id, ename, emanager
  FROM emp_test
  WHERE id = 2
  UNION ALL
  SELECT e.id, e.ename, e.emanager
  FROM emp_test e
  INNER JOIN emp_testnew e1 ON e1.id = e.emanager
)
SELECT *
FROM emp_testnew;

-- 查询所有上级管理人员
WITH RECURSIVE emp_testnew  AS (
  SELECT id, ename, emanager
  FROM emp_test
  WHERE id = 9
  UNION ALL
  SELECT e.id, e.ename, e.emanager
  FROM emp_test e
  INNER JOIN emp_testnew e1 ON e1.emanager = e.id
)
SELECT *
FROM emp_testnew;

# ALTER TABLE

-- 添加列
alter table dummy_table add col1 int;

-- 重命名列
alter table dummy_table  rename col1 to col2;

-- 修改列的类型
alter table dummy_table alter column col2 type char;

-- 删除列
alter table dummy_table drop column col2;

# COMMENT

注释


-- 给表添加注释
Comment on table dummy_table  is 'This was a testing table';

-- 方法添加注释
Comment on function f is 'Don''t update the function please' ;