我无法编译Oracle代码的这一部分,因为编译器报告“PL / SQL:ORA-00942:表或视图不存在”
Oracle表存在,但此过程必须根据“Order_ID”参数将表名传递给For循环过程。我在表所在的Schema中工作,所以我没有解决模式名称。
示例:TEMP_TBL_123存在于数据库中,通过传递order_ID为123,我试图使用变量TMP_TBL_NM来保存表名“TEMP_TBL_123”。
............................................... ..
CREATE OR REPLACE PROCEDURE EMAIL_DEPT_BLAST_TEST (SUBJECT VARCHAR2,MAIL_FROM VARCHAR2, MAIL_TO VARCHAR2,
L_MESSAGE VARCHAR2, L_MESSAGE2 VARCHAR2, ORDER_ID NUMBER)
IS
MAIL_HOST VARCHAR2(30):='XX.XX.XX.XX';
MAIL_CONN UTL_SMTP.CONNECTION;
TMP_TBL_NM VARCHAR2(30);
BEGIN
TMP_TBL_NM := 'TEMP_TBL_' || ORDER_ID;
MAIL_CONN := UTL_SMTP.OPEN_CONNECTION(MAIL_HOST, 25);
UTL_SMTP.HELO(MAIL_CONN, MAIL_HOST);
UTL_SMTP.MAIL(MAIL_CONN,'XXX@XXXXXX.com');
UTL_SMTP.RCPT(MAIL_CONN, MAIL_TO);
UTL_SMTP.OPEN_DATA(MAIL_CONN);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'Date: '||to_char(trunc(SYSDATE))||utl_tcp.crlf);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'From: '|| mail_from ||utl_tcp.crlf);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'To: '|| mail_to || utl_tcp.crlf);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'Subject: '||subject||utl_tcp.crlf);
UTL_SMTP.WRITE_DATA(MAIL_CONN, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(MAIL_CONN, ''|| L_MESSAGE || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(MAIL_CONN, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'Order details:' || UTL_TCP.crlf);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'Quantity - Location ID - Address' || UTL_TCP.crlf);
BEGIN
FOR I IN (SELECT LOCATION_ID, TRIM(TO_CHAR(COUNT(*),'9,999')) AS QUANTITY FROM TMP_TBL_NM GROUP BY LOCATION_ID)
LOOP
UTL_SMTP.WRITE_DATA(MAIL_CONN, I.QUANTITY || ' - ');
UTL_SMTP.WRITE_DATA(MAIL_CONN, I.LOCATION_ID || ' ');
UTL_SMTP.WRITE_DATA(MAIL_CONN,UTL_TCP.CRLF);
END LOOP;
END;
UTL_SMTP.WRITE_DATA(MAIL_CONN, L_MESSAGE2 || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(MAIL_CONN,UTL_TCP.CRLF);
UTL_SMTP.CLOSE_DATA(MAIL_CONN);
UTL_SMTP.QUIT(MAIL_CONN);
END SCT_CNTS_EMAIL_DEPT_BLAST_TEST;
答案 0 :(得分:5)
我没有太多运气让约翰的榜样有效。这是做的事情:
DECLARE
C SYS_REFCURSOR;
stmt VARCHAR2(1000);
tmp_tbl_nm VARCHAR2(64) := 'USER_TABLES';
the_name VARCHAR2(64);
BEGIN
stmt := 'SELECT table_name FROM ' || TMP_TBL_NM || ' ORDER BY 1';
OPEN C FOR stmt;
LOOP
FETCH C INTO the_name;
EXIT WHEN C%NOTFOUND;
dbms_output.put_line(the_name);
END LOOP;
END;
/
CONTINENT
COUNTRY
COUNTRYINFOIMPORT
COUNTRY_LANGUAGE
GEONAME
LANGUAGE
PL/SQL procedure successfully completed.
SQL>
我认为您不能使用EXECUTE IMMEDIATE语句返回游标。 This documentation page,第二段,似乎表明没有。无论如何,你不需要它,只需使用OPEN - FOR语法。
答案 1 :(得分:1)
你得到PL / SQL的原因是:ORA-00942是因为在原始代码中编译器正在寻找一个名为“TMP_TBL_NM”的表。这在您的模式中不存在,实际上是一个在PL / SQL中保存表名的变量。
我冒昧地调整了之前的答案并使用了一些动态SQL来为你的答案提供变体。
CREATE OR REPLACE PROCEDURE EMAIL_DEPT_BLAST_TEST (SUBJECT VARCHAR2,MAIL_FROM VARCHAR2, MAIL_TO VARCHAR2,
L_MESSAGE VARCHAR2, L_MESSAGE2 VARCHAR2, ORDER_ID NUMBER)
IS
MAIL_HOST VARCHAR2(30):='XX.XX.XX.XX';
MAIL_CONN UTL_SMTP.CONNECTION;
TMP_TBL_NM VARCHAR2(30);
BEGIN
TMP_TBL_NM := 'TEMP_TBL_' || ORDER_ID;
MAIL_CONN := UTL_SMTP.OPEN_CONNECTION(MAIL_HOST, 25);
UTL_SMTP.HELO(MAIL_CONN, MAIL_HOST);
UTL_SMTP.MAIL(MAIL_CONN,'XXX@XXXXXX.com');
UTL_SMTP.RCPT(MAIL_CONN, MAIL_TO);
UTL_SMTP.OPEN_DATA(MAIL_CONN);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'Date: '||to_char(trunc(SYSDATE))||utl_tcp.crlf);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'From: '|| mail_from ||utl_tcp.crlf);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'To: '|| mail_to || utl_tcp.crlf);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'Subject: '||subject||utl_tcp.crlf);
UTL_SMTP.WRITE_DATA(MAIL_CONN, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(MAIL_CONN, ''|| L_MESSAGE || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(MAIL_CONN, UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'Order details:' || UTL_TCP.crlf);
UTL_SMTP.WRITE_DATA(MAIL_CONN, 'Quantity - Location ID - Address' || UTL_TCP.crlf);
TYPE ItemRec IS RECORD (
loc_id NUMBER,
qty_cnt NUMBER);
TYPE ItemSet IS TABLE OF ItemRec;
all_items ItemSet;
BEGIN
stmt := 'SELECT LOCATION_ID, TRIM(TO_CHAR(COUNT(*),'9,999')) AS QUANTITY FROM '||TMP_TBL_NM ||' GROUP BY LOCATION_ID';
EXECUTE IMMEDIATE stmt
BULK COLLECT
INTO all_items;
FOR i IN all_items.FIRST..all_items.LAST
LOOP
UTL_SMTP.WRITE_DATA(MAIL_CONN, I.QUANTITY || ' - ');
UTL_SMTP.WRITE_DATA(MAIL_CONN, I.LOCATION_ID || ' ');
UTL_SMTP.WRITE_DATA(MAIL_CONN,UTL_TCP.CRLF);
END LOOP;
END;
UTL_SMTP.WRITE_DATA(MAIL_CONN, L_MESSAGE2 || UTL_TCP.CRLF);
UTL_SMTP.WRITE_DATA(MAIL_CONN,UTL_TCP.CRLF);
UTL_SMTP.CLOSE_DATA(MAIL_CONN);
UTL_SMTP.QUIT(MAIL_CONN);
END SCT_CNTS_EMAIL_DEPT_BLAST_TEST;
答案 2 :(得分:0)
将变量传递到这样的SQL语句的唯一方法是将查询作为dynamic sql运行。
您的代码可能类似于:
DECLARE
query_output SYS_REFCURSOR;
query_statement VARCHAR2(1000);
BEGIN
query_statement := 'SELECT LOCATION_ID, TRIM(TO_CHAR(COUNT(*),'9,999')) AS QUANTITY FROM ' || TMP_TBL_NM || ' GROUP BY LOCATION_ID';
execute immediate query_statement using out query_output;
....
END
现在你有一个光标,获取内容,循环计数并做其他所有事情