zoukankan      html  css  js  c++  java
  • oracle 基础知识(三)

    一、删除oracle

    进入注册表到HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesOracleOraHome91TNSListener 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_MACHINESOFTWAREORACLE,按del键删除这个入口。
    
    4、运行regedit,选择HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices,滚动这个列表,删除所有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   FilesOracle文件夹   
      4:删除开始——程序里面的oracle文件   
      5:运行regedit,删除HKEY_LOCAL_MACHINESOFTWARE下的ORACLE键   
      6:运行regedit,删除HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices下所有以oracle打头的键   
        
      到现在为止,你还是可以发现在服务里面还有oracle的服务存在,必须把他删除,否则你再安装oracle时就会出现什么服务已经存在的错误提示了!!而这些服务是在HKEY_LOCAL_MACHINESYSTEMCurrentControlSetEnumRoot下以LEGACY_ORACLE打头的,而且你选种按delete删除时系统会提示你一个错误!!不让你删除!!!现提供具体删除方法,win2000的如下:   
        
      7:运行regedt32注意了,不是regedit!!!!在HKEY_LOCAL_MACHINE那页找到HKEY_LOCAL_MACHINESYSTEMCurrentControlSetEnumRoot先选中ROOT然后点菜单上的安全—权限把自己添加到里面,并且权限设置为完全控制,确定后再删除ROOT下所有LEGACY_ORACLE打头的键,同样的方法也可以把HKEY_LOCAL_MACHINESYSTEMControlSet001和HKEY_LOCAL_MACHINESYSTEMControlSet002两个下面EnumRoot下所有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_MACHINESYSTEMCurrentControlSetServices--->删除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_MACHINESYSTEMCurrentControlSetServicesOracleServiceSID   
        
      删除组件   
      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_MACHINESOFTWAREORACLE删除ORACLE关键字   
      6、删除HKEY_LOCAL_MACHINESOFTWAREODBCODBCINST.INI中的Oracle选项   
      7、删除HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesEventLogApplication下的Oracle选项   
      8、删除HKEY_CURRENT_USERSOFTWAREORACLE下的以oracle/orcl开头的选项   
      9、删除HKEY_CURRENT_USERSOFTWAREODBCODBCINST.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:ORACLEORA81BIN;G:PROGRAM   FILESORACLEJRE1.1.7BIN     
      14、退出控制面板   
      15、进入SYSTEM_DRIVE:WINNTPROFILESALL   USERSSTART   MENUPROGRAMS.     
      16、删除图标   
      Oracle   -   HOME_NAME     
      Oracle   Installation   Products     
      where   HOME_NAME   is   the   previous   Oracle   home   name.     
      17、删除   SYSTEM_DRIVE:Program   FilesOracle目录   
      18、删除所有硬盘上   ORACLE_BASE目录     
      19、重启计算机     
        
      以上译自oracle随机文挡,如有不当之处请指正!   
        
      根据个人经验,删除的步骤最好为:   
      1、通过Oracle   Installation   Products   卸载已安装产品   
      2、在注册表中删除oracle,orcl,ora打头的注册项,可能有部分删除不了,不用管。   
      3、重起系统   
      4、删除系统下c:Program   FilesOracle目录和ORACLE_BASE目录     
        
      另:如果愿意,可将安装之前的注册表备冯文件导入试一下。   
        
        
      你没有彻底删除oracle,按如下方法可以彻底删除数据库   
        
      NT环境下:     
      1、以NT的Administrator   登陆     
      2、通过控制面版-〉服务,停掉所有ORACLE服务     
      3、打开注册表(REGEDIT命令),删除     
      HKEY_LOCAL_MACHINESOFTWAREORACLE     
      4、打开注册表中的   HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices     
        
      删除以ORACLE开头的所有服务     
      5、删除HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesEventLogA     
      pplication下     
      以ORACLE开头的所有服务     
      6、关闭REGEDIT     
      7、打开控制面版-〉系统-〉环境变量     
      8、如果ORACLE安装了JRE,就删除%ORACLE_HOME%BIN和JRE路径。     
      比如   ORACLEORA81BIN;G:   Program   FilesOraclejre1.1.7in     
      9、删除WinntProfilesAll   UsersStart   MenuProgramsOracle   和     
      WinntProfilesAll   UsersStart   MenuProgramsOracle     
      10、删除Program   FilesOracle     
      11、重新启动机器     
      12、删除所有ORACLE目录(在注册表HKEY_LOCAL_MACHINESOFTWAREORACLEORA     
      CLE_HOMES下)     
        
      在   Windows   95   /   Windows   98:     
        
      1.   打开注册表HKEY_LOCAL_MACHINESOFTWAREORACLE.     
        
      2.删除前面步骤中的第3步中的ORACLE     
        
      3.   删除AUTOEXEC.BAT   中的   %ORACLE_HOME%in   和   JRE     
        
      4.   删除所有ORACLE目录     
        
      5.   Program   FilesOracle     
        
      6.   WindowsStart   MenuProgramsOracle   -   <HOME>     
      WindowsStartMenuProgramsOracle     
        
      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
    )
  • 相关阅读:
    CRM详细介绍网址
    element上传多图片
    多图片上传WebForm
    MemCached原理
    Redis的原理
    Ninject用法详解
    SQLsugar和unity 的用法
    json中的转义字符的处理
    fiddler
    orm多表关系
  • 原文地址:https://www.cnblogs.com/lbangel/p/3530842.html
Copyright © 2011-2022 走看看