首页 运维知识 关于oracle 存储过程 动态sql语句

关于oracle 存储过程 动态sql语句

一、在oracle项目开发中越到问题: 在利用ODP向oracle中插入数据时,如果这样写: insert into clobTable (id, story) values(1,…

一、在oracle项目开发中越到问题:

在利用ODP向oracle中插入数据时,如果这样写:
insert into clobTable (id, story) values(1,\’….\’); 其中story为clob类型
如果story的长度大于2000字节,直接插入将出现 ORA-01704:文字字符串过长 的错误。
解决方案:
方案一、利用参数
insert into clobTable (id, story) values(1,:story);
OracleParameter param = new OracleParameter(“story”, OracleDbType.Clob);
param.Direction = ParameterDirection.Input;
param.Value = str;
cmd.Parameters.Add(param);
方案二、利用存储过程
这个就不用说了,写个存储过程,把参数传入即可。

二、解决方法

oracle 中,如下操作:

insert into table values(a,3,\’一个长文章\’);

ORA-01704: 文字字符串过长!

虽然在表中已经是clob字段,足够存储4G的内容,但是如果存的是特别长的字符串,超过4000就会报错。

解决方法:

方法一:就写个存储过程,然后用参数传过去就没问题了。

declare

v_clob clob :=\’一个长文章\’;

begin
insert into table values(a,3,:clob);
end;

这样就可以插进去了,所以我觉得应该是隐式转换,oracle默认把字符串 转换成 varchar2 类型,
而这个字符串的长度,又比4000大 所以会报ora-01704错误.

真实环境用的存储过程:

CREATE OR REPLACE PROCEDURE “BAI”.”LOGMNRTXT” (tab1 in varchar2,scns in number,timestamps in varchar2,seg_owner in varchar2,
table_name in varchar2,session_info in varchar2,sql_redo in clob,ssession in varchar2,serial in varchar2,operation in varchar2) is

str varchar(1000);
–注意tab1必须要更改,发现原来的logmnr_contents20140524中的sql_redo为varchar,需要改成clob
begin

str:= \’insert into \’||tab1||\’ values(:1,:2,:3,:4,:5,:6,:7,:8,:9)\’;
execute immediate str using scns,to_date(timestamps,\’yyyy-MM-dd hh24:mi:ss\’),seg_owner,table_name,session_info,sql_redo,ssession,serial,operation;
end logmnrtxt;
/

方法二:很复杂,其实没必要这么用,主要是为了学习高级的存储过程写法

创建存储过程:
CREATE OR REPLACE PROCEDURE p_In_Clob(pId IN NUMBER,outVar IN VARCHAR2)
IS
text_Var  CLOB;
amount_Var  NUMBER;
offset_Var  NUMBER;
BEGIN
INSERT INTO test VALUES(pId,empty_clob());
SELECT text INTO text_var FROM test
WHERE id=pId;
amount_var:=LENGTH(outVar);
offset_var:=1;
DBMS_LOB.WRITE(text_Var,amount_Var,offset_Var,outVar);
COMMIT;
END p_In_Clob;

调用存储过程:
begin
p_In_Clob(1,\’…\’);
end;

三、oracle 存储过程使用动态sql

Oracle存储过程使用动态SQL 有两种写法:用 DBMS_SQL 或 execute immediate,建议使用后者。试验步骤如下:

1. DDL和DML (注意DDL中可以用拼接字符串的方法用来create table或drop table,在DML中,类似于insert则不可以直接用execute immediate中直接拼接的方法,必须用using传递参数)

 1     /*** DDL ***/  
 2     begin   
 3         EXECUTE IMMEDIATE \'drop table temp_1\';   
 4         EXECUTE IMMEDIATE \'create table temp_1(name varchar2(8))\';   
 5     end;  
 6      
 7     /*** DML ***/  
 8     declare   
 9         v_1 varchar2(8);   
10         v_2 varchar2(10);   
11         str varchar2(50);   
12     begin   
13         v_1:=\'测试人员\';   --这里的v_1,v_2可以是直接存储过程中传过来的参数
14         v_2:=\'北京\';   
15         str := \'INSERT INTO test (name ,address) VALUES (:1, :2)\';   
16         EXECUTE IMMEDIATE str USING v_1, v_2;   
17         commit;   
18     end;

 

2. 返回单条结果

例1:

 1     declare   
 2         str varchar2(500);   
 3         c_1 varchar2(10);   
 4         r_1 test%rowtype;   
 5     begin   
 6         c_1:=\'测试人员\';   
 7         str:=\'select * from test where name=:c WHERE ROWNUM=1\';   
 8         execute immediate str into r_1 using c_1;   
 9         DBMS_OUTPUT.PUT_LINE(R_1.NAME||R_1.ADDRESS);   
10     end ;

例2:

 1     declare  
 2         v_col_name varchar2(30) := \'name\'; --字段名 name 用变量来表示  
 3         v_user_name  varchar2(30); --用户名称  
 4         v_user_age  integer;       --用户年龄  
 5         v_sql_str  varchar2(500);  --动态 SQL 语句  
 6     begin  
 7         v_sql_str := \'select \'||v_col_name||\',age from users --字段名后面不能紧随 into 到变量了  
 8                        where age between :start_age and :end_age and rownum=1\'; --两个命名参数  ,注意拼接的方法
 9           
10         --用 execute immediate 动态执行 SQL 语句  
11         --注意其后的 into 字段值到变量的写法,还有 using 来代入参数  
12         execute immediate v_sql_str into v_user_name,v_user_age using 18,25;   
13           
14         dbms_output.put_line(\'第一个符合条件的用户:\'||v_user_name||\',年龄:\'||v_user_age);  
15     end;

 

3. 返回结果集

 1     CREATE OR REPLACE package pkg_test as   
 2         /* 定义ref cursor类型   
 3         不加return类型,为弱类型,允许动态sql查询,   
 4         否则为强类型,无法使用动态sql查询;   
 5         */   
 6         type myrctype is ref cursor;  
 7      
 8         --函数申明   
 9         function get(intID number) return myrctype;   
10     end pkg_test;   
11     /  
12      
13     CREATE OR REPLACE package body pkg_test as   
14     --函数体   
15         function get(intID number) return myrctype is   
16             rc myrctype; --定义ref cursor变量   
17             sqlstr varchar2(500);   
18         begin   
19             if intID=0 then   
20                 --静态测试,直接用select语句直接返回结果   
21                 open rc for select id,name,sex,address,postcode,birthday from   
22     student;   
23             else   
24                 --动态sql赋值,用:w_id来申明该变量从外部获得   
25                 sqlstr := \'select id,name,sex,address,postcode,birthday from student   
26     where id=:w_id\';   
27                 --动态测试,用sqlstr字符串返回结果,用using关键词传递参数   
28                 open rc for sqlstr using intid;   
29             end if;  
30      
31             return rc;   
32         end get;  
33      
34     end pkg_test;   
35     /

四、存储过程一个总结的非常全的博客

http://www.cnblogs.com/chinafine/archive/2010/07/12/1776102.html

免责声明:文章内容不代表本站立场,本站不对其内容的真实性、完整性、准确性给予任何担保、暗示和承诺,仅供读者参考,文章版权归原作者所有。如本文内容影响到您的合法权益(内容、图片等),请及时联系本站,我们会及时删除处理。

作者: 小小编

为您推荐

dell R710 更换raid卡后,raid卡信息没有了,处理方案

dell R710 更换raid卡后,raid卡信息没有了,处理方案

1.将一台服务器(A)的硬盘依次拔出,按相同顺序插入另一台同样配置的服务器(B) 2.启动服务器(B) 3.按提示键盘按...
PL SQL Developer 13连接Oracle数据库并导出数据详细操作教程方法

PL SQL Developer 13连接Oracle数据库并导出数据详细操作教程方法

下载 并安装 PL SQL Developer 13,默认支持中文语言 ========================...
关于一条sql语句在mysql中是如何执行的

关于一条sql语句在mysql中是如何执行的

最近开始在学习mysql相关知识,自己根据学到的知识点,根据自己的理解整理分享出来,本篇文章会分析下一个sql语句在my...
关于sql注入姿势总结(mysql)

关于sql注入姿势总结(mysql)

前言 学习了sql注入很长时间,但是仍然没有系统的了解过,这次总结一波,用作学习的资料。 从注入方法分:基于报错、基于布...
关于Oracle SQL外连接

关于Oracle SQL外连接

SQL提供了多种类型的连接方式,它们之间的区别在于:从相互交叠的不同数据集合中选择用于连接的行时所采用的方法不同。 连接...

发表回复

返回顶部