oracle 基础知识(三)

 

一、删除oracle

进入注册表到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\OracleOraHome91TNSListener ImagePath关键值有?



试试

1、在“控制面板”/“管理工具”/“服务”中将所有ORACLE的服务停止。

2、将以下注册表键删除:HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE。

HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001/ORACLE....

HKEY_LOCAL_MACHINE/SYSTEM/ControlSet002/ORACLE....

HKEY_LOCAL_MACHINE/SYSTEM/ControlSet003/ORACLE....

3、直接删除ORACLE所在的目录。



安装不成功我一般的解决办法是:

1、用oracle系统的卸载工具先把全部组建卸载;

2、在“控制面板”/“管理工具”/“服务”中将所有oracle的服务停止

3、删除oracle目录

4、重起

5、再次检查“控制面板”/“管理工具”/“服务”中将所有oracle的服务,若有则全部停止

6、重新安装

一般好象都可以,有朋友也提到要修改注册表,我平时不改好象也行

如何完完整整干干净净的把oracle删除掉?





1、开始->设置->控制面板->管理工具->服务

   停止所有Oracle服务。



2、开始->程序->Oracle - OraHome81->Oracle Installation Products->Universal Installer

   卸装所有Oracle产品



3、运行regedit,选择HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE,按del键删除这个入口。



4、运行regedit,选择HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services,滚动这个列表,删除所有Oracle入口



5、从桌面上、STARTUP(启动)组、程序菜单中,删除所有有关Oracle的组和图标



6、重新启动计算机,重起后才能完全删除Oracle所在目录



7、删除与Oracle有关的文件,选择Oracle所在的缺省目录C:\Oracle,删除这个入口目录及所有子目录,



  并从Windows 2000目录(一般为C:\WINNT)下删除以下文件



  ORACLE.INI、oradim80.INI



8、WIN.INI文件中若有[ORACLE]的标记段,删除该段

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

删除过程   

  1:在管理工——服务里面         停止所有oracle的服务   

  2:删除D:\ORACLE文件夹   

  3:删除C:\Program   Files\Oracle文件夹   

  4:删除开始——程序里面的oracle文件   

  5:运行regedit,删除HKEY_LOCAL_MACHINE\SOFTWARE\下的ORACLE键   

  6:运行regedit,删除HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services下所有以oracle打头的键   

    

  到现在为止,你还是可以发现在服务里面还有oracle的服务存在,必须把他删除,否则你再安装oracle时就会出现什么服务已经存在的错误提示了!!而这些服务是在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root下以LEGACY_ORACLE打头的,而且你选种按delete删除时系统会提示你一个错误!!不让你删除!!!现提供具体删除方法,win2000的如下:   

    

  7:运行regedt32注意了,不是regedit!!!!在HKEY_LOCAL_MACHINE那页找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root先选中ROOT然后点菜单上的安全—权限把自己添加到里面,并且权限设置为完全控制,确定后再删除ROOT下所有LEGACY_ORACLE打头的键,同样的方法也可以把HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001和HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002两个下面\Enum\Root下所有LEGACY_ORACLE打头的键删除,重新启动计算机可以发现,服务里面的那些都没有了!!   

  7:在winXP中就比较简单了,还是运行regedit,找到LEGACY_ORACLE打头的键后右击,选择权限,同样将everyone设置为完全控制就可以删除了!删除后重新启动一下就可以了!!   

    

  8:重新安装新的oracle吧!!!SID一样也不会有什么错误的!!!

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

oracle在win2k下的安装与卸载的详细说明     

    

  在WinNT/2000上的安装过程   

  1、安装前先做好注册表的备份工作;   

  2、确认Oracle安装版本号   

  3、确认系统配置   

  系统基本要求:   

  内存:   128   M以上   

  交换空间   系统内存的2倍   

  光驱设备   支持ISO   9600格式   

  硬盘空间   典型安装NTFS下,ORACLE_HOME   DIRVE>1.2G   

  操作系统   SOLARIS   2.5,LINUX   2.2   ,NT4.0+SP6以上   

  4、安装   

  插入光盘——>自动运行——>Setup——>进入welcome窗口next   step——>确认安装目标路径——>选择要安装的产品   

  ——>选择安装类型(可先选择自主安装,选择产品语言后,再选择上一步,选择典型安装)   

  ——>输入全局数据库名——>安装——>下一步   

  安装时如果要安装ORACLE   WEBDB,不要接受的Oracle安装路径及其位置的默认值。   

    

  在WinNT/2000上的反安装过程   

  如果不注意,可能不能正确删除ORALE   

  1、使用Oracle   Universal   Installer反安装Oracle组件   

  包括三种情况:   

  a、安装中途取消安装   

  b、安装过程中计算机重启了   

  c、安装过程未完成   

  处理方法:只须删除硬盘上Oracle_home目录,因为此时未往注册表中写入信息   

    

  2、删除Net8,Oracle   Internet   Directory,Oracle8i   Database   and   Registry   entries   

  必须先停止Oracle的服务   

  重装Net8过程:   

  a、regedit   

  b、HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services--->删除OracleHOME_NAMETNSListener   

  c、exit   

    

  删除Oracle   Internet   Directory   

  C:\>OIDCTL   CONNECT=NET_SERVICE_NAME   SERVER=OIDLDAPD   INSTRANCE=SERVER   INSTANCE_NUMBER   STOP   

  C:\>OIDMON   STOP   

  C:\>OIDMON   REMOVE   

  后面的步骤同下   

    

  删除Oracle8i   Database   and   Registry   entries   

  a、start--->programes--->Oracle--->Database   Adminstrator--->Database   Configuration   Assistant   

  b、delete   a   database--->next   

  c、regedit--->删除HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\OracleServiceSID   

    

  删除组件   

  start--->programe--->Oracle   Installer   Appears--->Universal   Installer--->选择要删除的组件--->确定   

    

  手工清除所有的Oracle组件   

  1、以administrator帐户登录   

  2、停止所有的oracle服务(start-->setting-->control   panel-->administrator   tool-->service)   

  3、修改注册表regedit   

  4、HKEY_CLASS_ROOT-->删除所有以ORACLE/ORAL表示的关键字   

  5、HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE删除ORACLE关键字   

  6、删除HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI中的Oracle选项   

  7、删除HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application下的Oracle选项   

  8、删除HKEY_CURRENT_USER\SOFTWARE\ORACLE下的以oracle/orcl开头的选项   

  9、删除HKEY_CURRENT_USER\SOFTWARE\ODBC\ODBCINST.INI下的Oracle关键字   

  10、退出注册表   

  11、Start   --->   Settings   --->   Control   Panel   --->   系统--->高级--->   Environment   tab.     

  12、选择   the   system   variable   path   编辑   the   Path   variable.     

  13、删除所有   Oracle   entries   from   the   path.   例:if   JRE   was   installed   by   Oracle,   remove   the   %ORACLE_HOME%\BIN   path   and   the   JRE   path.   You   may   see   a   path   similar   to   this   one:     

  C:\ORACLE\ORA81\BIN;G:\PROGRAM   FILES\ORACLE\JRE\1.1.7\BIN     

  14、退出控制面板   

  15、进入SYSTEM_DRIVE:\WINNT\PROFILES\ALL   USERS\START   MENU\PROGRAMS.     

  16、删除图标   

  Oracle   -   HOME_NAME     

  Oracle   Installation   Products     

  where   HOME_NAME   is   the   previous   Oracle   home   name.     

  17、删除   SYSTEM_DRIVE:\Program   Files\Oracle目录   

  18、删除所有硬盘上   ORACLE_BASE目录     

  19、重启计算机     

    

  以上译自oracle随机文挡,如有不当之处请指正!   

    

  根据个人经验,删除的步骤最好为:   

  1、通过Oracle   Installation   Products   卸载已安装产品   

  2、在注册表中删除oracle,orcl,ora打头的注册项,可能有部分删除不了,不用管。   

  3、重起系统   

  4、删除系统下c:\Program   Files\Oracle目录和ORACLE_BASE目录     

    

  另:如果愿意,可将安装之前的注册表备冯文件导入试一下。   

    

    

  你没有彻底删除oracle,按如下方法可以彻底删除数据库   

    

  NT环境下:     

  1、以NT的Administrator   登陆     

  2、通过控制面版-〉服务,停掉所有ORACLE服务     

  3、打开注册表(REGEDIT命令),删除     

  HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE     

  4、打开注册表中的   HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services     

    

  删除以ORACLE开头的所有服务     

  5、删除HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\A     

  pplication下     

  以ORACLE开头的所有服务     

  6、关闭REGEDIT     

  7、打开控制面版-〉系统-〉环境变量     

  8、如果ORACLE安装了JRE,就删除%ORACLE_HOME%\BIN和JRE路径。     

  比如   \ORACLE\ORA81\BIN;G:   \Program   Files\Oracle\jre\1.1.7\bin     

  9、删除\Winnt\Profiles\All   Users\Start   Menu\Programs\Oracle   和     

  \Winnt\Profiles\All   Users\Start   Menu\Programs\Oracle     

  10、删除\Program   Files\Oracle     

  11、重新启动机器     

  12、删除所有ORACLE目录(在注册表HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ORA     

  CLE_HOMES下)     

    

  在   Windows   95   /   Windows   98:     

    

  1.   打开注册表HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE.     

    

  2.删除前面步骤中的第3步中的ORACLE     

    

  3.   删除AUTOEXEC.BAT   中的   %ORACLE_HOME%\bin   和   JRE     

    

  4.   删除所有ORACLE目录     

    

  5.   \Program   Files\Oracle     

    

  6.   \Windows\Start   Menu\Programs\Oracle   -   <HOME>     

  \Windows\StartMenu\Programs\Oracle     

    

  7.   重新启动   

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

很多朋友只用了oracle的删除,但很多情况下,他会发现重新安装时,点了下一步安装界面就消失了,往往无奈下只好重装系统,其实只是你数据库没删干净,删干净就不会出现这种情况了。



  实现方法:



  1、开始->设置->控制面板->管理工具->服务



  停止所有Oracle服务。



  2、开始->程序->Oracle - OraHome81->Oracle Installation Products->



  Universal Installer



  卸装所有Oracle产品,但Universal Installer本身不能被删除



  5、运行regedit,选择HKEY_LOCAL_MACHINESOFTWAREORACLE,按del键删除这个入口。



  6、运行regedit,选择HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices,滚动



  这个列表,删除所有Oracle入口。



  7、运行refedit,



  HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesEventlogApplication,



  删除所有Oracle入口。



  8、开始->设置->控制面板->系统->高级->环境变量



  删除环境变量CLASSPATH和PATH中有关Oracle的设定



  9、从桌面上、STARTUP(启动)组、程序菜单中,删除所有有关Oracle的组和图标



  10、删除Program FilesOracle目录



  11、重新启动计算机,重起后才能完全删除Oracle所在目录



  12、删除与Oracle有关的文件,选择Oracle所在的缺省目录C:Oracle,删除这个入



  口目录及所有子目录,并从Windows 2000目录(一般为C:WINNT)下删除以下文



  件ORACLE.INI、oradim73.INI、oradim80.INI、oraodbc.ini等等。



  13、WIN.INI文件中若有[ORACLE]的标记段,删除该段



  14、如有必要,删除所有Oracle相关的ODBC的DSN



  15、到事件查看器中,删除Oracle相关的日志



  说明:



  如果有个别DLL文件无法删除的情况,则不用理会,重新启动,开始新的安装,



  安装时,选择一个新的目录,则,安装完毕并重新启动后,老的目录及文件就可以删除掉了

二、oracle数据库对象

 

数据库对象同JAVA中的对象是一样的.有属性和方法.

oracle创建对象类型

create or replace TYPE address_typ AS OBJECT

(

   street varchar2(15),

   city varchar2(15),

   state char(2),

   zip varchar2(5)

);

create or replace type person_typ as object

(

   id number,

   nanm varchar2(10),

   dob date,

   phone varchar2(12),

   address address_typ--引用上面的对象类型.(对象类型可以相互引用)

);

现在写一个带有函数的对象类型.这个对象用于表示产品.注意声明了一个函数

get_sell_by_date().这个函数根据days_valid属性和当前日期,返回产品的最晚售出时间.

create or replace product_typ as object

(

  id number,

  name varchar2(15),

  description varchar2(22),

  price number(5,2),

  days_valid  number,

  MEMBER Function get_sell_by_date Return Date

);

Member function子句用于声明get_sell_by_dat函数,

Member procedure子句用于声明一个过程.

---由于在对象类型product_typ 中声明了方法(函数),所以必须为product_typ创建对象体(body).下面是创建product_typ的对象体.

create or replace type body product_typ as

   Member function get_sell_by_date Return date is

   v_sell_by_date date;

  begin

     select days_valid+sysdate into v_sell_by_date from dual;

     return v_sell_by_date;

  end get_sell_by_date;

end product_typ;

可以看出,函数通过将days_valid属性与当前日期相加,计算并返回产品当前最晚必须售出时间.

---可以通过describe来获取有关对象类型的信息

describe product_typ;

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

2.用对象类型定义列对象和对象表

对象类型可以用来定义表中的列,这种列称为列对象(Column object).同时,当对象类型包含嵌入对象类型时,嵌入对象类型也是一个列对象.person_typ(见上面)就是这样一个例子.

创建products表:--这种表是包含列对象的表

create table products

(

  product product_typ,

  quantity_in_stock number--库存数量

);

对象表:使用对象类型来定义整个表.这种表叫对象表.

下面这个例子创建两个对象表object_products和object_customers,分别使用product_typ和person_typ定义.注意OF子句用于将每个表标识为对象表:

 例子:

create table object_products of product_typ;

create table object_customers of person_typ;

对象表与包含列对象的表这两者的区别是:

后者可以具有多列.

-------对象引用和对象标识符

对象表的另一个不同之处在于可以使用对象引用(object reference)为对象表之间的关系建立模型,而不是使用外键.对象引用使用REF类型进行定义,通常都用作指向对象表中对象的指针.对象表中的每个对象都具有惟一的对象标识符(object identified,OID),它可以存储在REF列中.下面创建表purchases,其中包含了两个REF列:

  create table purchases

  (

    id number primary key,

    customer REF person_typ SCOPE IS object_cusotmers,

    product REF product_typ SCOPE IS object_products

  );

 SCOPE IS子句将对象引用限制在特定表中的对象上.例如列customer被限制在指向ojbect_customers表中的对象.

==========================================================================

下面对products,object_products,object_customers,purchases表进行DML操作.

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

-----对products(包含列对象的表)进行DML操作

1.插入

insert into products(product,quantity_in_stock)

  values(product_typ(1,'pasta','20 oz bag of pasta',3.95,10),50);

2.查询

--全查询

select * from products;product列对象的属性显示在product_typ的构造函数中.

--查询单个列对象:注意product对象的id属性的表被赋予别名p

select p.product from products p where  p.product.id=1;

--查询列对象中声明的方法(函数和过程)

在prodcut_typ对象类型中包含get_selll_by_date()函数,用于计算并返回某件产品的最晚售出时间.

select p.product.get_sell_by_date() from products p;

3.修改 

注意访问product列对象时使用了表别名

update products p set p.product.description='30 oz bag of pasta' 

 where p.product.id=1;

4.删除

delete from products p

 where p.product.id=2;

-------对object_products(对象表)表进行DML操作

1.插入(两种形式同sql一样)

insert into object_products 

values(product_typ(1,'pasta','20 oz bag of past',3.86,10));

insert into object_products (id,name,description,price,days_valid)

  values(2,'sardines','12 oz box of sardines',2.99,5);

2.选择记录

select * from object_products;

 可以用Oracle数据库内置的value()函数从对象表中查询记录.这种方法将记录看作真正的对象,并在对象类型的构造函数中返回对象的属性.value()函数接受表别名作参数.

select value(op) from object_products op;

3.更新

update object_products set description='25 oz bag of pasta' where id=1;

4.删除记录

delete from object_products where id=2;

---------对object_customers(对象表)进行DML操作

1.插入

insert into object_customers values

(

  person_typ(1,'John','Brown','01-FEB-1955','800-555-1211',

           address_typ('2 stat street','Beantown','MA','123456'))

);

2.查询

object_customers表是person_typ的对象表;person_typ包含嵌入的address_typ列对象address.

---全查询

select * from object_customers;

---查询一条记录

select * from object_customers oc where oc.id=1;--id是person_typ中的id

---对嵌入的列对象的state属性的查询

select * from object_customers oc

   where oc.address.state='MA';

3.更新和删除同对object_products的操作一样(略)

--------对purchases(这种表是包含列对象的表,但是较特殊的一种.这包含的列对象是对象表(通过REF),而不是对象类型)表进行DML操作

1.插入

  对象表中的每一条记录都具有惟一的对象标识符,这个标识符可保存在REF列中.可通过REF()函数访问这个对象标识符,并将返回的对象标识符保存在REF列中.

insert into purchases (id,costome,product)

 values(1,(select REF(oc) from object_customers oc where oc.id=1),

 (select REF(op) from object_products op where op.id=1));

这个例子记录的是顾客#1购买了产品.

2.查询(选择记录)

--全查询

注意customer和product列中包含很长的数字字母串,这些是指向object_customers和object_products表中记录的对象标识符.

select * from purchases;

--访问customer和product列所指向的记录

可以使用DEREF()函数通过REF列的值访问它所指向的对象表中的记录;这个函数接受REF列作为参数.

select DEREF(customer),DEFER(product) from purchases;

3.更新

--修改purchases表中的一条记录.注意product列的值被改为指向object_products表中的产品#2

update purchases set product=(select REF(op) from object_products op 

    where op.id=2) where id=1;



===============================

------------在PL/SQL中使用对象

程序包product_package中

包含一个get_products()函数,返回object_products表中的对象

一个insert_product()过程,向ojbect_products表中增加一个对象.

----product_package

程序包规范

create or replace package product_package as

Type ref_cursor_typ IS REF CORSOR

function get_products return ref_cursor_typ;

procedure insert_product(

    p_id in ojbect_products.id%type,

     p_name in object_products.name%type,

    p_descirption in object_products.description%type,

     p_price in object_products.price%type,

    p_days_valid in object_products.days_valid%type

);

end product_package;

程序包主体

create or replace package body product_package as

     function get_products return ref_cursor_typ 

     is

     products_ref_cursor ref_cursor_typ;

     begin

       open products_ref_cursor FOR select value(op) from object_products op;

       return products_ref_cursor;

     end get_products;

    procedure insert_product(

    p_id in ojbect_products.id%type,

     p_name in object_products.name%type,

    p_descirption in object_products.description%type,

     p_price in object_products.price%type,

    p_days_valid in object_products.days_valid%type

    )

     as

     product product_typ:=product_typ(p_id,p_name,p_description,p_price,p_days_valid);

    begin

      insert into object_products values(product);

      commit;  

    exception

      when others then

        rollback;

    end insert_product;

end product_package;



说明:get_products()函数使用value将object_products表的内容作为product_typ对象返回.

下面是对过程和函数的调用 

call product_package.insert_product(4,'sals','15 oz jar of salsa',1.50,20);

select product_package.get_products from dual;

三、动态创建表和传值

 

在SQL里面不能直接用参数做表名,要先连成字符串才执行

是动态建表和动态传值.

set ANSI_NULLS ON

set QUOTED_IDENTIFIER ON

go





ALTER proc [dbo].[CreateTable]

@Tablename nvarchar(100),

@Tablenamedp nvarchar(100) as



DECLARE @SQL nvarchar(3250)

DECLARE @SQL1 nvarchar(3250)

SET @SQL = '

CREATE TABLE '+@Tablename+' (

    [HtNo] [varchar](20) COLLATE Chinese_PRC_CI_AS NULL,

    [Dhr] [int] NULL,

    [Shr] [int] NULL,

    [Dhdh] [varchar](20) COLLATE Chinese_PRC_CI_AS NOT NULL PRIMARY KEY

) 

'

SET @SQL1='

CREATE TABLE '+@Tablenamedp+'(

    [Id] [bigint] NOT NULL  identity PRIMARY KEY,

    [Dhdh] [varchar](20) COLLATE Chinese_PRC_CI_AS NULL,

    [HtspId] [bigint] NULL,

    [Sl] [decimal](10, 4) NULL,

    [Jj] [money] NULL,

    [Jxsl] [decimal](18, 4) NULL

)

'

exec sp_executesql @SQL

exec sp_executesql @SQL1

============

sp_executesql 这个是系统存储过程

@SQL==变量.

四、复制表结构和改表名

改表名:rename tablename1 to tablename2;

改字段名:alter table tablename rename column age to age2;

复制表的结构给另一个新表。

create table cc as select * from aa;

复制表的一个字段给另一个表

insert into bb.age select age from age

insert into bb select * from aa;

==========

数据字典视图,USER_SOURCE 包含存储过程的代码文本。

USER_SOURCE

五、集合、数组和嵌套表

oracle中的集合

1.变长数组(varray).2.嵌套表.3.关联数组(以前称为索引表)

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

=======变长数组(varray)

1.创建变长数组

  使用create type语句创建变长数组类型,并在创建该类型时指定最大大小和存储在数组

中的元素类型.如下示例.创建一个名为varray_address_typ的变长数组类型,可以最多存储2个varchar2 字符串:

create type varray_address_typ as varray(2) of varchar2(50);

每个(共2个)varchar2可以用来表示我们虚构商店的一个顾客客的地址.地址可以是顾客装运的地址,即收到产品的地方,另一个是他们的付账地址,即收到产品帐单的地方.

2.使用变长数组类型定义表列

create table customers_with_varray

(

   id integer primary key,

   name varchar2(10),

   address varray_address_typ

)

3.获得变长数组信息

describe varray_address_typ;

describe customers_with_varray;

4.使用insert插入表

insert into customers_with_varray values

(1,'aa',varray_address_typ('南昌市二径路','南昌市三径路'));

5.查找变长数组元素

使用select语句查找变长数组元素.

select * from customers_with_varray;

6.更改变长数组元素.

   变长数组元素只能整体进行更改.这意味着,如果想要更改一个元素,必须提供变长数组的所有元素.

update customers_with_varray set

  address=varray_address_typ('1111111111111111','22222222222')where id=1;

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

==================嵌套表

  嵌套表是任意数量元素的一个有序集合,所有元素是同一数据类型.嵌套表有单个列,该列的类型可以是内置的数据库类型,也可以是以前创建过的对象类型.如果嵌套表的列类型,都是对象类型,则表可以被看作一个多列表,对象的每个属性是一列.可以插入,更改和删除嵌套表的单个元素.

1.创建嵌套表类型

-----address_typ这是一个对象类型,相当于java中的vo

 create type address_typ as OBJECT

(

  street varchar2(15),

  city varchar2(15),

  state char(2),

  zip varchar2(5)

)

-使用create type语句创建嵌套表类型,下例创建了嵌套表类型nested_table_addres_typ,用于存储address_typ对象类型

create type nested_table_address_typ as table of addres_typ;

2.使用嵌套表类型定义表列

  一旦已经定义了嵌套表类型,就可以使用它定义表列.例如表customers_with_nested_table使用nested_table_address_typ定义列addresses;

create table customers_with_nested_table

(

  id integer primary key,

  name varchar2(10),

  addresses nested_table_address_typ

)

NESTED TABLE

   addresses

STORE AS nested_addresses;

  NESTED TABLE子句标识了嵌套表列的名称(addresses),STORE AS子句指定了实际嵌套表

的名称(nested_addresses).可以独立于包含嵌套表的父表访问嵌套表.

3.获得嵌套表信息

describe nested_table_address_typ;

user_nested_tables;

all_nested_tables获得能访问的所有表的信息.

4.填充嵌套表元素

注意,使用nested_table_address_typ和address_typ构造函数指定了地址

insert into customers_with_nested_table values(

   1,'zhangsai',nested_table_addres_typ(

    address_typ('2 State Street ','Beantown','MA','123456'),

        address_typ('4 Hill Street','Lost town','CA','54321')

    )

);

可以看到,该行有两个地址,但是可以在嵌套表中存储任意数目的地址.

5.查找嵌套表元素

使用select语句查找嵌套表元素

select * from customers_with_nested_table;

6.更改嵌套表元素

 和变长数组不同,嵌套表的元素可单独更改:可以插入,更改和删除嵌套表元素. 

使用table子句和一个查找嵌套表的子查询可以完成这些操作.

-----下例在customer_with_nested_table中顾客#1的addresses嵌套表列的末尾插入一个地址.

insert into table

( select addresses form customers_with_nested_table where id=1)

 values(addres_typ('5 Main','Uptown','NY','55513'));

-----下例更改customers_with_nested_table中顾客#1的第一个地址.注意,使用别名addr标识

别第一个址,然后设置它:

 update table

(select addresses from customers_with_nested_table where id=1)

addr set value(addr)=address_typ

('1 Market street ','Main town','MA','54321')

where value(addr)=address_typ('2 State Street','Beantown','MA','12345');

-----最后一个例子删除customers_with_nested_table中顾客#1的第二个地址

delete from table

(select addresses from customers_with_nested_table where id=1)

addr where value(addr)=address_typ('4 Hill Street','Lost town','CA','54321');



=========================================================

----------在PL/SQL中使用集合

--1.操作变长数组

程序包varray_package

函数:get_customers(),它返回customers_with_varray表的相应行

过程:insert_customer().它在customers_with_varray表中添加一行.

create or replace package varray_package as

 type ref_cursor_typ is ref corsor;

 function get_customers return ref_cursor_typ;

 procedure insert_customer

(

  p_id in customers_with_varray.id%type,

  p_name in customers_with_varray.name%type,

  p_addresses in customers_with_varray.addresses%type

);

end varray_package;



create or replace package body varray_package as

 function get_customers return ref_cursor is

   customers_ref_cursor ref_cursor_typ;

 begin

  open customers_ref_cursor fro 

    select * from customers_with_varray;

  return customers_ref_cursor;

 end get_customers;



 procedure insert_customer

 (

  p_id in customers_with_varray.id%type,

  p_name in customers_with_varray.name%type,

  p_addresses in customers_with_varray.addresses%type

) as

 begin

  insert into customers_with_varray

   values(p_id,p_name,p.addresses);

  commit;

  exception 

   when others then

     rollback;

 end insert_customer;

end varray_package;

--测试

call varray_package.insert_customer(1,'james',

    varray_addres_typ('10 Main street,Green Town,CA,22212',

                         '20 State street,Blue Town FL,22213'));

varray_package.get_products(),从customers_with_varray中检索行

select varray_package.get_customers from dual;

================

---------操作嵌套表

程序包:nested_table_package它包含

函数:get_customers(),它返回表customers_with_table的相应的列

过程:insert_customer(),向customers_with_table表中添加一行



create or replace package nested_table_package  as

 type ref_cursor_typ is ref corsor;

 function get_customers return ref_cursor_typ;

 procedure insert_customer

(

  p_id in customers_with_varray.id%type,

  p_name in customers_with_varray.name%type,

  p_addresses in customers_with_varray.addresses%type

);

end varray_package;



create or replace package body nested_table_package as

   function get_customers return ref_cursor_typ is

     customers_ref_cursor ref_cursor_typ

   begin

     open customers_ref_cursor for 

          select * from customers_with_nested_table;

     return customers_ref_cursor;

   end get_customers;

  

   procedure insert_customer

  (

     p_id in customers_with_varray.id%type,

  p_name in customers_with_varray.name%type,

  p_addresses in customers_with_varray.addresses%type

  ) is

  begin

   insert into customers_with_table

   values(p_id,p_name,p.addresses);

   commit;

   exception 

    when others then

      rollback;

  end insert_customer;

end nested_table_package;

--测试

call nested_table_package.insert_customer(2,'James',

    nested_table_address_typ(

              address_typ('10 Main','Green twon','CA','22212'),

              address_typ('20 State','Blue twon','FL','22213')));

nested_table_package.get_products(),从customers_with_varray中检索行

select nested_table_package.get_customers from dual;

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

集合方法

count:返回集合的元素数目.

delete:删除集合中的元素.有三种形式.删除所有元素

delete(n):删除第n个元素

delete(n,m):删除从第n个到第m个元素

exists(n):如果集合的第n个元素存在,返回true;

extend:增加集合的大小.有三种形式.添加一个元素,设置为空值.

extend(n):添加n个元素,设置为空值.

extend(n,m):添加n个元素,设置为m

first:返回集合的第一个(最小的)索引号.如果集合为空,返回空值.

last:返回集合的最后一个(最大的)索引号.如果集合为空,返回空值.

next(n):返回n后面的元素的索引号,如果n后面没有元素,返回空值.

prior(n)返回n前面的元素的索引号,如果n前面没有元素,返回空值.

trim:删除集合末尾的元素.有两种形式:删除末尾的一个元素

trim(n):删除末尾n个元素.



---例子

create or replace procedure display_addresses

(addresses_par nested_table_address_typ)

as

count_var integer;

begin

  dbms_output.put_line(addresses_par.count);

 for count_var in 1..addresses_par.count

 loop

  dbms_output.put_line('Address #'|| count_var||':');

  dbms_output.put_line(addresses_par(count_var).street|| ',');

    dbms_output.put_line(addresses_par(count_var).city|| ',');

 end loop;

end display_addresses;

====上述语句addresses_par.count相对应的有其他的集合

addresses_par.delete;

addresses_par.extend;等等.

六、日期操作

select * from dual

--显示星期几(数字)一周中的第几天--这种写法是按西方算法星期四是5.

select to_char(sysdate,'D') as aa from dual;

--一周中的第几天(中文显示(如星期四))

select to_char(sysdate,'DAY') as aa from dual;

select to_char(sysdate,'dy') as bb from dual;

--一月中的第几天

select to_char(sysdate,'DD') as aa from dual;

--一年中的第几天`

select to_char(sysdate,'DDD') as aa from dual;

--显示全日期

select to_char(sysdate,'yyyy MONTH DAY') as aa from dual;

--显示日期格式.

select to_char(sysdate,'YYYY-MM-DD') as aa from dual;

--显示月份(中文)

select to_char(sysdate,'MON') as aa from dual;

select to_char(sysdate,'month') as aa from dual;

select t0_char(sysdate,'MONTH') as aa from dual;

--显示年份(数字)

select to_char(sysdate,'yyyy') as aa from dual;

--显示一月中的第几周(数字)

select to_char(sysdate,'W') as bb from dual;

--24小时显示

select to_char(sysdate,'HH24') as bb from dual;

--12小时显示

select to_char(sysdate,'HH') as bb from dual; 

--显示分钟

select to_char(sysdate,'MI') as bb from dual;

--显示秒钟

select to_char(sysdate,'ss') as bb from dual;

七、合并多行记录的字符串

怎么合并多行记录的字符串,一直是oracle新手喜欢问的SQL问题之一,关于这个问题的帖子我看过不下30个了,现在就对这个问题,进行一个总结。

   什么是合并多行字符串(连接字符串)呢,例如:

SQL> desc test;

Name    Type         Nullable Default Comments 

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

COUNTRY VARCHAR2(20) Y                         

CITY    VARCHAR2(20) Y                         



SQL> select * from test;



COUNTRY              CITY

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

中国                 台北

中国                 香港

中国                 上海

日本                 东京

日本                 大阪

要求得到如下结果集:

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

中国       台北,香港,上海

日本       东京,大阪

  实际就是对字符实现一个聚合功能,我很奇怪为什么Oracle没有提供官方的聚合函数来实现它呢:)

  下面就对几种经常提及的解决方案进行分析(有一个评测标准最高★★★★★):

1.被集合字段范围小且固定型 灵活性★   性能★★★★ 难度 ★

  这种方法的原理在于你已经知道CITY字段的值有几种,且还不算太多,如果太多这个SQL就会相当的



长。。看例子:

SQL> select t.country,

  2  MAX(decode(t.city,'台北',t.city||',',NULL)) ||

  3  MAX(decode(t.city,'香港',t.city||',',NULL))||

  4  MAX(decode(t.city,'上海',t.city||',',NULL))||

  5  MAX(decode(t.city,'东京',t.city||',',NULL))||

  6  MAX(decode(t.city,'大阪',t.city||',',NULL))

  7  from test t GROUP BY t.country

  8  /



COUNTRY              MAX(DECODE(T.CITY,'台北',T.CIT

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

中国                 台北,香港,上海,

日本                 东京,大阪,

  大家一看,估计就明白了(如果不明白,好好补习MAX DECODE和分组)。这种方法无愧为最笨的方法



,但是对某些应用来说,最有效的方法也许就是它。

2.固定表固定字段函数法 灵活性★★ 性能★★★★ 难度 ★★

  此法必须预先知道是哪个表,也就是说一个表就得写一个函数,不过方法1的一个取值就要便捷多了。在大多数应用中,也不会存在大量这种合并字符串的需求。废话完毕,看下面:

  定义一个函数

create or replace function str_list( str_in in varchar2 )--分类字段

  return varchar2

is

      str_list  varchar2(4000) default null;--连接后字符串

      str  varchar2(20) default null;--连接符号

begin

      for x in ( select TEST.CITY from TEST where TEST.COUNTRY = str_in ) loop

          str_list := str_list || str || to_char(x.city);

          str := ', ';

      end loop;

      return str_list;

end;

使用:

SQL> select DISTINCT(T.country),list_func1(t.country) from test t;



COUNTRY              LIST_FUNC1(T.COUNTRY)

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

中国                 台北, 香港, 上海

日本                 东京, 大阪



SQL> select t.country,str_list(t.country) from test t GROUP BY t.country;



COUNTRY              STR_LIST(T.COUNTRY)

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

中国                 台北, 香港, 上海

日本                 东京, 大阪

这个时候,使用分组和求唯一都可以满足要求。它的原理就是,根据唯一的分组字段country,在函数里面再次查询该字段对应的所有被合并列,使用PL/SQL将其合并输出。

3.灵活表函数法 灵活性★★★ 性能★★★ 难度 ★★★

  该方法是在方法2的基础上,使用动态SQL,将表名和字段名称传入,从而达到灵活的目的。

  create or replace function str_list2( key_name in varchar2,

                    key  in varchar2,

                    coname in varchar2,

                    tname     in varchar2 )

 return varchar2

as

    type rc is ref cursor;

    str    varchar2(4000);

    sep    varchar2(2);

    val    varchar2(4000);

    cur    rc;

begin

    open cur for 'select '||coname||'

                    from '|| tname || '

                    where ' || key_name || ' = :x '

                using key;

    loop

        fetch cur into val;

        exit when cur%notfound;

        str := str || sep || val;

        sep := ', ';

    end loop;

    close cur;

    return str;

end;

SQL> select test.country,

  2  str_list2('COUNTRY', test.country, 'CITY', 'TEST') emplist

  3  from test

  4   group by test.country

  5  /



COUNTRY              EMPLIST

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

中国                 台北, 香港, 上海

日本                 东京, 大阪

4.一条SQL法 灵活性★★★★ 性能★★ 难度 ★★★★

  一条SQL的法则是某位大师提出的,大家曾经在某个时期都乐此不彼的寻求各种的问题一条SQL法,但是大师的意思似乎被曲解,很多性能差,可读性差,灵活差的SQL都是这个原则产物,所谓画虎不成反成犬类。不过,解决问题始终是第一原则,这里还是给出一个比较有代表性的一条SQL方法。

SELECT country,max(substr(city,2)) city

  FROM

(SELECT country,sys_connect_by_path(city,',') city

 FROM 

(SELECT country,city,country||rn rchild,country||(rn-1) rfather

  FROM 

  (SELECT  test.country ,test.city,row_number() over (PARTITION BY test.country ORDER BY 



test.city) rn 

  FROM test))

CONNECT BY PRIOR rchild=rfather START WITH rfather LIKE '%0')

 GROUP BY country;

  下面分步解析,有4个FROM,就有4次结果集的操作。

   step 1 给记录加上序号rn

  SQL> SELECT  test.country ,test.city,row_number() over (PARTITION BY test.country ORDER 



BY test.city) rn

  2    FROM test

  3  /



COUNTRY              CITY                         RN

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

日本                 大阪                          1

日本                 东京                          2

中国                 上海                          1

中国                 台北                          2

中国                 香港                          3

  step 2 创造子节点父节点

SQL> SELECT country,city,country||rn rchild,country||(rn-1) rfather

  2    FROM

  3    (SELECT  test.country ,test.city,row_number() over (PARTITION BY test.country ORDER 



BY test.city) rn

  4    FROM test)

  5  /

 日本 大阪 日本1 日本0

 日本 东京 日本2 日本1

 中国 上海 中国1 中国0

 中国 台北 中国2 中国1

 中国 香港 中国3 中国2

  step 3 利用sys_connect_by_path生成结果集

SELECT country,sys_connect_by_path(city,',') city

 FROM 

(SELECT country,city,country||rn rchild,country||(rn-1) rfather

  FROM 

  (SELECT  test.country ,test.city,row_number() over (PARTITION BY test.country ORDER BY 



test.city) rn 

  FROM test))

CONNECT BY PRIOR rchild=rfather START WITH rfather LIKE '%0'

 日本 ,大阪

 日本 ,大阪,东京

 中国 ,上海

 中国 ,上海,台北

 中国 ,上海,台北,香港

  step 4 最终步骤,筛选结果集合

SQL> SELECT country,max(substr(city,2)) city

  2    FROM

  3  (SELECT country,sys_connect_by_path(city,',') city

  4   FROM

  5  (SELECT country,city,country||rn rchild,country||(rn-1) rfather

  6    FROM

  7    (SELECT  test.country ,test.city,row_number() over (PARTITION BY test.country ORDER 



BY test.city) rn

  8    FROM test))

  9  CONNECT BY PRIOR rchild=rfather START WITH rfather LIKE '%0')

 10   GROUP BY country;



COUNTRY              CITY

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

中国                 上海,台北,香港

日本                 大阪,东京



  可谓是,7歪8搞,最后还是弄出来了,呵呵。

5.自定义聚合函数 灵活性★★★★★ 性能★★★★★ 难度 ★★★★★

  最后一个方法是我认为“王道”的方法,自定义聚合函数。

  就如何我在本开始说的,为啥oracle没有这种聚合函数呢?我也不知道,但oracle提供了聚合函数的



API可以让我方便的自己定义聚合函数。

  详细可以看Oracle Data Catridge guide这个文档。连接如下:

  http://www.oracle.com.cn/other/9ionlinedoc/appdev.920/a96595/toc.htm

下面给出一个简单的例子:

SQL> SELECT t.country,strcat(t.city) FROM test t GROUP BY t.country;



COUNTRY              STRCAT(T.CITY)

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

日本                 东京,大阪

中国                 台北,香港,上海

简单吧,和官方的函数一样的便捷高效。

函数:

CREATE OR REPLACE FUNCTION strcat(input varchar2 )

RETURN varchar2

PARALLEL_ENABLE AGGREGATE USING strcat_type;

TYPE:

create or replace type strcat_type as object (

    cat_string varchar2(4000),

    static function ODCIAggregateInitialize(cs_ctx In Out strcat_type) return number,

    member function ODCIAggregateIterate(self In Out strcat_type,value in varchar2) return 



number,

    member function ODCIAggregateMerge(self In Out strcat_type,ctx2 In Out strcat_type) 



return number,

    member function ODCIAggregateTerminate(self In Out strcat_type,returnValue Out 



varchar2,flags in number) return number

)

 

你可能感兴趣的:(oracle)