面试篇三:数据库MySQLOracle

Posted 时光编辑师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试篇三:数据库MySQLOracle相关的知识,希望对你有一定的参考价值。

  • MySQL
  • MySQL分页查询
SELECT * FROM admin_company LIMIT 0,10;
SELECT * FROM admin_company ORDER BY id LIMIT 0,10;

limit后参数代表什么意思?

LIMIT[位置偏移量,]行数,第一个参数是从哪个序号加上,初始是0,第二个参数是查询多少行记录。

还有没有其他方式?

  • MySQL怎么查看执行计划

用explain,如 SELECT * FROM admin_company 

https://www.cnblogs.com/scorpio-cat/p/12661216.html

mysql索引

索引分类:主键索引、唯一索引、普通索引、全文索引、组合索引。

  MySQL默认会对主键和唯一键列创建索引。

       MySQL在创建表时就会创建一主键索引。如果主键存在,则存主键;如果主键不存在,但唯一键存在,则存唯一健;如果主键和唯一健都不存在,则存6个字节的rowid。

索引的优点:减少服务器需要扫描的数据量、帮助服务器避免排序和临时表、将随机io变成顺序io。

索引匹配方式:

(1)全值匹配:where条件为=。

(2)最左前缀匹配:组合索引时,SQL必须包括组合索引指定的第一列;如果不存在,则不会走索引。

(3)列前缀匹配:使用like模糊查询,like \'123%\'。

(4)范围值匹配:between and,> , <,但是索引中,如果包括了范围判断,则会导致后面的查询条件不走索引,只有前面的列和该范围列走索引。

(5)精确匹配某一列并范围匹配另一列。

(6)只访问索引的查询。

https://www.cnblogs.com/scorpio-cat/p/12661379.html

  • Oracle
  • Oracle分页查询
SELECT * FROM
    (SELECT ROWNUM rn ,* FROM admin_company WHERE rn <= 10)
 WHERE rn > 0; 

没有ORDER BY,两层查询;如果要排序使用上面两层查询,会出现什么问题?查询结果有问题。

ROWNUM伪列产生的序号是按照数据被查询出来的顺序添加上去的,第一条是1,第二条是2,依次加1。

在ORACLE中使用rownum伪列分页时,需要多加一层查询,以保证rownum序号的连续性。

SELECT * FROM 
  (SELECT ROWNUM rn , c.* FROM
    (SELECT * FROM admin_company ORDER BY companyno) c WHERE rn <= 10
  )
 WHERE rn > 0; 

当将一条语句交给查询优化器处理时:

如果排序列上有索引,则借助索引去查询数据,这样,读取出来的数据和rownum产生的序号是一种正常的对应关系。

如果排序列上没有索引,则使用全表扫描的方式,依次从表中读取数据,读取完成后,最后进行排序,可能产生的rownum序号不连续。

正是由于排序列上不一定有索引,所以在ORACLE中使用rownum伪列分页时,需要多加一层查询,以保证rownum序号的连续性。

  •  Oracle怎么查询执行计划

(1)通过使用工具PLSQL Developer中的Explain Plan Window窗口查看SQL执行计划。快捷键为F5。

(2)通过explain plan for explain plan for select *admin_company;

  • Oracle触发器

Oracle触发器是在事务发生时。隐式地自动执行的PL/SQL代码块,没有参数。

create or replace trigger trigger_name
 before insert on table_name
for each row
declare
next_id number;
begin
  select seq_test.nextval into next_id from dual; 
  :new.id :=next_id;
  insert into op_log values(1,\'insert\',sysdate,:next_id);
end;
  • Oracle存储过程

oracle存储过程,是用于完成一组特定功能的SQL合集。可以有参数,也可以无参数。

CREATE OR REPLACE PROCEDURE 存储过程名称
(      s_no in varchar,
       s_name out varchar,
       s_age number
) AS 
total NUMBER := 0;
BEGIN
  SELECT COUNT(1) INTO total FROM student s WHERE s.age=s_age;       
dbms_output.put_line(\'符合该年龄的学生有\'||total||\'\'); EXCEPTION WHEN too_many_rows THEN DBMS_OUTPUT.PUT_LINE(\'返回值多于1行\'); END

存储过程原文 https://blog.csdn.net/weixin_41968788/article/details/83659164

  •  Oracle游标
create or replace procedure proc_name is
  v_date date; --定义变量
  cursor cur is select * from ldcode where rownum<10; --定义游标
begin
  select sysdate into v_date from dual;
  --游标for循环开始
  for temp in cur loop --temp为临时变量名,自己任意起
    Dbms_Output.put_line(temp.Code); --输出某个字段,使用"变量名.列名"即可。
  end loop;
  --游标for循环结束
end proc_name;

 

索引

作用:提高查询速度、确保数据的唯一性、可以加速表和表之间的连接,实现表和表之间的参照完整性、使用分组和排序子句进行数据检索时,可以减少分组和排序的时间、全文检索字段进行搜素优化。

分类:主键索引(PRIMAY KEY)、唯一索引(UNIQUE)、常规索引(INDEX)、全文索引(FULLTEXT)。

主键索引的几种创建方式:确保数据记录的唯一性,主键索引只能有一个。(以下为MYSQL示例)

CREATE TABLE mytable (
  ID INT(11) AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR (16) NOT NULL
  #或 PRIMARY KEY(`ID`)
) ;

唯一索引的几种创建方式:避免同一个表中某数据列中的值重复,唯一索引可有多个。(以下为MYSQL示例)

(1)创建索引:  CREATE UNIQUE INDEX indexName ON mytable(username(length));  

(2)修改表结构:  ALTER table mytable ADD UNIQUE [indexName] (username(length));  

(3)创建表时指定:

CREATE TABLE mytable (
  ID INT NOT NULL,
  username VARCHAR (16) NOT NULL,
  UNIQUE [ indexName ] (username (LENGTH)) 
  # 或者username VARCHAR(16) NOT NULL UNIQUE
) ;

常规索引的几种创建方式:快速定位特定数据,应加在查询条件的字段,不易添加太多常规索引,影响数据的插入,删除和修改操作,使用KEY或INDEX关键字设置。(以下为MYSQL示例)

(1)创建表时添加:

CREATE TABLE mytable (
  ID INT NOT NULL,
  userno VARCHAR (16) NOT NULL,
  username VARCHAR (16) NOT NULL,
  loginname VARCHAR (16) NOT NULL,
  INDEX `index1` (userno, username),
  KEY `index2` (userno, loginname)
) ;

(2)创建后追加:  ALTER TABLE `mytable` ADD INDEX `ind` (`userno`,`username`);  

全文索引的几种创建方式:快速定位特定数据,只能用于MyISAM类型的数据表,只能用于CHAR ,VARCHAR,TEXT数据列类型。(以下为MYSQL示例)

(1)创建表时添加:

CREATE TABLE mytable(
 username VARCHAR (16) NOT NULL,
 FULLTEXT(`username`)
)ENGINE=MYISAM;

(2)创建后追加:  ALTER TABLE mytable ADD FULLTEXT(`username`); 

SQL怎么优化执行效率更高、SQL优化经验

(1)SELECT子句中避免使用‘*’:Oracle在解析的过程中, 会将‘*’依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间。

(2)使用表的别名(Alias): 当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上。这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。

(3)用IN来替换OR、用UNION替换OR (适用于索引列)、用EXISTS替代IN、用NOT EXISTS替代NOT IN。

(4)如果不需要去重,用UNION-ALL 替换UNION:UNION 将对结果集合进行合并和排序,这个操作会使用到SORT_AREA_SIZE这块内存,UNION ALL 将重复输出两个结果集合中相同记录,排序也不是必要的,效率就会因此得到提高。

(5)优化GROUP BY:提高GROUP BY 语句的效率,可以通过将不需要的记录在GROUP BY 之前过滤掉。

(6)使用DECODE函数来减少处理时间。【TODO】

(7)用Where子句替换HAVING子句:HAVING 只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序,总计等操作。

(8)合理使用索引:

  ①避免在索引列上使用NOT,当Oracle“遇到”NOT,他就会停止使用索引转而执行全表扫描。

  ②避免在索引列使用 !=、||、+,WHERE子句中,优化器将不使用索引而使用全表扫描。

  ③避免在索引列上使用计算。WHERE子句中,如果索引列是函数的一部分。优化器将不使用索引而使用全表扫描。

  ④避免在索引中使用任何可以为空的列,Oracle将无法使用该索引。对于单列索引,如果列包含空值,索引中将不存在此记录。对于复合索引,如果每个列都为 空,索引中同样不存在此记录。如果至少有一个列不为空,则记录存在于索引中。

  ⑤总是使用索引的第一个列:如果索引是建立在多个列上,只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引。这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略 了索引。 

  ⑥避免对WHERE子句的列名使用函数(避免改变索引列的类型):当比较不同数据类型的数据时,如

SELECT * FROM EMP WHERE EMPNO = TO_NUMBER(\'123\'); #类型转换没有发生在索引列上,索引的用途没有被改
SELECT * FROM EMP WHERE TO_NUMBER(EMPNO)=123; #类型转换发生在索引列上,索引失效

MySQL和Oracle的区别

链接https://www.cnblogs.com/xu-cceed3w/p/8824199.html https://www.jianshu.com/p/eb4e6c026035?utm_source=oschina-app

(1)分页查询,mysql是limit,oracle是rownum和嵌套查询。

(2)自增:oracle需建立一个自动增长的序列号,插入记录时要把序列号的下一个值赋于此字段;mysql有自动增长的数据类型:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT,使用AUTO_INCREMENT。

(3)默认的事务隔离级别:mysql是RR,oracle是RC。mysql默认是自动提交,而Oracle默认不自动提交,需要用户手动提交。

(4)保存数据的持久性:mysql是在数据库更新或者重启,则会丢失数据;Oracle把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,可以随时恢复。

(5)锁的区别:mysql的行级锁依赖于索引,如果sql没有使用索引,则仍然是表级锁。oracle行级锁是在数据库中的数据行上,不依赖与索引。

(6)mysql是轻量级,免费;oracle是重量级,收费。

(7)oracle对数据恢复、异常应对、管理工具、诊断性能调优等更加出色,mysql不够完善。

(8)语法异同:

递归查询,oracle支持start with … connect by prior id = pId,mysql不支持。

对于null返回0,oracle使用nvl函数nvl(参数,0),mysql使用IFNULL(参数,0)函数。

列转行,Oracle列转行函数可以用vm_comcat函数,mysql的用concat_ws函数。

对时间处理,Oracle是to_date(\'2020-04-12 12:37:13\', \'yyyy-mm-dd hh24:mi:ss\'),Mysql是str_to_date(\'2020-04-12 12:37:13\', \'%Y-%m-%d %H:%i:%s\')。

拼接字符串,oracle可使用||,mysql没有,需使用函数concat(str1,str2,...)或concat_ws(分隔符,str1,str2,...)。

以上是关于面试篇三:数据库MySQLOracle的主要内容,如果未能解决你的问题,请参考以下文章

初识JDBC-篇三

垃圾收集器与内存分配策略之篇三:理解GC日志和垃圾收集器参数总结

Socket编程篇三

spring事物源码分析篇三:业务代码的执行--事物增强器

面试常用的代码片段

面向面试编程代码片段之GC