一 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,表示在修改(删除)前的值。