CREATE TABLE learn_sql( l_id NUMBER(8), l_date DATE DEFAULT SYSDATE, l_str VARCHAR2(200) ); INSERT INTO learn_sql (l_id,l_str)VALUES(1,'小明');
SELECT * FROM learn_sql; -- 这里的“*”将会被隐式转化为多个字段,即以下语句(所有字段),这里不多做赘述 SELECT l_id,l_date,l_str FROM learn_sql;
最基础的count(1),将整体作为一个group SELECT count(1) FROM learn_sql l; --准备数据 INSERT INTO learn_sql (l_id,l_str)VALUES(2,'小青'); INSERT INTO learn_sql (l_id,l_str)VALUES(3,'小黑'); INSERT INTO learn_sql (l_id,l_str)VALUES(4,'小红'); INSERT INTO learn_sql (l_id,l_str)VALUES(9,'小蓝'); --查询语句 SELECT count(1),'你好' FROM learn_sql l GROUP BY CASE WHEN 1=1 THEN l.l_id ELSE 1 END HAVING COUNT(1)=2; -- 至于为什么能写case函数,因为它最后能返回一个字段,在此处它返回了一个l_id字段,decode也是如此 -- having里面最好不要写乱七八糟的东西,能在where里写的就不在having里写, having是最后筛选的 就比如: -- 1 SELECT count(1),SUM(l.l_id),CASE WHEN 1=1 THEN l.l_id ELSE 1 END "表的id" FROM learn_sql l GROUP BY CASE WHEN 1=1 THEN l.l_id ELSE 1 END HAVING CASE WHEN 1=1 THEN l.l_id ELSE 1 END = 2; -- 2. SELECT count(1),SUM(l.l_id),CASE WHEN 1=1 THEN l.l_id ELSE 1 END "表的id" FROM learn_sql l WHERE CASE WHEN 1=1 THEN l.l_id ELSE 1 END = 2 GROUP BY CASE WHEN 1=1 THEN l.l_id ELSE 1 END -- 这里最好选择2这种方式,能在where里面过滤的就不要到having里过滤,因为having是二次过滤 -- 除非是像以下这种问题,where不能过滤的聚合函数,需要放在having里面过滤, having本来也就是为了进行二次过滤出现的 SELECT count(1),SUM(l.l_id),l.l_id "表的id" FROM learn_sql l GROUP BY l.l_id HAVING COUNT(1)>=1;
-- 只要类型对了,就算 select 的是 * 也可以照用不误, 主要看返回值(不推荐用*) CREATE TABLE test_1206 (tid NUMBER(8)); INSERT INTO test_1206 VALUES(1); SELECT (SELECT * FROM test_1206),e.* FROM employees e; 这里是因为只插入了一条数据,且只有一列
-- 拓展:行转列函数 SELECT wm_concat(l.l_str) NAME FROM learn_sql l;
--因为in里面可以写null,eg:1 in (null,2) 1=null(假)继续过滤.. SELECT COUNT(1) FROM employees e1 WHERE e1.employee_id IN (SELECT e2.manager_id FROM employees e2);
--exists SELECT COUNT(1) FROM employees e WHERE EXISTS (SELECT 1 FROM employees e2 WHERE e2.manager_id = e.employee_id);
--not in需要加过滤条件 eg:1 not in(2,3,null); 当到了1!=null(假)直接跳出过滤 SELECT COUNT(1) FROM employees e WHERE e.employee_id NOT IN (SELECT e2.manager_id FROM employees e2 WHERE e2.manager_id IS NOT NULL);
--not exist SELECT COUNT(1) FROM employees outere WHERE NOT EXISTS (SELECT 1 FROM employees innere WHERE outere.employee_id = innere.manager_id);
SELECT LEVEL ,PRIOR e.last_name ,e.* FROM employees e CONNECT BY PRIOR e.employee_id = e.manager_id START WITH e.last_name = 'King' ORDER BY LEVEL DESC;
##基础函数 ###数字的玩法 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YXcpDL1T-1591502447019)(https://i.imgur.com/FMD7TuX.png)]
改变金钱前面的字符
alter session set NLS_CURRENCY = ‘¥';
SELECT to_char(432553425.1 ,'L000,000,000,000.000') FROM dual; --¥000,432,553,425.100
SELECT to_char(2341.3241 ,'L0999,999,999.0000') FROM dual; -- ¥0000,002,341.3241
SELECT to_char(2341.3241 ,'L9999,999,999.0000') FROM dual; -->2,341.3241
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eocH3jYb-1591502447029)(https://i.imgur.com/XKK538U.png)]
–>twenty seventeen
SELECT to_char(SYSDATE ,'year') FROM dual;
–>2017
SELECT to_char(SYSDATE ,'yyyy') FROM dual;
SELECT to_char(SYSDATE ,'mm') FROM dual;
SELECT to_char(SYSDATE ,'month') FROM dual;
-->december SELECT to_char(SYSDATE ,'mon') FROM dual; -->dec
–>5 这个月的第几天
SELECT to_char(SYSDATE ,'dd') FROM dual;
–tuesday
SELECT to_char(SYSDATE ,'day') FROM dual;
–>fifth
SELECT to_char(SYSDATE ,'ddspth') FROM dual;
–>tue
SELECT to_char(SYSDATE ,'dy') FROM dual;
–>02:13:54:pm
SELECT to_char(SYSDATE ,'hh:mi:ss:am') FROM dual;
–>现在是2017年12月05日 下午 16:19:58 星期二
SELECT REPLACE('现在是' || to_char(SYSDATE ,'yyyy"年"') || to_char(to_char(SYSDATE ,'mm') ,'99') || '月' || to_char(to_char(SYSDATE ,'DD') ,'00') || '日' ,' ' ,'') || ' ' || decode(to_char(SYSDATE ,'am') ,'am' ,'上午' ,'下午') || ' ' || to_char(SYSDATE ,'hh24:mi:ss') || decode(to_char(SYSDATE ,'dy') ,'tue' ,' 星期二') 我的日期 ,SYSDATE 默认日期 FROM dual;
--INSTR(源字符串, 要查找的字符串, 从第几个字符开始, 要找到第几个匹配的序号)返回找到的位置,如果找不到则返回0. SELECT INSTR('hello world','d',1,1) FROM dual; --结果为11 SELECT INSTR('hello world','o',1,2) FROM dual; -- 结果为8
###partition函数,块函数,分组函数。。随你叫吧
SELECT MAX(e.salary) over(PARTITION BY e.department_id) “最大工资”
,e.*
FROM employees e
ORDER BY e.employee_id;
SELECT e2.max_sal “最大工资”
,e.*
FROM employees e
,(SELECT e.department_id
,MAX(e.salary) max_sal
FROM employees e
GROUP BY e.department_id) e2
WHERE e.department_id = e2.department_id
ORDER BY e.employee_id;
SELECT DISTINCT (e2.max_sal) 最大工资
,e2.department_id
FROM employees e
,(SELECT e.department_id
,MAX(e.salary) max_sal
FROM employees e
GROUP BY e.department_id) e2
WHERE e.department_id = e2.department_id
ORDER BY e2.department_id;
SELECT DISTINCT (MAX(e.salary) over(PARTITION BY e.department_id)) 最大工资
,e.department_id
FROM employees e
ORDER BY e.department_id;
SELECT DISTINCT (e2.max_sal) 最大工资
,e2.department_id
FROM employees e
,(SELECT e.department_id
,MAX(e.salary) max_sal
FROM employees e
GROUP BY e.department_id) e2
WHERE e.department_id = e2.department_id
OR (e.department_id IS NULL
AND e2.department_id IS NULL)
ORDER BY e2.department_id;
SELECT e.salary
,e.department_id"部门"
,rank() over(ORDER BY e.salary DESC) rank
, – 重复的不算一个 1,1,1,4,4,6,6,6,9…
dense_rank() over(ORDER BY e.salary DESC) dense_rank
, – 重复的算一个 1,1,1,1,2,2,2,2,3…
row_number() over(ORDER BY e.department_id DESC) row_number – 从小到大无重复值 1,2,3,4,5,6…
FROM employees e
WHERE e.department_id = 50;
SELECT d.department_name
,e.last_name
,e.salary
,rank() over(PARTITION BY d.department_name ORDER BY e.salary DESC) dept_salary_rank1
,dense_rank() over(PARTITION BY d.department_name ORDER BY e.salary DESC) dept_salary_rank2
,row_number() over(PARTITION BY d.department_name ORDER BY e.salary DESC) dept_salary_rank3
FROM employees e
,departments d
WHERE 1 = 1
AND e.department_id = d.department_id;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hg9zbXhp-1591502447031)(https://i.imgur.com/tWqOrLq.png)]
-- 创建表test_1206 CREATE TABLE test_1206 ( ID NUMBER(8), NAME VARCHAR2(20), birthday DATE DEFAULT SYSDATE ); --修改表名字 ALTER TABLE test_1206 RENAME TO table_1206; -- 查询表内容 SELECT * FROM table_1206;-- 结果为空 --插入一条数据 INSERT INTO table_1206 VALUES (1,'xiaoli',to_date('19960206','yyyymmdd')); -- 查询表内容 SELECT * FROM table_1206; -- 有结果 commie; --就练习一次,这个随你开心就好
--创建视图 CREATE VIEW view_1206 AS SELECT * FROM table_1206 WHERE ID = 1; -- 通过视图获取信息 SELECT * FROM view_1206; -- 可以查到结果(注意where条件) -- 从视图向表中插入数据 INSERT INTO view_1206 VALUES(4,'xiaoli',SYSDATE);-- where条件不影响插入 SELECT * FROM TABLE_1206; --注意where条件,所以从表中直接查询,查询结果为已经插入 -- update也一样,注意where条件,逻辑说得过去就行,因为视图毕竟就是一个子查询
-- 创建视图 CREATE VIEW view_1206_complicated AS (SELECT NAME,COUNT(1) 统计同名的人 FROM table_1206 GROUP BY NAME); select * FROM view_1206_complicated; --通过视图查询 -- 现在你也应该大约了解为什么复杂视图不能进行DML操作了吧
DROP VIEW view_1206_complicated;
--最简单的方法去理解视图,上面那条简单视图插入的效果相同,复杂先抛开不说,首先它极有可能是不具备业务意义的 INSERT INTO (SELECT * FROM table_1206 WHERE id = 1) VALUES (7 ,'Tom' ,SYSDATE); -- 视图就是对用的频繁的子查询进行缩写,暂且可以认为它是一张表
create sequence my_index minvalue 1 --最小值 nomaxvalue --不设置最大值 start with 1 --从1开始计数 increment by 1 --每次加1个 nocycle --一直累加,不循环 nocache; --不建缓冲区 /* 如果你给出了cache值那么系统将自动读取你的cache值大小个seq, 这样在反复操作时会加快运行速度,但如果遭遇意外情况如当机了或oracle死了, 则下次取出的seq值将和上次的不连贯.如果没有强迫症连或者业务要求不连贯无所谓建议用cache. 假如缓冲区为200,这次用到了50,当机器关机后,下次在开启机器,会从201开始 */
SELECT my_index.nextval FROM dual;
SELECT my_index.currval FROM dual;--刚创建的序列不能直接得到当前值,需要用nextval初始化
INSERT ALL INTO sal_history VALUES (empid ,hiredate ,sal) INTO mgr_history VALUES (empid ,mgr ,sal) SELECT employee_id empid ,hire_date hiredate ,salary sal ,manager_id mgr FROM employees WHERE employee_id > 200;
INSERT ALL INTO sal_history VALUES (empid ,hiredate ,sal) INTO mgr_history VALUES (empid ,mgr ,sal) SELECT employee_id empid ,hire_date hiredate ,salary sal ,manager_id mgr FROM employees WHERE employee_id > 200;
INSERT FIRST WHEN sal > 25000 THEN INTO special_sal VALUES (deptid ,sal) WHEN hiredate LIKE ('%00%') THEN INTO hiredate_history_00 VALUES (deptid ,hiredate) WHEN hiredate LIKE ('%99%') THEN INTO hiredate_history_99 VALUES (deptid ,hiredate) ELSE INTO hiredate_history VALUES (deptid ,hiredate) SELECT department_id deptid ,SUM(salary) sal ,MAX(hire_date) hiredate FROM employees GROUP BY department_id;
INSERT ALL INTO sales_info VALUES (employee_id ,week_id ,sales_mon) INTO sales_info VALUES (employee_id ,week_id ,sales_tue) INTO sales_info VALUES (employee_id ,week_id ,sales_wed) INTO sales_info VALUES (employee_id ,week_id ,sales_thur) INTO sales_info VALUES (employee_id ,week_id ,sales_fri) SELECT employee_id ,week_id ,sales_mon ,sales_tue ,sales_wed ,sales_thur ,sales_fri FROM sales_source_data;
CREATE TABLE test_bin AS SELECT e.employee_id ,e.last_name FROM employees e; SELECT * FROM test_bin;
SELECT * FROM tab;
drop TABLE test_bin;
SELECT * FROM tab;
SELECT * FROM recyclebin;
SELECT * FROM "BIN$owBmXtYwQbGx1UIC/tv3kA==$0";
– 清空回收站,这次就真的得跑路了。。。。。
purge recyclebin;
CREATE TABLE test_bin AS SELECT e.employee_id ,e.last_name FROM employees e; SELECT * FROM test_bin; DROP TABLE test_bin PURGE; SELECT * FROM recyclebin;
CREATE TABLE timestamp_test_table AS
SELECT e.employee_id
,e.last_name
FROM employees e;
SELECT * FROM timestamp_test_table; – 查询数据是否插入,首先看看是有数据的哦,可别说我骗你
COMMIT;–DDL是已经带有commit功能的,这个提交是为了让你玩的放心
DELETE FROM timestamp_test_table;
COMMIT;
SELECT * FROM timestamp_test_table; – 这可是真的删了哦
SELECT * FROM timestamp_test_table AS OF TIMESTAMP SYSDATE-1/(2460);
– 下面这句是查询二十分钟之前的数据库的东西(时间自己把控)
SELECT * FROM timestamp_test_table AS OF TIMESTAMP SYSDATE-20/(24*60);
###基于会话
CREATE global temporary TABLE temp_table_session
(tid NUMBER,tname VARCHAR2(20))
ON COMMIT preserve rows;
插入数据
INSERT INTO temp_table_session
SELECT e.employee_id
,e.last_name
FROM employees e;
SELECT * FROM temp_table_session;
COMMIT;
SELECT * FROM temp_table_session;
重新开启一个会话或者重启客户端,重新连接,随你
SELECT * FROM temp_table_session;–查不到数据啦。。。。
###基于事务
CREATE global temporary TABLE temp_table_session2
(tid NUMBER,tname VARCHAR2(20)) ON COMMIT DELETE ROWS;
INSERT INTO temp_table_session2
SELECT e.employee_id
,e.last_name
FROM employees e;
SELECT * FROM temp_table_session2;
COMMIT;
SELECT * FROM temp_table_session2;