通过Oracle存储过程传递变量执行SQL

时间:2015-05-18 21:36:10

标签: sql oracle

我在Oracle中创建了以下存储过程:

create or replace
PROCEDURE APPUSERCT 
(
  PROJNAME IN VARCHAR2  
, WHEREDATE IN VARCHAR2 ,
cnt OUT long
) AS 
BEGIN
  select count(Distinct UPPER(field1)) into cnt from bs_log where application_name=PROJNAME and field1 is not null and log_type='info' || WHEREDATE;
END APPUSERCT;

在我的php页面中,WHEREDATE设置为:

$ whereDate =“和(TO_DATE(created_on,'mm / dd / yyyy HH24:MI:SS')> = TO_DATE('”。$ startDate。“','mm / dd / yyyy')和TO_DATE (created_on,'mm / dd / yyyy HH24:MI:SS')< = TO_DATE('“。$ endDate。”','mm / dd / yyyy'))“;

然后我绑定参数和值并调用SP:

$sql = 'BEGIN APPUSERCT(:projName,:whereDate,:cnt); END;';
$result = oci_parse($dbconn, $sql); 

oci_bind_by_name($result,':cnt',$totalRowCount,32);
oci_bind_by_name($result,':projName',$projName,32);
oci_bind_by_name($result,':whereDate',$whereDate,200);
oci_execute($result);

如果用户在php页面上没有输入日期范围,则SP中的WHEREDATE为空,并且SQL运行时没有任何范围或任何附加语法在Store Procedure(SP)中附加到它的末尾。

当用户在php页面上输入日期范围时,WHEREDATE参数变为:

and (TO_DATE(created_on,'mm/dd/yyyy HH24:MI:SS')>=TO_DATE('05/01/2015','mm/dd/yyyy') AND TO_DATE(created_on,'mm/dd/yyyy  HH24:MI:SS')<=TO_DATE('05/07/2015','mm/dd/yyyy'))

并将其附加到SP中SQL的末尾。但每当发生这种情况时,我的php页面总是从执行的SQL返回0个计数。没有错误,只有0计数。

如果我尝试直接在Oracle中运行SQL,那就是:

   select count(Distinct UPPER(field1)) as cnt from bs_log where application_name='Myweather' and field1 is not null and log_type='info' and (TO_DATE(created_on,'mm/dd/yyyy HH24:MI:SS')>= TO_DATE('05/01/2015','mm/dd/yyyy') AND TO_DATE(created_on,'mm/dd/yyyy HH24:MI:SS')<= TO_DATE('05/07/2015','mm/dd/yyyy'))

我得到了结果。我得到了倒数。但是当我通过程序调用它时,我得到0.有人能看出原因吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

好吧,出现了几个问题。

首先,我建议您将cnt参数的声明从LONG更改为NUMBERLONG不是Oracle中的数字类型;相反,它是一种不推荐使用的LOB。如果您真的想要使用BLOBCLOB,请选择适当的LOB。

其次,您不能传入包含WHERE子句的一部分的字符串(WHEREDATE参数),并将其连接到SQL语句的末尾。在这种情况下,您将WHEREDATE中的文本连接到字符串文字info,我怀疑这不是您的想法。您应该以类似于以下的方式使用动态SQL:

create or replace PROCEDURE APPUSERCT(PROJNAME IN VARCHAR2,
                                      WHEREDATE IN VARCHAR2,
                                      cnt OUT NUMBER)
AS 
  strSql_text VARCHAR2(32767) := 'select count(Distinct UPPER(field1)) ' ||
                                 ' from bs_log where application_name=''' || PROJNAME ||
                                 ''' and field1 is not null and ' ||
                                 ' log_type=''info'' ' || WHEREDATE;
  csr SYS_REFCURSOR;
BEGIN
  OPEN csr FOR strSql_text;
  FETCH csr INTO cnt;
  CLOSE csr;
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('APPUSERCT - exception : ' || SQLCODE || ' (' ||
                         SQLERRM || ')');
    RAISE;
END APPUSERCT;

因此,您将SQL语句构建为文本字符串,包括添加到WHERE子句,然后使用OPEN语句打开该语句的游标。然后获取光标,将结果放入cnt,然后关闭光标,最后退出例程。我已经包含了一个默认的EXCEPTION处理程序 - 在任何例程中总是一个好主意。