SQL总结(语法部分)
1.exists和in的区别
......
where exists (
select 'x' from employees e
where e.department_id = d.department_id
);
......
where department_id in (
select e.department_id, from employees e
where e.department_id = d.department_id
);
通过上面两个简单的例子我们明显看出exists 和 in 语法的区别和关键
在exists中 select ‘x’ 表示返回一个结果,并不在乎表的具体字段类型,只判断有没有记录生成,后面的子查询只要有结果生成,就认为真,否则便是假。
那么查不到具体的东西,又怎么筛选呢,我们平时写东西,判断一个是否存在,会像in那样的语法,我的字段数据是否存在另一列中,而exists前面不允许加字段名,所以我们在编写exists的子查询中如果没有和主查询的from表进行一定的判断和比较,那么exists后面的子查询又只会判断记录是否生成,那结果可想而知,要么主查询结果全部出现,要么一个也不出现。这也是exists效率高于in的原因。
另外在两者互相替换使用的过程中,基本不会出现太大问题,不过由于null in null被认为是假的,所以当你想用not in 替换not exists时请务必保证子查询的数据中没有null,否则任何not in的都会认为是真,那么任何数据都无法输出。
2.null值处理
= null是没有意义的 请用is NULL
is Null,注意:索引不会取到Null值;
可能为空值的字段与其他表关联时使用外连接,否则将缺少数据
可能为空值的,建立nvl(xx,’N’)函数索引,转化NULL为其他值
3.外连接
主表记录全显示,从表记录有则显示,无则留空
Oracle的(+) ,等价于 left join / right join
(+)在谁后面谁就是从表,left join的写法相反
如下
FROM employees e
LEFT JOIN departments d
ON e.department_id = d.department_id;(using(col)也可以)
WHERE e.department_id = d.department_id(+);
简单来说,有空的为主表可以出现为空的数据,没空的为主表则可以清楚为空的数据
4.count注意
Count(*)/Count(1)全量
Count(字段)去Null值
Count(null)恒为0
select count(*) from employees; -- 107
select count(1) from employees; -- 107
select count(e.commission_pct) from employees e; -- 35
select count(null) from dual; -- 0
5.insert注意
INSERT INTO
(SELECT employee_id,last_name,email,hire_date,job_id,salary,department_id
FROM employees
WHERE department_id = 50 WITH CHECK OPTION)
VALUES
(99998,'Smith','JSMITH',sysdate,'ST_CLERK',5000,50); --OK
WITH CHECK OPTION 强制表上执行的所有数据修改语句都必须符合由 select_statement 设置的准则, 以后对该视图插入、修改、删除操作时,会自动加上字段1=’a’ 的条件,所以如果没有where条件,该限制也是多余的。
如果没有WITH CHECK OPTION,只需在插入的时候保证即可,之后对表的修改等操作不受该限制。
6.Truncate/Delete区别
Trunc是DDL,Delete是DML
1) Trunc没有Rollback机会 ,Delete不提交还有
2) TruncHWM(High Water Mark)标记复位,Delete有高水位线问题
第一个就不解释了,DDL,DML操作的区别
第二个Trunc就是删除的一干二净,一张啥也没有的空表
高水位线问题就是Delete执行后,虽然数据都删除了,但他们的位置指针仍然没变,之前累积到第500个数据,那你删除之后再添加的数据位于501号指针,虽然不在表里展示,但再查询等操作时,依然会跟据指针为1的位置进行搜索,此时就算你表里只有一条数据,也是很耗时的。
7.UNION和UNION ALL
要求两个表的表结构,字段一样,否则不可union,UNION去重,UNION不去重
8.Group by
select 类别, sum(数量) as 数量之和, 摘要
from A
group by 类别
order by 类别 desc
执行后会提示错误,这就是需要注意的一点,在select指定的字段要么就要包含在Group By语句的后面,作为分组的依据;要么就要被包含在聚合函数中。
“Group By”从字面意义上理解就是根据“By”指定的规则对数据进行分组,所谓的分组就是将一个“数据集”划分成若干个“小区域”,然后针对若干个“小区域”进行数据处理。
我们通俗来理解,当我们对一个表进行了group by col,那么本来有很多行相同col的属性被并成了一组,也就是一行数据,那么我们select 非col属性的值时,将面临无法展示的问题,因为已经分成了一组,数据却还有那么多行,所以会报错,那为什么聚合函数可以呢,很简单,聚合函数对一列值,只保留一个值,正好可以放在这一行分组的数据里,比如sum(数量),每一个col都有很多数量但sum()之后只有一个值,可以存在该分组里。
group by 增强语法
自己找规律吧
GROUP BY ROLLUP(1,2,3);
=group by(1,2,3) union group by(1,2) union group by(1) union group by(null)
GROUP BY CUBE(1,2,3);
=group by(1,2,3) union group by(1,2) union group by(1,3) union group by(2,3) union group by(1) union group by(2) union group by(3) union group by(null)
GROUP BY GROUPING SETS ((1,2),(3,4))——–字面意思
9.with
with table-name as(子查询)
select ============
定义一个暂时表,给后面的查询用。
10.递归查询语法
select ... from tablename start with 条件1
connect by 条件2
where 条件3;
用PRIOR表示上一条记录
CONNECT BY PRIOR employee_id=manager_id
上一条记录的employee_id是本条记录的manager_id
用于递归表中。