前言

文本


PL/SQL



(Procedure Language,程序语言)SQL 1999主要的数据库供应商提供结构化的共同语言  PL/SQL只有支持Oracle数据库

基本的语法



多行凝视   /*    */      单行凝视   --

PLSQL程序块



结构


[declare]

定义变量

begin

过程语句

[exception]

处理 异常

end;





样例 输出helloworld





begin

  dbms_output.put_line('hello');

end;

--假设过程运行完没有输出,必须将server输出打开



运行

 

SQL> set serveroutput on/off;

SQL> 

SQL> begin

  2    dbms_output.put_line('hello');

  3  end;

  4  /

 

hello

 

PL/SQL procedure successfully completed

变量



declare

变量名称   变量类型;

begin



end;

标识符:不能以数字開始
长度不能超过30个字符

变量初始化


採用:= 进行赋值

v_age number(10) := 10;

变量类型



number(m,n)  数字类型

char()       固定长度字符串

varchar2()   可变长度字符串 

date         日期类型

boolean(true/false/null)      布尔类型

binary_integer  有符号整型

注意:布尔类型不能直接输出





代码演示样例

注意:变量名称不能是SQLkeyword,最好不要和表中字段同名

变量命名:

v_实际含义的单词

常量命名:

c_实际含义 

參数命名

p_实际含义

游标类型

名称_cursor

表类型

名称_table

记录类型

名称_record

变量作用域

变量从声明開始到相应模块的end结束为它的作用域



--变量作用域代码演示样例

变量的其它类型

1.表类型



定义表类型

type  表类型名称 is table  of  表类型存储的基本类型 index by binary_integer

声明变量为表类型

变量名称  表类型名称





表类型类似java中的数组,用来存储具有同种类型的数据









属性:

first  表示获得表类型的第一个下标

last   表示获得表类型的最后一个下标

count  表示表类型的数据个数

next(下标) 表示下一个下标

prior(下标) 表示前一个下标

代码演示样例:



表类型通过下标操作

2.记录类型



 用来存储一条记录

 type  记录类型名称 is record(field1 类型,field2 类型)

 定义变量,将变量类型设置成记录类型

 v_record 记录类型名称

代码演示样例

定义记录类型的简单方式



 %rowtype 定义记录类型

 表名%rowtype

代码演示样例
<div></div>

定义表类型的简单方式



 %type  定义表类型

 表名.字段名%type
代码演示样例


代码演示样例: 将表中的全部记录存在一个变量中

操作符

算数运算符



跟java一致

v_age number(3) := 0;



v_age := v_age +1;

比較运算符



>  < >= = 不等于!= <> ~= ^=

逻辑运算符



and or not 





between   and

赋值运算符



:=

流程控制

分支:



   1.if分支

     if  布尔表达式  then

     …………

     else

     …………

     end if;





   多个分支:

     if  布尔表达式  then

     …………

     elsif 布尔表达式 then

     …………

     elsif 布尔表达式 then

     …………

     else

     …………

     end if;





案例: --查找员工,依据职位进行工资的添加


2.case分支,类似java中的switch````case







case 变量

when 条件 then

语句·····

when 条件 then

语句·····

when 条件 then

语句·····

else

语句·····

end case;





案例

循环:

1.loop循环

定义一个循环指数

v_index binary_integer := 0;





loop

if v_index=循环次数 then

  exit;

end if;

循环体









循环指数自增

v_index := v_index+1;

 





end loop;



案例:

--loop循环

declare

--定义循环指数

v_index binary_integer :=1;

begin

--定义loop循环

loop

--定义推出循环的条件

if v_index=5 then

exit;

end if;

--运行循环体

dbms_output.put_line(v_index);

--循环指数自增

v_index := v_index+1;

end loop;

end;

2.for循环


定义一个循环指数 

v_index binary_integer;





for 循环指数 in 下限指数..上限指数 loop

循环体

end loop;





案例:

--for循环

注意:循环指数的開始一定要小于结束



通过reversekeyword实现循环反转



--for循环反转

declare

  v_index binary_integer;

begin

  for v_index in reverse 10..20 loop

  dbms_output.put_line(v_index);

  end loop;

end;

3.while循环




定义循环指数

v_index binary_integer := 1;



while 布尔表达式 loop

循环体

循环指数自增

end loop;





案例:

--while循环

declare

  v_index binary_integer := 1;

begin

  while v_index<5 loop

  dbms_output.put_line(v_index);

  v_index := v_index+1;

  end loop;

end;

循环嵌套



通过<<label>>标签方式来控制循环





案例:

4.goto跳转

PL/SQL中书写定义sql

1.DQL语言



select 语句要求:1.必须写intokeyword

2.查询语句仅仅能有一条返回值

异常演示样例: 没有值  no_data_found。值过多  too_many_rows

2.DML(insert/update/delete)




注意:运行DML语句要处理事务



动态传參

&+变量来实现动态传參





--运行DML语句

declare

begin

    --普通DML语句

    delete from emp where empno=&xx;

    --事务处理

    commit;

end;

3.DDL(create/drop/alter/truncate)



DDL语句要在 execute  immediate('DDL')

游标(cursor)




sql语句运行时会在内存中开辟一个区域。用来存放运行的sql语句以及返回的数据,我们把这个内存区域叫做上下文环境(context);游标就是指向这个上下文环境的指针。





游标分类


隐式游标:由数据库管理系统创建运行

显示游标:有程序猿负责创建运行和关闭的游标



游标的属性


%rowcount  存储的是游标运行时所影响的记录条数


操作属性


显示游标:自己定义游标名称%rowcount

隐式游标:sql%rowcount

%found  推断当前数据有没有下一条 true/fase

%notfound 推断当前数据有没有下一条 true/fase

%isopen  推断游标是否开启

显示游标



1.创建游标

cursor 游标名称 is 查询语句

2.开启游标

open 游标名称

3.获取数据

fetch 游标名称 into 变量

4.关闭游标

close 游标名称



案例:
--显示游标



for循环来循环游标


定义游标时传递參数

注意:设置形參时不要写參数的长度,实參是在开启游标的时候传递

     游标不能反复开启和关闭

定义游标类型的变量

1.定义游标类型



type 游标类型名称 is ref cursor return 返回结果类型

2.定义游标类型的变量

变量名称   游标类型名称

过程和函数



过程(procedure)又叫存储过程(stored procedure)。是一个有名称的PL/SQL程序块

过程相当于java中的方法。它注重的是实现某种业务功能

函数(function)也相当于java中的方法。它注重计算而且总是有返回结果

过程和函数都是可以永久存储在数据库中的程序代码块。应用时通过调用运行

过程的基本结构



create [or replace ] procedure 过程名称(形參名称  形參类型,形參名称  形參类型······)

is | as 

定义变量

begin

过程体

exception

异常

end;

1.含有输入參数的过程



输入參数  用in 标识  可省略

2.无參的过程

3.有输出參数的过程



输出參数用 out 标识

过程的调用

1.通过匿名块调用



输入參数

输出參数过程

无參的过程



begin

    mypro_noparam;

end;

2.命令行调用



调用输入參数

SQL> exec mypro(7788,3000);

输出參数

SQL> var v_sal number;   注冊变量

SQL> exec mypro(7788,:v_sal); :变量名称 使用变量接收输出

调用无參

SQL> exec mypro;



演示样例代码:

1.写一个过程封装emp表中的数据

2.写一个过程输入员工编号。通过游标获取输出该员工相应下属的信息

3./*计算100-200的素数*/

3.通过java调用过程

java调用过程代码演示样例


自己定义函数


function.sql代码演示样例



异常


系统异常分为提前定义异常和非提前定义异常
提前定义异常。是由数据库定义好。含有异常编码,异常名称,异常信息的这么一种异常。大概有20种,比如too_many_rouws;no_data_found;zero_divide.
非提前定义异常:异常编码。异常信息,但没有异常名称
非提前定义异常代码演示样例

自己定义异常


自己定义异常代码演示样例

包用于管理过程和函数
包分为包头和包体

包的代码演示样例



jdbc调用含有包的过程体的代码演示样例

注:包一定要有包头,包头负责声明函数、过程、变量和常量
包体详细来实现包头所声明定义的函数和过程
包体封装实现
包头可单独定义,那么单独定义的包头仅仅能含有常量

触发器 trigger


类似java中的Listener

触发器由数据库管理系统负责调用和运行
通过触发触发器所监听的事物来实现触发器的调用

表级别的触发器(对于整个数据库表做监听)
行级别的触发器(对于表中的每一行做监听)

触发器代码演示样例


注:触发器的运行顺序



有表级别的触发器,行级别的触发器作用于同一个表

1.before表级别触发器
2.before 行级别触发器
3.after 行级别触发器
4.after 表级别触发器


系统触发器


DBA用来调试系统
on database


注:
触发器不带參数,没有放回值。不作事务处理

总结

使用SQL*PLUS登陆远程数据库的配置

手工编辑

$ORACLE_HOME/network/admin/tnsnames.ora文件。

工具编辑

通过Net Configuration Assistant或 Net Manager进行本地网络服务名配置。

UNIX系统

使用“sqlplus”命令登陆。

比如:DEV =

(DESCRIPTION =

(ADDRESS_LIST =

(ADDRESS = (PROTOCOL = TCP)(HOST = 172.11.11.11)(PORT = 1521))

)

(CONNECT_DATA =

(SERVICE_NAME = m11oti11on11)

)

)

使用SET命令配置环境

SQL*PLUS系统提供了很多SET命令。

使用SET命令能够控制当前环境的设置。SET命令的语法形式例如以下:

SET system_variable value

在上面的语法中, system_variable变量用来控制当前环境,value是该系统变量的当前值。

假设希望得到当前指定SET命令的设置,那么能够使用SHOW [ALL]命令显示当前环境设置。

建立数据库

CREATE DATABASE database;

建立顺序号

CREATE SEQUENCE CINOSEQ MINVALUE 1 MAXVALUE 4000000000 START WITH 41 INCREMENT BY 1 NOCYCLE;

创建索引

语法

CREATE [ UNIQUE ] INDEX index

ON table "("

     column [ ASC | DESC]

  [, column [ ASC | DESC]]... ")" ;

改动表

在表的后面添加一个字段

ALTER TABLE 表名 ADD 字段名 字段名描写叙述   [ DEFAULT expr ][ NOT NULL ][ ,字段名2 ……];

改动表里字段的定义描写叙述



ALTER TABLE 表名 MODIFY 字段名1 字段名1描写叙述  [ DEFAULT expr ][ NOT NULL ][ ,字段名2 ……];

删除表里的某个字段

ALTER TABLE 表名 DROP 字段名;

给表里的字段加上/禁止/启用约束条件

ALTER TABLE 表名 ADD | DISABLE | ENABLE CONSTRAINT 约束名 PRIMARY KEY (字段名1[,字段名2 ……]);

ALTER TABLE 表名 ADD | DISABLE | ENABLE CONSTRAINT 约束名 UNIQUE (字段名1[,字段名2 ……]);

删除表里的约束条件

ALTER TABLE 表名 DROP CONSTRAINTS 约束名 [CASCADE];

会把约束相关的索引一起删除,CASCADE能同一时候删去外键的约束条件。

删除索引

DROP INDEX 索引名;

删除顺序号

DROP SEQUENCE 顺序名;

删除数据库表

DROP TABLE 表名 [{CASCADE | CASCADE CONSTRAINTS | RESTRICT}] ;

查询

SELECT [ DISTINCT | ALL ]

     { * |  column [[AS] alias] }

     FROM { table | view }[ alias ]

          [ WHERE condition]

              [ { [ START WITH condition ]

                  CONNECT BY condition

              | GROUP BY expr [, expr]...

              | [HAVING condition] }]

单表查询

SELECT t.* FROM table t WHERE t.c1=‘…’;

内连接

SELECT t1.* FROM table1 t1 INNER JOIN table2 t2 ON t1.column1=t2.column2;

SELECT t1.* FROM table1 t1, table2 t2 WHERE t1.column1=t2.column2;

外连接

SELECT t1.* FROM table1 t1 { [ LEFT | RIGTH ] } [ OUTER ] JOIN table2 t2 ON t1.column1=t2.column2;

SELECT t1.* FROM table1 t1, table2 t2  WHERE t1.column1=t2.column2(+);

SELECT t1.* FROM table1 t1, table2 t2  WHERE t1.column1(+)=t2.column2;

子查询

SELECT … FROM (SELECT … FROM t1, [t2, …]  WHERE condition1) WHERE condition2;

SELECT … FROM t1 WHERE t1.c1 IN (SELECT t2.c2 FROM t2 WHERE condition);

SELECT … FROM t1 WHERE t1 WHERE [NOT] EXISTS ( SELECT t2.c2 FROM t2 WHERE condition );

树查询(递归查询)

SELECT t1.* FROM table t1 START WITH  t1.c1= … CONNECT BY PRIOR t1.c1=t1.c2;

connect by 是结构化查询中用到的。其基本的语法是:

select * from tablename start with cond1

connect by cond2

where cond3;

oracle中的select语句能够用START WITH...CONNECT BY PRIOR子句实现递归查询,connect by 是结构化查询中用到的,其基本的语法是:

select * from tablename start with cond1

connect by cond2

where cond3;

简单说来是将一个树状结构存储在一张表里。比方一个表中存在两个字段:

id,parentid那么通过表示每一条记录的parent是谁。就能够形成一个树状结构。

用上述语法的查询能够取得这棵树的全部记录。

当中COND1是根结点的限定语句,当然能够放宽限定条件,以取得多个根结点,实际就是多棵树。

COND2是连接条件。当中用PRIOR表示上一条记录。比方 CONNECT BY PRIOR ID=PRAENTID就是说上一条记录的ID是本条记录的PRAENTID。即本记录的父亲是上一条记录。

COND3是过滤条件。用于对返回的全部记录进行过滤。

对于oracle进行简单树查询(递归查询)

DEPTID           NUMBER                   部门id

PAREDEPTID   NUMBER                   父部门id(所属部门id)

NAME              CHAR (40 Byte)        部门名称

通过子节点向根节点追朔.

select * from persons.dept start with deptid=76 connect by prior paredeptid=deptid

通过根节点遍历子节点.

select * from persons.dept start with paredeptid=0 connect by prior deptid=paredeptid

可通过level keyword查询所在层次.

select a.*,level from persons.dept a start with paredeptid=0 connect by prior deptid=paredeptid

PS:start with 后面所跟的就是就是递归的种子。也就是递归開始的地方;

connect by  prior后面的字段顺序是有讲究的;

若prior缺省:则仅仅能查询到符合条件的起始行,并不进行递归查询。比如:

select * from emp  start with  empno=7839 connect by  empno=mgr;

 

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO

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

 7839 KING       PRESIDENT       1981-11-17    5000.00               10

 例:

select * from table

start with org_id = 'HBHqfWGWPy'

connect by prior org_id = parent_id;

简单说来是将一个树状结构存储在一张表里,比方一个表中存在两个字段:

org_id,parent_id那么通过表示每一条记录的parent是谁,就能够形成一个树状结构。

用上述语法的查询能够取得这棵树的全部记录。

当中:

条件1 是根结点的限定语句,当然能够放宽限定条件,以取得多个根结点,实际就是多棵树。

条件2 是连接条件,当中用PRIOR表示上一条记录,

比方 CONNECT BY PRIOR org_id = parent_id就是说上一条记录的org_id 是本条记录的parent_id,即本记录的父亲是上一条记录。

条件3 是过滤条件,用于对返回的全部记录进行过滤。

简介例如以下:

在扫描树结构表时,须要依此訪问树结构的每一个节点。一个节点仅仅能訪问一次,其訪问的过程例如以下:

第一步:从根节点開始;

第二步:訪问该节点;

第三步:推断该节点有无未被訪问的子节点,若有,则转向它最左側的未被訪问的子节点,并运行第二步,否则运行第四步;

第四步:若该节点为根节点,则訪问完成,否则运行第五步;

第五步:返回到该节点的父节点,并运行第三步骤。

总之:扫描整个树结构的过程也即是中序遍历树的过程。

1. 树结构的描写叙述

树结构的数据存放在表中,数据之间的层次关系即父子关系,通过表中的列与列间的关系来描写叙述,如 EMP 表中的 EMPNO 和 MGR 。 EMPNO 表示该雇员的编号, MGR 表示领导该雇员的人的编号。即子节点的 MGR 值等于父节点的 EMPNO 值。在表的每一行中都有一个表示父节点的 MGR (除根节点外)。通过每一个节点的父节点。就能够确定整个树结构。

select * from emp  start with  empno=7839 connect by prior empno=mgr;

在 SELECT 命令中使用 CONNECT BY 和 START WITH 子句能够查询表中的树型结构关系。其命令格式例如以下:

SELECT ...

CONNECT BY {PRIOR 列名 1= 列名 2| 列名 1=PRIOR 裂名 2}

[START WITH] ;

当中: CONNECT BY 子句说明每行数据将是按层次顺序检索,并规定将表中的数据连入树型结构的关系中。

PRIORY 运算符必须放置在连接关系的两列中某一个的前面。对于节点间的父子关系。 PRIOR 运算符在一側表示父节点,在还有一側表示子节点。从而确定查找树结构的顺序是自顶向下还是自底向上。

在连接关系中,除了能够使用列名外,还同意使用列表达式。 START WITH 子句为可选项。用来标识哪个节点作为查找树型结构的根节点。若该子句被省略,则表示全部满足查询条件的行作为根节点。

START WITH: 不但能够指定一个根节点。还能够指定多个根节点。

2. 定义查找起始节点

在自顶向下查询树结构时,不但能够从根节点開始,还能够定义不论什么节点为起始节点。以此開始向下查找。这样查找的结果就是以该节点为開始的结构树的一枝。

3.使用 LEVEL

在具有树结构的表中。每一行数据都是树结构中的一个节点,因为节点所处的层次位置不同。所以每行记录都能够有一个层号。层号依据节点与根节点的距离确定。

不论从哪个节点開始。该起始根节点的层号始终为 1 ,根节点的子节点为 2 , 依此类推。

4.节点和分支的裁剪

在对树结构进行查询时,能够去掉表中的某些行,也能够剪掉树中的一个分支,使用 WHERE 子句来限定树型结构中的单个节点。以去掉树中的单个节点。但它却不影响其后代节点(自顶向下检索时)或前辈节点(自底向顶检索时)。

5.排序显示

像在其他查询中一样,在树结构查询中也能够使用 ORDER BY 子句,改变查询结果的显示顺序。而不必依照遍历树结构的顺序。

插入数据insert

INSERT INTO { table | view } ["("column [, column]...")"]{ VALUES "(" expression[, expression]...")" | subquery };

说明

使用INSERT语句一次仅仅能插入一行数据。

update

UPDATE { table | view } [ alias ] SET column = { expression | subquery } [, column = { expr | subquery }]...[WHERE condition] ;

说明

在改动表中数据时,不能破环表的完整性约束。假设改动的数据与完整性约束有冲突,那么这样的改动操作不能成功。

delete

DELETE FROM { table | view }[WHERE condition] ;

说明

就像改动数据一样,删除数据时也不能破坏数据库的完整性约束。

事务

事务是一个逻辑上的单元。

要么所有成功,要么所有失败。

在以下的情况下系统自己主动地结束一个事务:

COMMIT或ROLLBACK命令。

DDL,如CREATE TABLE语句;

退出SQL*PLUS;

系统失败。

语法

COMMIT [WORK] ;

ROLLBACK [{ WORK | TO savepoint_name }] ;

SAVEPOINT savepoint_name ;

REMOVE SAVEPOINT <savepoint_name>;

数据的导入和导出的样例

将数据库TEST全然导出,usernamesystem passwordmanager 导出到daochu.dmp中

exp system/manager@TEST file=d:daochu.dmp full=y

将数据库中的表inner_notify、notify_staff_relat导出

exp aichannel/aichannel@TESTDB2 file= datanewsmgnt.dmp tables= (inner_notify,notify_staff_relat)


样例:导入

将daochu.dmp 中的数据导入 TEST数据库中

imp system/manager@TEST file=daochu.dmp

将daochu.dmp中的表table1 导入

imp system/manager@TEST file=d:daochu.dmp tables=(table1)

PL/SQL一个简短的引论的更多相关文章

  1. Saiku一个简短的引论

    一个简短的引论 Saiku成立于2008年,通过Tom Barber和Paul Stoellberger研究. 最初叫Pentaho分析工具.最初是基于OLAP4J图书馆的使用GWT采用前端分析工具包 ...

  2. Hibernate一个简短的引论

    我们从几个方面进行阐述Hibernate When? What ? How? When? Hibernate由来是因为当时EJBBean1.1在处理entittBean架构时,花费的时间要比业务逻辑很 ...

  3. Mybatis之ResultMap一个简短的引论,关联对象

    基础部分能够查看我的还有一篇博客http://blog.csdn.net/elim168/article/details/40622491 MyBatis中在查询进行select映射的时候.返回类型能 ...

  4. Oracle 指数 一个简短的引论

    1 索引创建语法: CREATE UNIUQE | BITMAP INDEX <schema>.<index_name>       ON <schema>.< ...

  5. HSQL一个简短的引论

    前言     在对dao层写測试类的时候,我们须要一个測试数据库,一般我们会是专门建立一个真实的測试数据库,可是有了HSQLDB事情就变得简单了起来. 正题 一.简单介绍: hsql数据库是一款纯Ja ...

  6. Jsoup一个简短的引论——采用Java抓取网页数据

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/40115479 概述 jsoup 是一款Java 的HTML解析器,可直接解析某个U ...

  7. Spark第一个研究笔记1一片 - Spark一个简短的引论

    该公司推出的在线项目Spark拥有近1随着时间的推移.有效,Spark事实上,优秀的分布式计算平台,以提高生产力. 开始本篇笔记.此前的研究会Spark研究报告共享出来(由于篇幅的限制,它将被划分成制 ...

  8. Cache基础知识OR1200在ICache一个简短的引论

    以下摘录<步骤吓得核心--软-core处理器的室内设计与分析>一本书 12.1 Cache基本知识 12.1.1 Cache的作用 处理器的设计者通常会声称其设计的处理器一秒钟能做多少次乘 ...

  9. HTML5分析实战WebSockets一个简短的引论

    HTML5 WebSockets规范定义了API,同意web页面使用WebSockets与远程主机协议的双向通信. 介绍WebSocket接口,并限定了全双工通信信道,通过套接字网络. HTML5 W ...

随机推荐

  1. android开发设计辅助工具整理

    1.Button设计工具button设计

  2. LaTeX indicator function(指示函数)(\mathbb {1} 不起作用)

    问题说明: \mathbb字符的空心化显示仅对字符有效,对数字无效. 解决方法: 使用 bbm 包 \documentclass{article} \usepackage{bbm} \begin{do ...

  3. 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.

    注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享.  原文地址: http://blog.csdn.net/zhange ...

  4. Javascript和jquery事件--鼠标右键事件,contextmenu

    右键点击触发是浏览器的默认菜单事件contextmenu,你可以选择阻止它,使用event.preventDefault();或者return false;. 想要定义右键点击事件,关注的是mouse ...

  5. HttpWatch--time chart分析

    这是一个IE的插件,下载可以点这里.下载后解压如下图所示,一共有4个文件.HttpWatch Professional是单独软件,可以单独使用. 解压后有四个文件 插件安装时,只需运行httpwatc ...

  6. Access WMI via Python from Linux

    You can use Impacket (https://github.com/CoreSecurity/impacket) that has WMI implemented in Python. ...

  7. 对生产者和消费者问题的另一个解决办法是使用QWaitCondition(封装好了wakeOne,wakeAll,而且与QReadWriteLock对接,几乎是万能的办法)

    对生产者和消费者问题的另一个解决办法是使用QWaitCondition,它允许线程在一定条件下唤醒其他线程.其中wakeOne()函数在条件满足时随机唤醒一个等待线程,而wakeAll()函数则在条件 ...

  8. Spring Boot 2.x 使用 jpa 连接 mysql

    在spring boot网站上生成一个项目,如图: 我使用的是Maven项目,java使用是jdk8(spring boot 2.x必须要jdk8及以上),dependencies分别输入选择 web ...

  9. 2、HZK和FreeType的使用

    HZK16汉字库的使用 定义如下: unsigned char str[]="我" 在运行时str被初始化为2个字节长度,内容为“我”的GBK码,为:0xCE(区码),0xD2(位 ...

  10. android请求

    //请求 HttpURLConnection conn = (HttpURLConnection)new URL(path).openConnection(); conn.setConnecTimeo ...