目录 
1.简单查询........................................................................................................................................ 2 
2.时间函数........................................................................................................................................ 3 
3.分组查询........................................................................................................................................ 5 
4.多表查询........................................................................................................................................ 6 
5.多表连接........................................................................................................................................ 9 
6.子查询 ......................................................................................................................................... 10 
7.创建和管理表 .............................................................................................................................. 12 
8.约束 ............................................................................................................................................. 15 
9.视图,序列,索引 ...................................................................................................................... 17 
10.pl sql 基础 .................................................................................................................................. 19 
 
 
 
1.简单查询 
--1.  消除重复的姓 
select distinct e.last_name as  姓氏  from employees e 
 
--2.  计算员工的月收入(工资+佣金) 
select salary,salary*(nvl(commission_pct,0)+1) as  工资佣金  from employees 
 
--3.  查询在 1998 年入职的员工 
select * from employees e 
where to_char(e.hire_date,'yyyy')='1998' 
 
--4.  查询姓以 B 开头的员工 
select * from employees e 
where e.last_name like 'B%' 
 
--5.  查询部门号为 10 或者 20 或者 30 的员工 
select *from employees e 
where e.department_id in (10,20,30) 
 
-6. -查询在 1998-02-02 和 1998-05-01 之间入职的员工的姓氏、职务标识和起始日期 
select t.last_name,t.job_id,t.hire_date from employees t 
where t.hire_date between 
to_date('19980220','yyyyMMdd') and to_date('19980501','yyyyMMdd'); 
 
--7.  显示员工名字中的第三个字母为“a”的所有员工的姓氏 
select t.last_name from employees t 
where t.last_name like '__a%'; 
 
--8.  显示赚取佣金的所有员工的姓氏、薪金和佣金,按薪金和佣金的降序对数据进行排序 
select t.last_name , t.salary,t.commission_pct from employees t 
where t.commission_pct is not null 
order by t.salary desc,t.commission_pct desc; 
 
 
2.时间函数 
--1.  显示当前日期 
select sysdate from dual; 
 
--2.  显示当前日期,格式为 yyyy 年 mm 月 dd 日,别名为 hday 
select to_char(sysdate,'yyyy"年"mm"月"dd"日"') hday from dual; 
 
--3.  编写一个查询,显示姓名以 J、A 或 M 开始的所有员工的姓氏(第一个字母大写,其余
字母小写)和姓氏的长度,给每列一个合适的标签 
select initcap(t.last_name) lname,length(t.last_name) len from employees t 
where substr(upper(last_name),0,1) in('J','A','M');   
 
--4  .  计算每位员工截止到当前时间入职的星期数,别名为 weeks_worked。按聘用的星期数
对结果进行排序。该星期数舍入到最接近的整数。同时显示员工的名字 
select t.first_name,round((sysdate-t.hire_date)/7) as weeks_worked from employees t; 
 
--5.  创建一个查询。显示所有员工的薪金。将薪金格式规定为 15 个字符长,左边填充$ 
select lpad(t.salary,15,'$') sal from employees t; 
 
--6.  显示每位员工的姓氏、聘用日期和薪金复核日期,薪金复核日期是服务六个月之后的第
一个星期一。将该列标记为 review,格式类似于:Monday,the Thirty-First of July,2000 
select t.last_name,t.hire_date, 
/*next_day(add_months(t.hire_date,6),2) from employees t*/ 
to_char(next_day(add_months(t.hire_date,6),2), 
'fmday,"the "ddspth" of "month,yyyy','nls_date_language=english') review 
from employees t; 
注:to_char 的第三个参数用于设置本次查询使用的国家和地区,ddspth 中 spth 为后缀,表
示 Spelled, ordinal number 
 
--7.  显示员工的姓氏、聘用日期和该员工在星期几开始工作的 
select t.last_name,t.hire_date,to_char(t.hire_date,'DAY') as start from employees t; 
 
--8.  创建一个查询,使其显示员工的姓氏,并用星号指明他们的年薪。每个星号代表一千美
元。按薪资降序排列数据 
select t.last_name||lpad(' ',trunc(t.salary/1000)+1,'*'),t.salary from employees t 
order by t.salary desc; 
 
--9.  创建一个查询。使其显示员工的姓氏和佣金额。如果某位员工不赚取佣金则显示“No 
Commission”,将该列标记为 COMM 
select t.last_name,nvl(to_char(t.salary*t.commission_pct,'999,999.99'),'No Commission') COMM 
from employees t; 
 
--10.  使用 decode 函数编写一个查询,使其按照以下数据根据 JOB_ID 列的值显示所有员工
的级别,同时显示员工的姓氏 
job_id 
 
 
 
 
 
 
 
 
 
grade 
AD_PRES  
ST_MAN   
IT_PROG   
SA_REP 
 
ST_CLERK  
都不 
 
select t.last_name,t.job_id job, 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
A 
B 
C 
D 
E 
0 
decode(t.job_id,'AD_PRES','A' 
                              ,'ST_MAN','B' 
                              ,'IT_PROG','C' 
                              ,'SA_REP','D' 
                              ,'ST_CLERK','E' 
                              ,'0') as grade 
from employees t; 
 
--11.  使用 case 语法重写一遍上题 
select t.last_name,t.job_id job, 
case t.job_id   
          when 'AD_PRES'then 'A' 
          when 'ST_MAN' then 'B' 
          when 'IT_PROG' then 'C' 
          when 'SA_REP' then 'D' 
          when 'ST_CLERK' then 'E' 
          else '0' 
end as grade 
from employees t; 
 
--12.  显示当前日期,本月最后一天的日期,以及本月还剩多少天 
select sysdate,last_day(sysdate) "last",last_day(sysdate)-sysdate "days left" from dual; 
 
--13.  显示今年的第一天 
select trunc(sysdate,'year') from dual; 
 
--14.  显示本月的第一天 
select trunc(sysdate,'month') from dual; 
 
--15.  最近一个星期四是哪天(不含今日) 
select next_day(sysdate,5) from dual; 
3.分组查询 
--1.  求所有员工的平均工资、最高工资、最低工资和工资总和,给予适当的别名 
select avg(t.salary),max(t.salary),min(t.salary),sum(t.salary) from employees t; 
 
--2.  查询出各部门的部门编号以及各部门的总工资和平均工资,按部门编号升序排列。 
select t.department_id,sum(t.salary),avg(t.salary) from employees t     
group by t.department_id 
order by t.department_id; 
 
--3.  显示每种工作的人数 
select t.job_id,count(*) from employees t 
group by t.job_id; 
 
--4.  显示员工最高工资超过 10000 的部门的 id 及其员工最高工资 
select t.department_id,max(t.salary) m from employees t 
group by t.department_id 
having max(t.salary)>10000; 
 
--5.  显示平均工资最高的部门 id 及其平均工资 
select * from( 
select t.department_id,avg(t.salary) 
from employees t 
group by t.department_id 
order by avg(t.salary) desc 
) 
where rownum<2; 
 
 
4.多表查询 
多表查询,基本知识: 
什么是多表查询? 
什么是笛卡尔积? 
怎样避免笛卡尔积? 
要将 n 个表联结在一起,至少需要多少个联结条件? 
什么是等值联结? 
如何在联结条件外附加限制条件? 
如何限定模糊的列名? 
如何进行非等值联结? 
什么是外联结? 
什么是自联结? 
如何用 sql1999 标准表达:笛卡尔积、自然联结、等值联结、内联结、左外联结、右外
联结和全外联结? 
 
联结的分类: 
Joins that are compliant with the SQL:1999 standard include the following: 
Natural joins: 
                NATURAL JOIN clause 
                USING clause 
                ON clause 
Outer joins: 
            LEFT OUTER JOIN 
            RIGHT OUTER JOIN 
            FULL OUTER JOIN 
Cross joins 
 
sql1999 联结语法: 
SELECT table1.column, table2.column 
FROM table1 
[NATURAL JOIN table2]   
|[JOIN table2 USING (column_name)]   
|[JOIN table2 ON (table1.column_name = table2.column_name)] 
|[LEFT|RIGHT|FULL OUTER JOIN table2 ON (table1.column_name = table2.column_name)] 
|[CROSS JOIN table2]; 
 
--1. Write a query for the HR department to produce the addresses of all the departments. Use 
the  LOCATIONS  and  COUNTRIES  tables.  Show  the  location  ID,  street  address,  city,  state  or 
province, and country in the output. Use a NATURAL JOIN to produce the results. 
select lct.location_id,lct.street_address,lct.state_province,cty.country_name 
from locations lct 
natural join countries cty; 
 
--2.  The  HR  department  needs  a  report  of  employees  in  Toronto.  Display  the  last  name,  job, 
department number, and the department name for all employees who work in Toronto. 
select emp.last_name,emp.job_id,dpt.department_id,dpt.department_name 
from employees emp 
join departments dpt on emp.department_id=dpt.department_id 
join locations lct on dpt.location_id=lct.location_id 
where lct.city='Toronto'; 
 
--3.  Create  a  report  for  the  HR  department  that  displays  employee  last  names,  department 
numbers,  and all the  employees who  work  in  the  same  department  as  a  given  employee.  Give 
each column an appropriate label. Save the script to a file named lab_06_06.sql. 
select emp.last_name Employee,emp.department_id,colleague.last_name colleague 
from employees emp 
join employees colleague on emp.department_id=colleague.department_id 
where emp.employee_id<>colleague.employee_id 
order by Employee; 
 
--4. The HR department needs a report on job grades and salaries. To familiarize yourself with the 
JOB_GRADES table, first show the structure of the JOB_GRADES table. Then create a query that 
displays the name, job, department name, salary, and grade for all employees.*/ 
--建表 
create table JOB_GRADES( 
LOWEST_SAL    NUMBER(6), 
HIGHEST_SAL NUMBER(6), 
GRADE_LEVEL CHAR(1) 
) 
--插入数据 
insert into JOB_GRADES (LOWEST_SAL, HIGHEST_SAL, GRADE_LEVEL) 
values (30000, 40000, 'F'); 
insert into JOB_GRADES (LOWEST_SAL, HIGHEST_SAL, GRADE_LEVEL) 
values (20000, 30000, 'E'); 
insert into JOB_GRADES (LOWEST_SAL, HIGHEST_SAL, GRADE_LEVEL) 
values (15000, 20000, 'D'); 
insert into JOB_GRADES (LOWEST_SAL, HIGHEST_SAL, GRADE_LEVEL) 
values (8500, 15000, 'C'); 
insert into JOB_GRADES (LOWEST_SAL, HIGHEST_SAL, GRADE_LEVEL) 
values (5500, 8500, 'B'); 
insert into JOB_GRADES (LOWEST_SAL, HIGHEST_SAL, GRADE_LEVEL) 
values (2000, 5000, 'A'); 
commit; 
 
select emp.last_name Employee,emp.salary,g.grade_level 
from employees emp 
join job_grades g on emp.salary between g.lowest_sal and g.highest_sal; 
 
--5. The HR department wants to determine the names of all the employees who were hired after 
Davies. Create a query to display the name and hire date of any employee hired after employee 
Davies. 
select emp.last_name Employee,emp.hire_date 
from employees emp 
join employees clg on emp.hire_date > clg.hire_date 
where clg.last_name='Davies' 
order by emp.hire_date; 
--6. The HR department needs to find the names and hire dates of all the employees who were 
hired before their managers, along with their managers’ names and hire dates. Save the script to 
a file named lab_06_09.sql. 
 
select emp.last_nam,emp.hire_date,mgr.last_name,mgr.hire_date 
from employees emp   
join employees mgr on emp.manager_id=mgr.employee_id and emp.hire_date < mgr.hire_date;