系列文章目录

【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事
【SQL开发实战技巧】系列(二):简单单表查询
【SQL开发实战技巧】系列(三):SQL排序的那些事
【SQL开发实战技巧】系列(四):从执行计划讨论UNION ALL与空字符串&UNION与OR的使用注意事项
【SQL开发实战技巧】系列(五):从执行计划看IN、EXISTS 和 INNER JOIN效率,我们要分场景不要死记网上结论
【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放
【SQL开发实战技巧】系列(七):从有重复数据前提下如何比较出两个表中的差异数据及对应条数聊起
【SQL开发实战技巧】系列(八):聊聊如何插入数据时比约束更灵活的限制数据插入以及怎么一个insert语句同时插入多张表
【SQL开发实战技巧】系列(九):一个update误把其他列数据更新成空了?Merge改写update!给你五种删除重复数据的写法!
【SQL开发实战技巧】系列(十):从拆分字符串、替换字符串以及统计字符串出现次数说起
【SQL开发实战技巧】系列(十一):拿几个案例讲讲translate|regexp_replace|listagg|wmsys.wm_concat|substr|regexp_substr常用函数
【SQL开发实战技巧】系列(十二):三问(如何对字符串字母去重后按字母顺序排列字符串?如何识别哪些字符串中包含数字?如何将分隔数据转换为多值IN列表?)
【SQL开发实战技巧】系列(十三):讨论一下常用聚集函数&通过执行计划看sum()over()对员工工资进行累加
【SQL开发实战技巧】系列(十四):计算消费后的余额&计算银行流水累计和&计算各部门工资排名前三位的员工
【SQL开发实战技巧】系列(十五):查找最值所在行数据信息及快速计算总和百之max/min() keep() over()、fisrt_value、last_value、ratio_to_report
【SQL开发实战技巧】系列(十六):数据仓库中时间类型操作(初级)日、月、年、时、分、秒之差及时间间隔计算
【SQL开发实战技巧】系列(十七):数据仓库中时间类型操作(初级)确定两个日期之间的工作天数、计算—年中周内各日期出现次数、确定当前记录和下一条记录之间相差的天数
【SQL开发实战技巧】系列(十八):数据仓库中时间类型操作(进阶)INTERVAL、EXTRACT以及如何确定一年是否为闰年及周的计算
【SQL开发实战技巧】系列(十九):数据仓库中时间类型操作(进阶)如何一个SQL打印当月或一年的日历?如何确定某月内第一个和最后—个周内某天的日期?
【SQL开发实战技巧】系列(二十):数据仓库中时间类型操作(进阶)获取季度开始结束时间以及如何统计非连续性时间的数据
【SQL开发实战技巧】系列(二十一):数据仓库中时间类型操作(进阶)识别重叠的日期范围,按指定10分钟时间间隔汇总数据
【SQL开发实战技巧】系列(二十二):数仓报表场景☞ 从分析函数效率一定快吗聊一聊结果集分页和隔行抽样实现方式
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高
【SQL开发实战技巧】系列(二十四):数仓报表场景☞通过案例执行计划详解”行转列”,”列转行”是如何实现的
【SQL开发实战技巧】系列(二十五):数仓报表场景☞结果集中的重复数据只显示一次以及计算部门薪资差异高效的写法以及如何对数据进行快速分组
【SQL开发实战技巧】系列(二十六):数仓报表场景☞聊聊ROLLUP、UNION ALL是如何分别做分组合计的以及如何识别哪些行是做汇总的结果行


文章目录

  • 系列文章目录
  • 前言
  • 一、一个update把其他列数据清空了?
  • 二、使用merge更新合并记录
  • 三、删除违反参照完整性的记录
  • 四、给你删除重复数据的五种写法
  • 总结

前言

本篇文章讲解的主要内容是:你有没有经历过一个update把其他列数据清空了、使用merge更新合并记录、删除违反参照完整性的记录、给你五种删除重复数据的写法
【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。


一、一个update把其他列数据清空了?

如标题,没开玩笑。工作中很容易出现这种情况,博主就遇到过很多同事这样做了。
拿个案例讲解吧!

create table empd as select * from emp;
alter table empd add dname varchar2(20) default 'default';
SQL> select * from empd;EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO DNAME
----- ---------- --------- ----- ----------- --------- --------- ------ --------------------7369 SMITH      CLERK      7902 1980-12-17     800.00               20 default7499 ALLEN      SALESMAN   7698 1981-2-20     1600.00    300.00     30 default7521 WARD       SALESMAN   7698 1981-2-22     1250.00    500.00     30 default7566 JONES      MANAGER    7839 1981-4-2      2975.00               20 default7654 MARTIN     SALESMAN   7698 1981-9-28     1250.00   1400.00     30 default7698 BLAKE      MANAGER    7839 1981-5-1      2850.00               30 default7782 CLARK      MANAGER    7839 1981-6-9      2450.00               10 default7788 SCOTT      ANALYST    7566 1987-4-19     3000.00               20 default7839 KING       PRESIDENT       1981-11-17    5000.00               10 default7844 TURNER     SALESMAN   7698 1981-9-8      1500.00      0.00     30 default7876 ADAMS      CLERK      7788 1987-5-23     1100.00               20 default7900 JAMES      CLERK      7698 1981-12-3      950.00               30 default7902 FORD       ANALYST    7566 1981-12-3     3000.00               20 default7934 MILLER     CLERK      7782 1982-1-23     1300.00               10 default1001 test                       2021-10-9 1                            default15 rows selected

接下来有个需求:只更新部门(10:ACCOUNTING,20:RESEARCH)的数据。其他未更新的部门名称应该保持为default不变。
大家会不会这么写这个SQL?

update empdset dname =(select dnamefrom deptwhere dept.deptno = empd.deptnoand dept.deptno in (10, 20));

好,看下这个sql的执行结果:

SQL> update empd2     set dname =3         (select dname4            from dept5           where dept.deptno = empd.deptno6             and dept.deptno in (10, 20));15 rows updatedSQL> select * from empd;EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO DNAME
----- ---------- --------- ----- ----------- --------- --------- ------ --------------------7369 SMITH      CLERK      7902 1980-12-17     800.00               20 RESEARCH7499 ALLEN      SALESMAN   7698 1981-2-20     1600.00    300.00     30 7521 WARD       SALESMAN   7698 1981-2-22     1250.00    500.00     30 7566 JONES      MANAGER    7839 1981-4-2      2975.00               20 RESEARCH7654 MARTIN     SALESMAN   7698 1981-9-28     1250.00   1400.00     30 7698 BLAKE      MANAGER    7839 1981-5-1      2850.00               30 7782 CLARK      MANAGER    7839 1981-6-9      2450.00               10 ACCOUNTING7788 SCOTT      ANALYST    7566 1987-4-19     3000.00               20 RESEARCH7839 KING       PRESIDENT       1981-11-17    5000.00               10 ACCOUNTING7844 TURNER     SALESMAN   7698 1981-9-8      1500.00      0.00     30 7876 ADAMS      CLERK      7788 1987-5-23     1100.00               20 RESEARCH7900 JAMES      CLERK      7698 1981-12-3      950.00               30 7902 FORD       ANALYST    7566 1981-12-3     3000.00               20 RESEARCH7934 MILLER     CLERK      7782 1982-1-23     1300.00               10 ACCOUNTING1001 test                       2021-10-9 1                            15 rows selectedSQL> rollback;

可以看到,这个语句是对全表做更新,而不是需求所说的部门(10:ACCOUNTING,20:RESEARCH),而且因为部门(30:SALES)没有匹配到的数据,dname均被更新为NULL值了。
可以想象,在生产环境中,大量的数据被清空或改错是多扯淡的行为(DBA肯定背地问候你)?原因在于该语句中少了必要的过滤条件。
以上UPDATE语句的结果及错误用查询语句描述如下:

select deptno,dname as old_dname,(select dnamefrom deptwhere dept.deptno = empd.deptnoand dept.deptno in (10, 20)) as new_name,casewhen empd.deptno not in (10, 20) then'无辜的行'end as desfrom empd;
DEPTNO OLD_DNAME            NEW_NAME       DES
------ -------------------- -------------- --------20 default              RESEARCH       30 default                             无辜的行30 default                             无辜的行20 default              RESEARCH       30 default                             无辜的行30 default                             无辜的行10 default              ACCOUNTING     20 default              RESEARCH       10 default              ACCOUNTING     30 default                             无辜的行20 default              RESEARCH       30 default                             无辜的行20 default              RESEARCH       10 default              ACCOUNTING     default                             15 rows selected

正确的思路是要加上限定条件的!!!

select deptno,dname as old_dname,(select dnamefrom deptwhere dept.deptno = empd.deptnoand dept.deptno in (10, 20)) as new_name,casewhen empd.deptno not in (10, 20) then'无辜的行'end as desfrom empdwhere exists(select dnamefrom deptwhere dept.deptno = empd.deptnoand dept.deptno in (10, 20));
DEPTNO OLD_DNAME            NEW_NAME       DES
------ -------------------- -------------- --------20 default              RESEARCH       20 default              RESEARCH       10 default              ACCOUNTING     20 default              RESEARCH       10 default              ACCOUNTING     20 default              RESEARCH       20 default              RESEARCH       10 default              ACCOUNTING     8 rows selected

同样的正确的update语句应该这么来:

SQL> update empd2     set dname =3         (select dname4            from dept5           where dept.deptno = empd.deptno6             and dept.deptno in (10, 20))7    where exists(8    select dname9            from dept10           where dept.deptno = empd.deptno11             and dept.deptno in (10, 20)12    );8 rows updatedSQL> select * from empd;EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO DNAME
----- ---------- --------- ----- ----------- --------- --------- ------ --------------------7369 SMITH      CLERK      7902 1980-12-17     800.00               20 RESEARCH7499 ALLEN      SALESMAN   7698 1981-2-20     1600.00    300.00     30 default7521 WARD       SALESMAN   7698 1981-2-22     1250.00    500.00     30 default7566 JONES      MANAGER    7839 1981-4-2      2975.00               20 RESEARCH7654 MARTIN     SALESMAN   7698 1981-9-28     1250.00   1400.00     30 default7698 BLAKE      MANAGER    7839 1981-5-1      2850.00               30 default7782 CLARK      MANAGER    7839 1981-6-9      2450.00               10 ACCOUNTING7788 SCOTT      ANALYST    7566 1987-4-19     3000.00               20 RESEARCH7839 KING       PRESIDENT       1981-11-17    5000.00               10 ACCOUNTING7844 TURNER     SALESMAN   7698 1981-9-8      1500.00      0.00     30 default7876 ADAMS      CLERK      7788 1987-5-23     1100.00               20 RESEARCH7900 JAMES      CLERK      7698 1981-12-3      950.00               30 default7902 FORD       ANALYST    7566 1981-12-3     3000.00               20 RESEARCH7934 MILLER     CLERK      7782 1982-1-23     1300.00               10 ACCOUNTING1001 test                       2021-10-9 1                            default15 rows selectedSQL> rollback;

好了,这样更新就对了,当然了我们还可以通过更新VIEW方式去实现这个需求,将需要被更新的数据范围查出来然后update这个view,或则使用merge方式去实现,我这里给一个merge的更新sql:

merge into empd aa
using (select deptno, dname from dept where dept.deptno in (10, 20)) dd
on (aa.deptno = dd.deptno)
when matched thenupdate set aa.dname = dd.dname;

我为什么只给merge的呢,一因为update view的方式类似,二的话,咱们看下update语句和merge语句的执行计划:

 Plan Hash Value  : 1616490401 --------------------------------------------------------------------------------------
| Id  | Operation                         | Name    | Rows | Bytes | Cost | Time     |
--------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT                   |         |    9 |   405 |    5 | 00:00:01 |
|   1 |   MERGE                           | EMPD    |      |       |      |          |
|   2 |    VIEW                           |         |      |       |      |          |
| * 3 |     HASH JOIN                     |         |    9 |   441 |    5 | 00:00:01 |
|   4 |      INLIST ITERATOR              |         |      |       |      |          |
|   5 |       TABLE ACCESS BY INDEX ROWID | DEPT    |    2 |    26 |    2 | 00:00:01 |
| * 6 |        INDEX UNIQUE SCAN          | PK_DEPT |    2 |       |    1 | 00:00:01 |
| * 7 |      TABLE ACCESS FULL            | EMPD    |    9 |   324 |    3 | 00:00:01 |
--------------------------------------------------------------------------------------Predicate Information (identified by operation id):
------------------------------------------
* 3 - access("AA"."DEPTNO"="DEPTNO")
* 6 - access("DEPT"."DEPTNO"=10 OR "DEPT"."DEPTNO"=20)
* 7 - filter("AA"."DEPTNO"=10 OR "AA"."DEPTNO"=20)

在回头看下正确的update的执行计划:

 Plan Hash Value  : 430611376 ------------------------------------------------------------------------------------
| Id  | Operation                       | Name    | Rows | Bytes | Cost | Time     |
------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT                |         |    9 |   351 |   21 | 00:00:01 |
|   1 |   UPDATE                        | EMPD    |      |       |      |          |
|   2 |    NESTED LOOPS                 |         |    9 |   351 |    3 | 00:00:01 |
| * 3 |     TABLE ACCESS FULL           | EMPD    |    9 |   324 |    3 | 00:00:01 |
| * 4 |     INDEX UNIQUE SCAN           | PK_DEPT |    1 |     3 |    0 | 00:00:01 |
| * 5 |    FILTER                       |         |      |       |      |          |
|   6 |     TABLE ACCESS BY INDEX ROWID | DEPT    |    1 |    13 |    1 | 00:00:01 |
| * 7 |      INDEX UNIQUE SCAN          | PK_DEPT |    1 |       |    0 | 00:00:01 |
------------------------------------------------------------------------------------Predicate Information (identified by operation id):
------------------------------------------
* 3 - filter("EMPD"."DEPTNO"=10 OR "EMPD"."DEPTNO"=20)
* 4 - access("DEPT"."DEPTNO"="EMPD"."DEPTNO")
* 4 - filter("DEPT"."DEPTNO"=10 OR "DEPT"."DEPTNO"=20)
* 5 - filter(10=:B1 OR 20=:B1)
* 7 - access("DEPT"."DEPTNO"=:B1)
* 7 - filter("DEPT"."DEPTNO"=10 OR "DEPT"."DEPTNO"=20)

从上面执行计划你能看到,使用merge只读了一次dept表!!!如果是大表的话肯定这个快嘛

二、使用merge更新合并记录

前面介绍了MERGE INTO的好处,那么怎么使用呢?下面用注释及等价改写的方式来介绍

merge into empd aa --只更新这个表
using dept dd  --用来更新aa表的表
on (aa.deptno = dd.deptno)--两个表更新时候的关联条件
--匹配条件aa.deptno = dd.deptno
when matched then--当aa表中存在与dd表对应数据时进行update or deleteupdate set aa.dname = dd.dname   --这里update的范围就是(aa.deptno = dd.deptno)的范围减去被删掉的 aa.comm is null的结果delete where aa.comm is null --where 在matched中只能出现一次,如果这里出现了那update哪里再出现的话,delete的where 条件这个无效,删除时候,只更新comm is null 的数据
when not matched then--当不满足匹配条件aa.deptno = dd.deptno的数据进行下面操作insert(empno,deptno,dname)values(dd.deptno, dd.deptno,dd.dname)where(dd.loc is not null) --新增的时候只更新loc is not null的数据,注意这里是aa表中不存在对应数时候才新增EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO DNAME
----- ---------- --------- ----- ----------- --------- --------- ------ --------------------7499 ALLEN      SALESMAN   7698 1981-2-20     1600.00    300.00     30 SALES7521 WARD       SALESMAN   7698 1981-2-22     1250.00    500.00     30 SALES7654 MARTIN     SALESMAN   7698 1981-9-28     1250.00   1400.00     30 SALES7844 TURNER     SALESMAN   7698 1981-9-8      1500.00      0.00     30 SALES1001 test                       2021-10-9 1                            default40                                                                40 OPERATIONS6 rows selected

三、删除违反参照完整性的记录

创建测试用表:

create table empc as select * from emp;
create table deptc as select * from dept;
alter table empcadd constraint pk_empc primary key (EMPNO);
alter table deptcadd constraint pk_deptc primary key (deptno);
insert into empc(empno,ename,deptno)values(1221,'zhaoyd',50);

当我们增加如下外键时,会因数据违反完整性而报错:

SQL> alter table empc2    add constraint FK_DEPTNO foreign key (DEPTNO)3    references deptc (DEPTNO);
ORA-02298: 无法验证 (ZYD.FK_DEPTNO) - 未找到父项关键字

这种提示在处理业务时会经常遇到,是因为子表中的数据(deptno:50)与主表不一致(主表中没有deptno:50)引起的。
这时就要处理违反完整性的数据,要根据情况选择在主表中加入数据,或删除子表中的数据。下面选择删除子表中的数据(注意,删除前后要核对数据后再提交,严格地说,应该要先备份表中的数据,再做删除操作):

delete from empc where not exists (
select null
from deptc
where empc.deptno=deptc.deptno
);

删除数据后再次添加外键约束就可以了!

alter table empc
add constraint FK_DEPTNO foreign key (DEPTNO)
references deptc (DEPTNO);

这时候如果再在emp表添加一条dept表没有的部门员工,就会报错了

SQL>  insert into empc(empno,ename,deptno)values(1221,'zhaoyd',50);
ORA-02291: 违反完整约束条件 (ZYD.FK_DEPTNO) - 未找到父项关键字

四、给你删除重复数据的五种写法

先创建测试数据

create table deptf as select * from dept;
insert into deptf  where deptno>10;
commit;

下面几种写法,需要根据你的数据分布情况来挑选着使用。

  • 第一种,自关联删除
delete from dept aawhere exists (select nullfrom dept bbwhere aa.deptno > bb.deptnoand aa.loc = bb.locand aa.dname = bb.dname);
  • 第二种,通过rowid来删除
delete from dept aawhere exists (select nullfrom dept bbwhere aa.rowid > bb.rowidand aa.loc = bb.locand aa.dname = bb.dname);
  • 第三种,通过分析函数生成序号+rowid删除
delete from deptwhere rowid in (select ridfrom (select rowid rid,row_number() over(partition by dname order by deptno) as rnfrom dept)where rn > 1);
  • 第四种,变种,改写成exists删除
delete from deptwhere exists (select nullfrom (select ridfrom (select rowid rid,row_number() over(partition by dname order by deptno) as rnfrom dept)where rn > 1) ffwhere ff.rid = dept.rowid);
  • 第五种,变种,改写成not exists删除
delete from deptwhere not exists (select nullfrom (select ridfrom (select rowid rid,row_number() over(partition by dname order by deptno) as rnfrom dept)where rn = 1) ffwhere ff.rid = dept.rowid);

其他写法自行研究
[]( ̄▽ ̄)*

【SQL开发实战技巧】系列(九):一个update误把其他列数据更新成空了?Merge改写update!给你五种删除重复数据的写法!相关推荐

  1. 【SQL开发实战技巧】系列(十九):数据仓库中时间类型操作(进阶)如何一个SQL打印当月或一年的日历?如何确定某月内第一个和最后—个周内某天的日期?

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

  2. 【SQL开发实战技巧】系列(八):聊聊如何插入数据时比约束更灵活的限制数据插入以及怎么一个insert语句同时插入多张表

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

  3. 【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

  4. 【SQL开发实战技巧】系列(十):从拆分字符串、替换字符串以及统计字符串出现次数说起

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

  5. 【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

  6. 【SQL开发实战技巧】系列(三):SQL排序的那些事

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

  7. 【SQL开发实战技巧】系列(五):从执行计划看IN、EXISTS 和 INNER JOIN效率,我们要分场景不要死记网上结论

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

  8. 【SQL开发实战技巧】系列(七):从有重复数据前提下如何比较出两个表中的差异数据及对应条数聊起

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

  9. 【SQL开发实战技巧】系列(二):简单单表查询

    系列文章目录 [SQL开发实战技巧]系列(一):关于SQL不得不说的那些事 [SQL开发实战技巧]系列(二):简单单表查询 [SQL开发实战技巧]系列(三):SQL排序的那些事 [SQL开发实战技巧] ...

最新文章

  1. python yaml配置文件_python读取yaml配置文件
  2. 哨兵机器人钢力士_哨兵胳膊都被卸了?巴西厂X战警钢力士正式公布
  3. ORACLE会话以及SQL执行信息查询
  4. 独家总结| 一文读懂卡尔曼滤波
  5. Spark学习笔记:索引分区映射
  6. [刷题]算法竞赛入门经典(第2版) 5-2/UVa1594 - Ducci Sequence
  7. Sharding-JDBC水平分库(水平数据库分片策略配置)_Sharding-Sphere,Sharding-JDBC分布式_分库分表工作笔记010
  8. 【数字信号去噪】基于matlab中值滤波+奇异值分解(SVD)数字信号降噪【含Matlab源码 1021期】
  9. 一个js内存泄露的好例子
  10. DEVELOPMENT OF A LOW-COST VISION SYSTEM FOR FINDING CONTOUR AND SURFACE DEFECTS ON CAST IRON ENGINE
  11. 手撸CAPL(二)——OSEK网络管理N个节点建环机制(包含节点建环/丢失/跳过等)代码自取
  12. 机载激光雷达原理与应用科普(一)
  13. 13丨性能测试场景:如何进行场景设计
  14. 如何通过简书引流(简书引流之标题的重要性)万能的小胡
  15. 论黑客必知DOS命令技术大拳!
  16. 华夏文化-让你心醉又心碎的陶笛--故乡的原风景
  17. [Android]DDMS查看app保存的Sqlite数据库db文件和db升级
  18. 《超越对手-大项目售前售后的30种实战技巧》读书心得
  19. 【阿里聚安全·移动安全周刊】移动裸奔时代,手机已成为隐私的监视器
  20. 《CTF竞赛权威指南》|Off-By-One

热门文章

  1. 计算机毕业设计php的菜品食谱美食网
  2. 信通院魏亮:产业数字化让传统赛道产生新赛道
  3. 为高性价比代言的HKC神盾MG25H电竞显示器
  4. 吉林大学Linux考试时间,《吉林大学软件学院10级Linux试题A.doc
  5. 金山毒霸2006完美梦幻无限期升级版(8月31号更新)
  6. postgresql dba常用sql查询语句
  7. html css怎么做太阳,Html+css编写太阳星系
  8. Android使用svg矢量图
  9. 技术点详解---双链路智能切换--h3c NQA(Network Quality Analysis)
  10. AFL源码分析之afl-fuzz(学习笔记)(一)