??xml version="1.0" encoding="utf-8" standalone="yes"?> CREATE OR REPLACE PROCEDURE SP_EMPLOYEE_AUTONOMOUS PRAGMA AUTONOMOUS_TRANSACTION; CREATE OR REPLACE PROCEDURE SP_EMPLOYEE BEGIN INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('003','TS1'); CREATE OR REPLACE PROCEDURE SP_EMPLOYEE_AUTONOMOUS INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('001','TS1'); PRAGMA AUTONOMOUS_TRANSACTION; 1、直接执行动态SQL vs_sql VARCHAR2(4000); BEGIN vs_sql := 'UPDATE EMPLOYEE_T SET EMPLOYEE_NAME='||CHR(39)||'zsj'||CHR(39)||' WHERE EMPLOYEE_ID = 001'; WHEN OTHERS THEN end SP_DEAL; 2、执行有输出l果的动态SQL vn_num NUMBER(2); BEGIN vs_sql := 'SELECT COUNT(EMPLOYEE_ID) FROM EMPLOYEE_T'; WHEN OTHERS THEN end SP_DEAL_OUT; 3、执行有输入参数与输出结果的动态SQL --select时?br />
CREATE OR REPLACE PROCEDURE SP_DEAL_IN_OUT vn_num NUMBER(2); BEGIN vs_employee_id := '001'; vs_sql := 'INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME) VALUES (:1,:2) RETURNING EMPLOYEE_ID INTO :3'; WHEN OTHERS THEN end SP_DEAL_IN_OUT; CREATE OR REPLACE PROCEDURE SP_EMPLOYEE( vs_sql VARCHAR2(4000); BEGIN vs_sql := 'SELECT EMPLOYEE_ID,EMPLOYEE_NAME FROM EMPLOYEE_T '; end SP_EMPLOYEE; BEGIN vs_sql := 'SELECT EMPLOYEE_ID,EMPLOYEE_NAME FROM EMPLOYEE_T '; LOOP WHEN OTHERS THEN end SP_EMPLOYEE; vs_sql VARCHAR2(1000); --动态SQL描述 BEGIN WHEN OTHERS THEN
Expression exp = new Expression("(x + y)/2");
Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
variables.put("x", new BigDecimal("4.32"));
variables.put("y", new BigDecimal("342.1"));
BigDecimal result = exp.eval(variables);
System.out.println(result);
// 布尔?br />Expression ww = new Expression("( A && B ) || C ");
Map<String, BigDecimal> vs = new HashMap<String, BigDecimal>();
vs.put("A", new BigDecimal("0"));
vs.put("B", new BigDecimal("1"));
vs.put("C", new BigDecimal("1"));
System.out.println(ww.eval(vs));
// 布尔?
Expression dd = new Expression(" A > 200 ");
Map<String, BigDecimal> as = new HashMap<String, BigDecimal>();
as.put("A", new BigDecimal("12000"));
System.out.println(dd.eval(as));
需要eval.jar
]]>
服务端Oracle 11g
客户端Oracle 10g
--准备脚本
DROP TABLE EMPLOYEE_SALARY_T;
CREATE TABLE EMPLOYEE_SALARY_T(
EMPLOYEE_ID VARCHAR2(20),
EMPLOYEE_NAME VARCHAR2(20),
DEPARTMENT VARCHAR2(10),
COMPANY VARCHAR2(10),
SALARY NUMBER(6),
SALARY_YEAR VARCHAR2(10)
);
INSERT INTO EMPLOYEE_SALARY_T VALUES('001','znp','dep001','VisSoft',30000,'2005');
INSERT INTO EMPLOYEE_SALARY_T VALUES('001','znp','dep001','VisSoft',40000,'2006');
INSERT INTO EMPLOYEE_SALARY_T VALUES('001','znp','dep001','VisSoft',50000,'2007');
INSERT INTO EMPLOYEE_SALARY_T VALUES('001','znp','dep001','VisSoft',60000,'2008');
INSERT INTO EMPLOYEE_SALARY_T VALUES('002','zsj','dep001','AvsSoft',3000,'2005');
INSERT INTO EMPLOYEE_SALARY_T VALUES('002','zsj','dep001','AvsSoft',4000,'2006');
INSERT INTO EMPLOYEE_SALARY_T VALUES('002','zsj','dep001','AvsSoft',5000,'2007');
INSERT INTO EMPLOYEE_SALARY_T VALUES('002','zsj','dep001','AvsSoft',6000,'2008');
INSERT INTO EMPLOYEE_SALARY_T VALUES('003','ts1','dep002','VisSoft',30000,'2005');
INSERT INTO EMPLOYEE_SALARY_T VALUES('003','ts1','dep002','VisSoft',40000,'2006');
INSERT INTO EMPLOYEE_SALARY_T VALUES('003','ts1','dep002','VisSoft',50000,'2007');
INSERT INTO EMPLOYEE_SALARY_T VALUES('003','ts1','dep002','VisSoft',60000,'2008');
INSERT INTO EMPLOYEE_SALARY_T VALUES('004','ts2','dep002','AvsSoft',3000,'2005');
INSERT INTO EMPLOYEE_SALARY_T VALUES('004','ts2','dep002','AvsSoft',4000,'2006');
INSERT INTO EMPLOYEE_SALARY_T VALUES('004','ts2','dep002','AvsSoft',5000,'2007');
INSERT INTO EMPLOYEE_SALARY_T VALUES('004','ts2','dep002','AvsSoft',6000,'2008');
COMMIT;
--行查询实现脚本
--查询含义为将09qdep001部门的salary预定部门05q?6q与08q的d
--而dep002部门09q的salary预定部门06q?7q与08q的d
SELECT COMPANY,DEPARTMENT,SALARYS FROM EMPLOYEE_SALARY_T
MODEL
RETURN UPDATED ROWS --是否昄基本查询?如果有该行则不显C基本查询行Q只昄查询计算l果?br />
PARTITION BY (COMPANY) --分区Q对行计结果的分区Q本例中以company列做为分区项
DIMENSION BY (DEPARTMENT,SALARY_YEAR ) --军_两个计算的维度,当前表示W一l度为部门,W二l度资年?br />
MEASURES (SALARY SALARYS) --我的理解是规则指向列Q即对哪一列进行规则计或规则改变
RULES (
SALARYS['dep001', '2009'] = SALARYS['dep001', '2005'] + SALARYS['dep001', '2006']+ SALARYS['dep001', '2008'],
SALARYS['dep002', '2009'] = SALARYS['dep002', '2006'] + SALARYS['dep002', '2007']+ SALARYS['dep002', '2008']
);
x如果用列U查询时实现的效果(^_^ 是不是比较地不麻烦)
PS:把COMPANY的gDEPARTMENT的D成同步,即DEPARTMENT?01时公司全部ؓAvsSoft,DEPARTMENT?02时公司全部ؓVisSoft。看看结果如何?
元旦快乐
]]>
CREATE TABLE EMPLOYEE_T
(
EMPLOYEE_ID VARCHAR2(20),
EMPLOYEE_NAME VARCHAR2(20)
);
在存储过E中Q尤其是一l相互调用的存储q程中如果要为其中的每个存储q程记录执行日志时会存在比较ȝ的问题。即在操作出现异常时如何记录相关异常日志(q个时候的日志应该才是最重要的吧>_<!!!)Q此时如果调用一般的事务方式q行commit以保存日志则脚本~写会相当烦琐且l护性差。此时可以考虑采用自治事务的方式来提交执行日志
自治事务相当于与当前事务q行的另一个事务,其提交与否ƈ不媄响当前主要事务的提交与回滚,通常定义在函C存储q程之中方式如下
IS
BEGIN
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('007','TS5');
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('008','TS6');
COMMIT;
END SP_EMPLOYEE_AUTONOMOUS;
配合实现方式?br />
IS
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('004','TS2');
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('005','TS3');
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('006','TS4');
SP_EMPLOYEE_AUTONOMOUS();
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('009','TS7');
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('0010','TS8');
ROLLBACK;
END SP_EMPLOYEE;
则执行的l果则只插入007?08两条记录
PS:一U错误的实现方式Q如?br />
IS
BEGIN
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('002','TS2');
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('007','TS5');
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('008','TS6');
COMMIT;
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('003','TS7');
INSERT INTO EMPLOYEE_T(EMPLOYEE_ID,EMPLOYEE_NAME)VALUES('004','TS8');
ROLLBACK;
END SP_EMPLOYEE_AUTONOMOUS;
此时~译与执行SP_EMPLOYEE_AUTONOMOUS且不报错Q但是执行的l果~~~~~~~~~~~~~~~~~ ^_^
]]>
动态SQL是存储过E及函数中常用的实现查询操作手段Q以下记录几U常用Ş式以供自?br />
CREATE TABLE EMPLOYEE_T(
EMPLOYEE_ID VARCHAR2(20) NOT NULL,
EMPLOYEE_NAME VARCHAR2(20)
);
CREATE OR REPLACE PROCEDURE SP_DEAL
IS
EXECUTE IMMEDIATE vs_sql;
COMMIT;
EXCEPTION
ROLLBACK;
CREATE OR REPLACE PROCEDURE SP_DEAL_OUT
IS
vs_sql VARCHAR2(4000);
EXECUTE IMMEDIATE vs_sql INTO vn_num;
EXCEPTION
ROLLBACK;
IS
vs_sql VARCHAR2(4000);
vs_employee_id EMPLOYEE_T.EMPLOYEE_ID%TYPE;
vs_employee_name EMPLOYEE_T.EMPLOYEE_NAME%TYPE;
vs_out_employee_id EMPLOYEE_T.EMPLOYEE_ID%TYPE;
vs_msg VARCHAR2(4000);
vs_employee_name := 'znp';
EXECUTE IMMEDIATE vs_sql USING vs_employee_id,vs_employee_name RETURN INTO vs_out_employee_id ;
COMMIT;
EXCEPTION
vs_msg :=SQLERRM;
ROLLBACK;
1、通过动态SQL直接提取查询l果,q回查询l果?/p>
cur OUT SYS_REFCURSOR
)
IS
OPEN cur FOR vs_sql;
2、通过动态SQL提取查询l果?通过昑ּ游标方式q行处理
CREATE OR REPLACE PROCEDURE SP_EMPLOYEE
IS
vs_sql VARCHAR2(4000);
vs_id EMPLOYEE_T.EMPLOYEE_ID%TYPE;
vs_name EMPLOYEE_T.EMPLOYEE_NAME%TYPE;
TYPE cur_cursor IS REF CURSOR;
cur cur_cursor;
OPEN cur FOR vs_sql;
FETCH cur INTO vs_id,vs_name;
UPDATE EMPLOYEE_T
SET EMPLOYEE_NAME = vs_name
WHERE EMPLOYEE_ID = vs_id;
EXIT WHEN cur%NOTFOUND;
END LOOP;
CLOSE cur;
COMMIT;
EXCEPTION
ROLLBACK;
3、通过动态SQL直接调用存储q程
CREATE OR REPLACE PROCEDURE SP_DEAL(
is_name VARCHAR2
)
IS
--拼接动态调用哪一个存储过E?指定三个调用形参)
vs_sql := 'BEGIN SP_'||is_name||'_BACKUP(:V1,:V2,:V3,:v4); END;';
--执行动态SQL,同时指定一个入参与两个出差
EXECUTE IMMEDIATE vs_sql USING IN is_id, IN is_para,OUT on_flag,OUT os_msg;
EXCEPTION
on_flag := -1;
os_msg := 'SP_'||is_name||':'||SUBSTR(SQLERRM,0,200);
END SP_DOUBT_BACKUP;
4、ؓ动态SQL指定入参
]]>
Server Oracle 11g
Client Oracle 10g
vs_string 输入参数格式?info1,info22,info333,info4444',?,"做间隔符,每变量长度不定
vn_num vs_string 中合q拼接的变量数量
SELECT SUBSTR(vs_string,
DECODE(LEVEL,1,0,(INSTR(vs_string,',',1,LEVEL-1)))+1,
DECODE(LEVEL,vn_num,LENGTH(vs_string),INSTR(vs_string,',',1,DECODE(LEVEL,1,1,LEVEL))-1)-
(DECODE(LEVEL,1,0,(INSTR(vs_string,',',1,LEVEL-1)))+1)+1)
FROM DUAL
CONNECT BY LEVEL <= (SELECT REGEXP_COUNT(vs_string,',',1,'i')+1 FROM DUAL);
在oracle ?IN 函数只能Ҏ询的l果集或明确的参数集合进行多行查询,对于一个参数无论其表现形式只能q行一个参数的判断查询
?/p>
EMPLOYEE_T 表中存在如下数据
EMPLOYEE_ID EMPLOYEE_NAME
--------------------------------
001 znp
002 zsj
003 zhsj
SELECT EMPLOYEE_ID,EMPLOYEE_NAME FROM EMPLOYEE_T WHERE EMPLOYEE_ID IN ('001','002')的查询结果如?/p>
EMPLOYEE_ID EMPLOYEE_NAME
--------------------------------
001 znp
002 zsj
SELECT EMPLOYEE_ID,EMPLOYEE_NAME FROM EMPLOYEE_T WHERE EMPLOYEE_ID IN ('001,002')的查询结果如?/p>
EMPLOYEE_ID EMPLOYEE_NAME
--------------------------------
?SELECT * FROM EMPLOYEE_T WHERE EMPLOYEE_ID IN ('001,002') ?"'001,002'" 只能做ؓ一个入参而不是两个入?参数gؓ
'001,002' ,故查不到合适的记录
在存储过E中对于以上的入参可以采取两U办法进?/p>
1、通过拼接动态SQLq行查询
vs_sql := 'SELECT EMPLOYEE_ID,EMPLOYEE_NAME FROM EMPLOYEE_T WHERE EMPLOYEE_ID IN ('||CHR(39)||'001'||CHR(39)||','||CHR(39)||'002'||CHR(39)||');
OPEN _cur FOR vs_sql;
2、将拼接串{为结果集输出至IN函数?使用如下脚本
vs_string 输入参数格式?info1,info22,info333,info4444',?,"做间隔符,每变量长度不定
vn_num vs_string 中合q拼接的变量数量
SELECT SUBSTR(vs_string,
DECODE(LEVEL,1,0,(INSTR(vs_string,',',1,LEVEL-1)))+1,
DECODE(LEVEL,vn_num,LENGTH(vs_string),INSTR(vs_string,',',1,DECODE(LEVEL,1,1,LEVEL))-1)-
(DECODE(LEVEL,1,0,(INSTR(vs_string,',',1,LEVEL-1)))+1)+1)
FROM DUAL
CONNECT BY LEVEL <= (SELECT REGEXP_COUNT(vs_string,',',1,'i')+1 FROM DUAL);
照办上例,即ؓ
SELECT EMPLOYEE_ID,EMPLOYEE_NAME FROM EMPLOYEE_T
WHERE EMPLOYEE_ID IN
(
SELECT SUBSTR(vs_string,
DECODE(LEVEL,1,0,(INSTR(vs_string,',',1,LEVEL-1)))+1,
DECODE(LEVEL,vn_num,LENGTH(vs_string),INSTR(vs_string,',',1,DECODE(LEVEL,1,1,LEVEL))-1)-
(DECODE(LEVEL,1,0,(INSTR(vs_string,',',1,LEVEL-1)))+1)+1)
FROM DUAL
CONNECT BY LEVEL <= (SELECT REGEXP_COUNT(vs_string,',',1,'i')+1 FROM DUAL)
);
-- a.ctl
Load data --加蝲数据
infile a.txt --加蝲数据文g名称(现在是相对\?可以写成l对路径c:\bak.txt)
badfile a.bad --p|数据写入文g
append -- append q加 truncate truncate delete 删除
into table t_employee_bak --插入操作?br />
FIELDS TERMINATED BY '|' --Ҏ指定标识W隔断各字段?OPTIONALLY ENCLOSED BY '"' qo掉指定的标识W??{?br />
(employee_id, --指定插入字段及数?br />
employee_name,
employee_salary)
准备完成后,在cmd下输?br />
sqlldr -userid zhsj/zhsj@zhsj control=c:\a.ctl
执行Q在t_employee_bak表中可以见到a.txt中的数据已导?br />
在执行过E如果出现数据没有导入的情况Q可能原因会有以下几U情?br />
1、在导出的数据文件中存在同时打印输出的命令行Q将命o行删除后重新保存文g卛_数据正常插入到数据库中
2、虽然文本中已是正确的数据但仍然无法导入,此时在执行的SQL脚本中增加一个间隔符的输出,?br />
select employee_id||'|'||employee_name||'|'||employee_salary from t_employee;
改ؓ
select employee_id||'|'||employee_name||'|'||employee_salary||'|' from t_employee;
此时会正常导入Q这是因为列值存在空数据D间隔计算问题
以上为txt格式数据文g导出
对于异质数据库,可以采用sqldeveloper{工具将相关数据库中数据以csv格式导出Q此时在~写执行脚本旉变更如下
-- a.ctl
Load data --加蝲数据
infile a.txt --加蝲数据文g名称(现在是相对\?可以写成l对路径c:\bak.txt)
badfile a.bad --p|数据写入文g
append -- append q加 truncate truncate delete 删除
into table t_employee_bak --插入操作?br />
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' --Ҏ指定标识W隔断各字段?OPTIONALLY ENCLOSED BY '"' qo掉指定的标识W??{?br />
(employee_id, --指定插入字段及数?br />
employee_name,
employee_salary)
因ؓcsv格式文g在用txt打开可以看到数据文g格式?1","znp","80000.00"Q需要将' " '标识W去掉,才可以正常导?br />
大数据量时csv格式文g会比txt格式文g?倍左叻I且导入时可能出现问题Q所以尽量采用txt文g方式导入