CREATE OR REPLACE PROCEDURE STRING_CHECK
( QUERY_COND IN VARCHAR2, RESP_CODE OUT VARCHAR2, RESP_MSG OUT VARCHAR2 )
IS
EM_NAME VARCHAR2(50);
BEGIN
SELECT EMAIL INTO EM_NAME FROM EMPLOYEES WHERE EMPLOYEE_ID=110 QUERY_COND;
END;
在这个简单的过程中,QUERY_COND有一个我希望在where条件之后传递的字符串,如下所示:
DECLARE
RESP_CODE VARCHAR2(20) := '000';
RESP_MSG VARCHAR2(50) := 'SUCCESS';
QUERY_COND VARCHAR2(100) := 'AND HIRE_DATE BETWEEN ''15-JUN-2003'' AND ''25-MAY-2005''';
BEGIN
DBMS_OUTPUT.PUT_LINE(QUERY_COND);
STRING_CHECK(QUERY_COND,RESP_CODE,RESP_MSG);
END;
我只是想知道是否可以这样做。如果完成,我该如何实现呢?
答案 0 :(得分:1)
您可以使用动态SQL执行此操作;例如:
CREATE OR REPLACE PROCEDURE STRING_CHECK(QUERY_COND IN VARCHAR2,RESP_CODE OUT VARCHAR2,RESP_MSG OUT VARCHAR2)
IS
EM_NAME VARCHAR2(50);
vSQL varchar2(1000);
BEGIN
vSQL := 'SELECT EMAIL FROM EMPLOYEES WHERE EMPLOYEE_ID=110 ' || QUERY_COND;
--
execute immediate vSQL into EM_NAME;
END;
DECLARE
RESP_CODE VARCHAR2(20):='000';
RESP_MSG VARCHAR2(50):='SUCCESS';
QUERY_COND VARCHAR2(100):='AND HIRE_DATE BETWEEN date ''2003-06-15'' AND date ''2005-05-25''';
BEGIN
DBMS_OUTPUT.PUT_LINE(QUERY_COND);
STRING_CHECK(QUERY_COND,RESP_CODE,RESP_MSG);
END;
请注意,我更改了处理日期的方式,以避免在不提供格式的情况下进行转换。
另外,我不推荐这样的方法来构建基于某个参数的查询;使用一些日期参数构建静态查询会更好,避免使用动态SQL。
例如:
CREATE OR REPLACE PROCEDURE STRING_CHECK_2(dateStart IN date,
dateEnd IN date,
RESP_CODE OUT VARCHAR2,
RESP_MSG OUT VARCHAR2
)
IS
EM_NAME VARCHAR2(50);
BEGIN
SELECT EMAIL
into EM_NAME
FROM EMPLOYEES
WHERE EMPLOYEE_ID=110
and HIRE_DATE BETWEEN dateStart and dateEnd;
--
END;
当然,必须对其进行细化以处理错误,并且在输入中没有给出两个日期的情况下,但我更喜欢使用布尔逻辑而不是动态布局逻辑的静态方法。
答案 1 :(得分:0)
通常,您不应该使用该方法,因为它会将代码打开到各种SQL注入漏洞:
DECLARE
RESP_CODE VARCHAR2(20):='000';
RESP_MSG VARCHAR2(50):='SUCCESS';
QUERY_COND VARCHAR2(100):=' AND EXISTS( SELECT 1 FROM your_password_table WHERE user_id = ''007'') --';
BEGIN
DBMS_OUTPUT.PUT_LINE(QUERY_COND);
STRING_CHECK(QUERY_COND,RESP_CODE,RESP_MSG);
END;
如果user_id
007
的表中有密码,则会返回结果(这几乎肯定不是您希望用户能够对此查询执行的操作)。
相反,您应该知道要过滤哪些参数并接受它们:
CREATE OR REPLACE PROCEDURE STRING_CHECK(
date_start IN EMPLOYEES.HIRE_DATE%TYPE,
date_end IN EMPLOYEES.HIRE_DATE%TYPE,
RESP_CODE OUT VARCHAR2,
RESP_MSG OUT VARCHAR2
)
IS
EM_NAME VARCHAR2(50);
BEGIN
SELECT EMAIL
INTO EM_NAME
FROM EMPLOYEES
WHERE EMPLOYEE_ID = 110
AND ( date_start IS NULL OR date_start <= hire_date )
AND ( date_end IS NULL OR hire_date <= date_end );
-- generate responses
END;
/