mysql oracle 查询语句执行顺序_Oracle(二)SELECT语句执行顺序

目录

一、样例

二、SELECT语句的处理过程

1. FROM阶段

2. WHERE阶段

3. GROUP BY阶段

4. HAVING阶段

5. SELECT阶段

6. ORDER BY阶段

三、样例解释

数据库SQL(Structure Query Language)包含3种类型的语言:DML(Data Manipulation Language)、DDL(Data Definition Language)和DCL(Data Control Language),其中使用最频繁的当属DML,DML包括4条具体的命令,它们是SELECT、UPDATE、INSERT、DELETE,就象它的名字一样,这4条命令是用来对数据库里的数据进行操作的语言。这4条命令中,使用最频繁的是SELECT命令,所有查询的操作都是通过它来获取数据库中的数据。但你是否有思考过,数据库执行SELECT命令的顺序是否与我们写出的SELECT命令的顺序一致?接下来,我们就来分析一下Oracle数据库执行SELECT命令的顺序。

先通过一个例子来看JOIN ON和WHERE执行结果的不同。

一、样例

CREATE TABLE"SCOTT"."A" (

"PERSON_ID"NUMBER(5) NULL,

"PERSON_NAME"VARCHAR2(255 BYTE) NULL)

;------------------------------

--Records of A

------------------------------

INSERT INTO "SCOTT"."A" VALUES ('1', '张三');INSERT INTO "SCOTT"."A" VALUES ('2', '李四');INSERT INTO "SCOTT"."A" VALUES ('3', '王五');INSERT INTO "SCOTT"."A" VALUES ('4', '赵六');INSERT INTO "SCOTT"."A" VALUES ('5', '周七');CREATE TABLE"SCOTT"."B" (

"PERSON_ID"NUMBER(5) NULL,

"LOVE_FRUIT"VARCHAR2(255 BYTE) NULL);------------------------------

--Records of B

------------------------------

INSERT INTO "SCOTT"."B" VALUES ('1', '香蕉');INSERT INTO "SCOTT"."B" VALUES ('2', '苹果');INSERT INTO "SCOTT"."B" VALUES ('3', '橘子');INSERT INTO "SCOTT"."B" VALUES ('4', '梨');INSERT INTO "SCOTT"."B" VALUES ('8', '桃');

查询语句1

SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID =B.PERSON_ID AND A.PERSON_ID =1;

25c601fccf44104e095fc42c44c4b2a9.png

查询语句2

SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID =B.PERSON_ID WHERE A.PERSON_ID =1;

e7da59d46b7506c2d99e050b589a4253.png

为什么结果不同呢?可以从查询逻辑处理的过程解释。

二、SELECT语句的处理过程

我们知道,SQL 查询的大致语法结构如下:

(5)SELECT DISTINCT TOP() (1)FROM JOIN ON (2)WHERE (3)GROUP BY (4)HAVING (6)ORDER BY

SELECT语法的处理顺序:

The following steps show the processing order for a SELECT statement.

FROM

ON

JOIN

WHERE

GROUP BY

WITH CUBE or WITH ROLLUP

HAVING

SELECT

DISTINCT

ORDER BY

TOP

这些步骤执行时,每个步骤都会产生一个虚拟表,该虚拟表被用作下一个步骤的输入。这些虚拟表对调用者(客户端应用程序或者外部查询)不可用。只是最后一步生成的表才会返回给调用者。如果没有在查询中指定某一子句,将跳过相应的步骤。

SELECT各个阶段分别干了什么:

1. FROM阶段

FROM阶段标识出查询的来源表,并处理表运算符。在涉及到联接运算的查询中(各种JOIN),主要有以下几个步骤:

求笛卡尔积。不论是什么类型的联接运算,首先都是执行交叉连接(CROSS JOIN),求笛卡儿积,生成虚拟表VT1-J1。

ON筛选器。  这个阶段对上个步骤生成的VT1-J1进行筛选,根据ON子句中出现的谓词进行筛选,让谓词取值为true的行通过了考验,插入到VT1-J2。

添加外部行。如果指定了OUTER JOIN,还需要将VT1-J2中没有找到匹配的行,作为外部行添加到VT1-J2中,生成VT1-J3。

经过以上步骤,FROM阶段就完成了。概括地讲,FROM阶段就是进行预处理的,根据提供的运算符对语句中提到的各个表进行处理(除了JOIN,还有APPLY,PIVOT,UNPIVOT)。

2. WHERE阶段

WHERE阶段是根据中条件对VT1中的行进行筛选,让条件成立的行才会插入到VT2中。

3. GROUP BY阶段

GROUP阶段按照指定的列名列表,将VT2中的行进行分组,生成VT3。最后每个分组只有一行。

4. HAVING阶段

该阶段根据HAVING子句中出现的谓词对VT3的分组进行筛选,并将符合条件的组插入到VT4中。

5. SELECT阶段

这个阶段是投影的过程,处理SELECT子句提到的元素,产生VT5。这个步骤一般按下列顺序进行:

计算SELECT列表中的表达式,生成VT5-1。

若有DISTINCT,则删除VT5-1中的重复行,生成VT5-2。

若有TOP,则根据ORDER BY子句定义的逻辑顺序,从VT5-2中选择签名指定数量或者百分比的行,生成VT5-3。

6. ORDER BY阶段

根据ORDER BY子句中指定的列明列表,对VT5-3中的行,进行排序,生成游标VC6。

三、样例解释

查询语句1的执行过程

SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID = B.PERSON_ID AND A.PERSON_ID = 1;

求笛卡尔积,产生5*5=25条记录

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

张三

1

香蕉

1

张三

2

苹果

1

张三

3

橘子

1

张三

4

1

张三

8

2

李四

1

香蕉

2

李四

2

苹果

2

李四

3

橘子

2

李四

4

2

李四

8

3

王五

1

香蕉

3

王五

2

苹果

3

王五

3

橘子

3

王五

4

3

王五

8

4

赵六

1

香蕉

4

赵六

2

苹果

4

赵六

3

橘子

4

赵六

4

4

赵六

8

5

周七

1

香蕉

5

周七

2

苹果

5

周七

3

橘子

5

周七

4

5

周七

8

ON筛选器(A.PERSON_ID=B.PERSON_ID AND A.PERSON_ID=1)

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

张三

1

香蕉

添加外部行

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

张三

1

香蕉

1

张三

1

张三

1

张三

1

张三

查询语句2的执行过程

SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID = B.PERSON_ID WHERE A.PERSON_ID = 1;

求笛卡尔积,产生5*5=25条记录

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

张三

1

香蕉

1

张三

2

苹果

1

张三

3

橘子

1

张三

4

1

张三

8

2

李四

1

香蕉

2

李四

2

苹果

2

李四

3

橘子

2

李四

4

2

李四

8

3

王五

1

香蕉

3

王五

2

苹果

3

王五

3

橘子

3

王五

4

3

王五

8

4

赵六

1

香蕉

4

赵六

2

苹果

4

赵六

3

橘子

4

赵六

4

4

赵六

8

5

周七

1

香蕉

5

周七

2

苹果

5

周七

3

橘子

5

周七

4

5

周七

8

ON筛选器 (A.PERSON_ID=B.PERSON_ID)

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

张三

1

香蕉

2

李四

2

苹果

3

王五

3

橘子

4

赵六

4

添加外部行

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

张三

1

香蕉

2

李四

2

苹果

3

王五

3

橘子

4

赵六

4

5

周七

WHERE阶段 (A.PERSON_ID=1)

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

张三

1

香蕉

有了上面的验证,我们可以猜测下面语句的执行结果

SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID =B.PERSON_ID;

30313eea3ec8f9fbd18d2dd45fbfbe14.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Java编写一个程序,通过JDBC连接Oracle数据库,读取其中的表和数据,然后将其转换为MySQL语法,并通过JDBC连接MySQL数据库,将数据写入其中。 下面是一个简单的代码示例: ```java import java.sql.*; public class OracleToMySQL { public static void main(String[] args) { String oracleUrl = "jdbc:oracle:thin:@localhost:1521:ORCL"; String oracleUser = "username"; String oraclePassword = "password"; String mysqlUrl = "jdbc:mysql://localhost:3306/mysql"; String mysqlUser = "root"; String mysqlPassword = "password"; try { // Connect to Oracle database Connection oracleConnection = DriverManager.getConnection(oracleUrl, oracleUser, oraclePassword); Statement oracleStatement = oracleConnection.createStatement(); // Connect to MySQL database Connection mysqlConnection = DriverManager.getConnection(mysqlUrl, mysqlUser, mysqlPassword); Statement mysqlStatement = mysqlConnection.createStatement(); // Read tables from Oracle ResultSet tables = oracleStatement.executeQuery("SELECT table_name FROM user_tables"); while (tables.next()) { String tableName = tables.getString(1); // Read columns from Oracle ResultSet columns = oracleStatement.executeQuery("SELECT column_name, data_type FROM user_tab_columns WHERE table_name = '" + tableName + "'"); StringBuilder createTableSql = new StringBuilder("CREATE TABLE " + tableName + " ("); while (columns.next()) { String columnName = columns.getString(1); String dataType = columns.getString(2); createTableSql.append(columnName + " " + dataType + ","); } createTableSql.setLength(createTableSql.length() - 1); createTableSql.append(")"); mysqlStatement.execute(createTableSql.toString()); // Read data from Oracle and insert into MySQL ResultSet data = oracleStatement.executeQuery("SELECT * FROM " + tableName); while (data.next()) { StringBuilder insertSql = new StringBuilder("INSERT INTO " + tableName + " VALUES ("); ResultSetMetaData metaData = data.getMetaData(); for (int i = 1; i <= metaData.getColumnCount(); i++) { String value = data.getString(i); insertSql.append("'" + value + "',"); } insertSql.setLength(insertSql.length() - 1); insertSql.append(")"); mysqlStatement.execute(insertSql.toString()); } } // Close connections mysqlStatement.close(); mysqlConnection.close(); oracleStatement.close(); oracleConnection.close(); } catch (SQLException e) { e.printStackTrace(); } } } ``` 需要注意的是,该代码仅供参考,实际应用中需要考虑更多的细节和异常情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值