Orcale语法

一 Orcale的大字段用clob,图像用blob,clob字段在Hibernate的映射文件中用String就可以

二 Orcale备份数据库表:

    create table test_bak as select * from test

 

三 Orcale配置客户端:

    D:\oracle\product\10.1.0\Db_1\NETWORK\ADMIN\tnsnames.ora 添加

 

CSMW =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.100.93)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = CSMW)
    )
  )

 

四 VARCHAR2(10) 可以存10个字符,5个汉字

 

1)复制表结构及其数据:

create table table_name_new as select * from table_name_old

2) 只复制表结构:

create table table_name_new as select * from table_name_old where 1=2;

 

六 查找表中某列的重复记录

 

select *
          from User u
         where u.user_name in (select u.user_name 
                                 from User u
                                group by u.user_name   having count(*) > 1)

 

七 存储过程:

 

create or replace procedure test(age in number,sex in varchar,a out number) is

  v_count number;
 
  v_errorcode number;
  v_errormsg varchar2(1024);
 
begin
  v_count :=1;
        insert into USERS values(v_count,'zz',age,to_char(sex));

        a := v_count; 
        dbms_output.put_line('aaaa');
  commit;
 
end;

 

  存储过程填给两个参数赋值:

  SELECT   field_name,data_type   into   v_fieldName,v_dataType
  FROM   tapp_field   WHERE   table_id   =   p_tableID   and   field_id   =   p_fieldID;

 

 

 

八 游标

 

  动态游标: 动态游标虽然可以使游标变的很灵活,但是这使得在使用函数的时候才能确定是用哪个SQL语句,导致性能会差很多,再数据量小的时候再考虑使用。

 

create or replace function QBLRESULTINFO(Id in varchar2,inputName in varchar2) return varchar2 is
  Result varchar2(100); --这里必须是varchar2型,因为hi_antigen字段是varchar2型,字符串相加的话
                        --类型要相同
  v_sql varchar2(200);
  v_str varchar2(200);
  TYPE   c_table   IS   REF   CURSOR;  --因为这里要使用动态的字段名称,所以这里要声明为动态游标
  getResult c_table;
begin

  if inputName='hi_result' then    --不同的字段名称,对应的SQL语句也不同,这样写避免了每个字段写一个函数
  v_sql := 'select decode('||inputName||',''1'',''阳性'',''2'',''阴性'')  from lws_q_bl_result_info  i where i.id_parent = '''||Id||'''';
  elsif inputName='hi_antigen' then
  v_sql := 'select (select d.names
          from lws_dd_dict_qbl d
         where d.code = '||inputName||' and pid = 17) from lws_q_bl_result_info  i where i.id_parent = '''||Id||'''';
  end if;



  open getResult for v_sql ;
  loop
  fetch getResult into v_str;
  exit when getResult%notfound;   --必须放在Result := Result ||','|| v_str; 这句之前,否则会多执行一次该句,
                                  --因为loop是直到见到exit才退出循环的
     if(v_str is not null) then
        Result := Result ||','|| v_str;  --结果应为“阳性,阴性”这样
     end if;


  end loop;
  close getResult;


/* for z in (v_str) loop             --这里无法使用隐式游标,因为SQL语句是动态的

             if(z.hi_antigen is not null) then

              Result := Result ||','|| z.hi_antigen ;
             end if;
          end loop; */

  if(substr(Result,1,1)=',') then         --去掉字符串开头的逗号
  Result := substr(Result,2,length(Result));
  end if;

  return(Result);
end;

 

 

    显示游标:

 

   

create or replace function QBLRESULTINFO_SRH_YANG(Id in varchar2) return varchar2 is
  Result varchar2(100); --这里必须是varchar2型,因为hi_antigen字段是varchar2型,字符串相加的话
                        --类型要相同
  v_str varchar2(200);
  
 cursor getResult is select (select d.names    --声明游标
          from lws_dd_dict d
         where d.code = srh_yang and pid = 23) from lws_q_bl_result_info  i where i.id_parent = Id; 
begin

open getResult;
  loop
  fetch getResult into v_str;
  exit when getResult%notfound;   --必须放在Result := Result ||','|| v_str; 这句之前,否则会多执行一次该句,
                                  --因为loop是直到见到exit才退出循环的
     if(v_str is not null) then
        Result := Result ||','|| v_str;  --结果应为“阳性,阴性”这样
     end if;


  end loop;
  close getResult;


  if(substr(Result,1,1)=',') then         --去掉字符串开头的逗号
  Result := substr(Result,2,length(Result));
  end if;

  return(Result);
end;

 

 

   隐式游标:

  

create or replace function ANTIGEN(Id in varchar2) return varchar2 is
  Result varchar2(100); --这里必须是varchar2型,因为hi_antigen字段是varchar2型,字符串相加的话
                        --类型要相同
begin
   
  
 for z in (select decode(hi_antigen,'1','阳性','2','阴性') hi_antigen  from lws_q_bl_result_info  i where i.id_parent = Id) loop   

             if(z.hi_antigen is not null) then
           
              Result := Result ||','|| z.hi_antigen ;
             end if;  
          end loop;   
   
  if(substr(Result,1,1)=',') then         --去掉字符串开头的逗号
  Result := substr(Result,2,length(Result));
  end if;
  
  return(Result);
end ANTIGEN;

 

  ps: 静态游标(显示游标和隐式游标)要比动态游标效率高。动态游标只有在以下情况下使用。

1)把结果集返回给客户端;
2)在多个子例程之间共享游标;
3)没有其他有效的方法来达到你的目标时,则使用ref游标,正如必须用动态SQL时那样;

普通cursor与REF cursor还有一些大家应该都熟悉的区别,我再浪费点唾沫。

1)PL/SQL静态光标不能返回到客户端,只有PL/SQL才能利用它。ref光标能够被返回到客户端,这就是从Oracle的存储过程返回结果集的方式。

2)PL/SQL静态光标可以是全局的,而ref光标则不是。 也就是说,不能在包说明或包体中的过程或函数之外定义ref光标。 只能在定义ref光标的过程中处理它,或返回到客户端应用程序。

3)ref光标可以从子例程传递到子例程,而光标则不能。 为了共享静态光标,必须在包说明或包体中把它定义为全局光标。 因为使用全局变量通常不是一种很好的编码习惯,因此可以用ref光标来共享PL/SQL中的光标,无需混合使用全局变量。

       

   九 存储过程返回结果集

       存储过程返回结果集的话要使用REF CURSUR 游标返回

  

    先创建一个包:

CREATE OR REPLACE PACKAGE pkg_test
AS
      TYPE   myrctype   IS   REF   CURSOR;

      PROCEDURE   get   (p_rc   OUT   myrctype);
END   pkg_test;

   再创建包体内容:

   

CREATE OR REPLACE PACKAGE   BODY   pkg_test
AS
      PROCEDURE   get   (p_rc   OUT   myrctype)   --建立存储过程get
      IS
            sqlstr       VARCHAR2   (500);
      BEGIN
           -- 进行所需的增删改查操作,最后通过游标返回结果集
                  OPEN   p_rc   FOR
                        select * from sari_j_caseinfo t;

      END   get;
END   pkg_test;

 

   然后通过JAVA调用该存储过程:

   

  

public void testPro() {
		// TODO Auto-generated method stub
		 System.out.println("调用get存储过程!");
			
			
			Session s = dao.openSession();
		
			try {
		
				CallableStatement cs = s
							.connection()
							.prepareCall(
									"{call pkg_test.get(?)}");
					

	                cs.registerOutParameter(1, OracleTypes.CURSOR);
					cs.execute();
					ResultSet r = (ResultSet)cs.getObject(1);
					cs.close();
					
					List list = new ArrayList(); //取到的结果集转换成LIST
					while(r.next()){
						SariJCaseinfo sariJCaseinfo = new SariJCaseinfo(); 
						sariJCaseinfo.setCaseId(r.getString("case_id"));
						list.add(sariJCaseinfo);
					}
					
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					s.close();
					System.out.println("OK...");
				
				}
            
			
	}

 

 

 ps:

 1)identifier 'PKG_TEST.GET' must be declared 的错误可能是用一个用户在数据库中建立了一个存储过程,又用另一个用户去调用导致的。

 2)

org.apache.commons.dbcp.DelegatingCallableStatement with address: "oracle.jdbc.driver.OracleCallableStatement@1dc4ead" is closed.

  错误是因为之前的 ResultSet r = (ResultSet)cs.getObject(1); 放在了cs.close(); 导致的。

 

十 批量更新ID,ID号每一行+1

     两种方法:

     1)建立一个序列:

   

create   sequence   SEQ_ZSF_ID
minvalue   1
maxvalue   99999
start   with   21
increment   by   1
cache   20
order;

然后直接
update   table   set   字段   =   SEQ_ZSF_ID.nextval

     2)

    

create or replace procedure TTT is
v_str number;
begin
    v_str := 1;
    for z in (select * from test_zjj) loop
    
    update test_zjj set id = v_str where id = z.id;
    
    v_str:=v_str+1;
    end loop;

end TTT;

 

 十一  orcale中取得唯一序列的方法是 select sys_guid() from dual

 

   十二  如果数据库配置的查询中是select * from A where a like '?__'  形式,而?可能被当成字符串来解析,这时可以这样写:select * from A where a like ?||'__' ,  或者写个函数 select * from A where a like functionName(?)  

  

   十三  触发器

 

   

create or replace trigger trigger_eruption_b_detect
  after insert or update on lab_eruption_b_detect 
  for each row
declare
  -- local variables here
  -- PRAGMA AUTONOMOUS_TRANSACTION;   --①
   V_MSG      VARCHAR2(200);
   V_CODE     VARCHAR2(20);  --记录发生错误的操作

begin       
      IF INSERTING THEN  --当执行的操作是插入
      V_CODE := 'INSERT';
insert into pathogeny_center(id_pathogeny_center, pathogeny_type, pathogeny_name, detect_way,
       detect_result, sociotomy_result, type_result, first_detect_date, detect_unit, sample_id, sample_type,
       sample_date, disease, patient_id, symptom, birthday, vis_date, disease_date, area, code_hospital,
       code_hospital_new, code_address, case_type, age, age_unit, sex, patient_job, is_outbreak, orgcode_add, 
       date_add, age_group)
(select lab_seq.nextval,'02' pathogeny_type ,'030201' pathogeny_name,'01' detect_way,d.i_tab_separate,
       '' sociotomy_result,'' type_result,d.first_detect_date,d.detect_unit,s.sample_id,s.sample_type,
       s.sample_date,s.disease,p.patient_id,p.syndrome,p.birthday,p.vis_date,p.disease_date,'' area,p.code_hospital,
       p.code_hospital_new,p.code_address,p.case_type,p.age,p.age_unit,p.sex,p.patient_job,'' is_outbreak,p.orgcode_add,
       p.date_add,'' age_group
from lab_eruption_b_detect d,lab_sampleinfo s,lab_patient p 
where d.id_sampleinfo = s.id_sampleinfo and s.id_patient = p.id_patient  and s.id_sampleinfo = :NEW.id_sampleinfo);
commit;    
      ELSIF UPDATING THEN  --当执行的操作是修改
      V_CODE := 'MODIFY';  
      update.....

      END IF;

       --记录错误日志
  EXCEPTION
  WHEN OTHERS THEN
    V_MSG  := SUBSTR(SQLERRM, 1, 200);
    V_CODE := V_CODE;
    INSERT INTO RPT_QUERY_ERR_LOG
      (OPDATE, FUNCNAME, ERRCODE, ERRMSG)
    VALUES
      (SYSDATE, 'trigger_eruption_b_detect', V_CODE, V_MSG);

end trigger_eruption_b_detect;

  

    ps:

     1. mysql只能对每一行触发一次,而oracle可以对每一行整个表触发一次。

     2.mysql只能是表的行激活触发器,但oracle可以做到对列触发。

 

  

    1:在写trigger的时候,经常会遇到这种情况
当在程序块中需要对trigger本表进行修改或查询的时候,系统会提示错误:  ORA-04091: table is mutating, trigger/function may not see it,关于这个错误,其实是由于对本表的操作造成的.ORACLE DB里默认在写TRIGGER的时候把本表锁死,不允许对其进行操作,也就是说这个错误是不能通过系统的手段解决的,只能改用一些其它的SQL来绕开它.
刚接触TRIGGER的时候会经常犯这样的错误,其中有大部分是可以通过:new 来解决的。但是还会有一定要对本表进行修改或查询操作的情况,不能避免.这里的解决办法则是加上①语句。(如上面的SQL语句其实可以把trigger本表lab_eruption_b_detect表去掉,用:NEW的形式,:NEW表示在执行完操作后(插入,修改)后该条字段在表中的值,如:new.first_detect_date,相对的是:old,表示在修改(删除)前的值。

 

 

 

你可能感兴趣的:(oracle,Hibernate)