这不是骗子,谢谢
我有一个存储过程,它引用了dba_tables,还有一些引用了,这意味着它们将必须成为变量而不是硬编码值。因此,我一直在努力将过程中的核心SQL及其变量更改为动态SQL。我提出了这个问题,以便为想要重复问题的任何人创建表的结构。最终结果将是服务器目录中的.csv文件(如果存在相关的数据库链接,该文件将具有一些值。)但是,下面的条目将生成一个文件,并且如果照原样复制,该过程将成功编译。我的版本中有一个数据库链接,该位可以用您的global_name替换,也可以将其删除,因为否则代码只会查看您本地的dba_tables。
我所需要做的就是使代码能够编译并成功运行,但要使用动态SQL,这样我便可以放入任何表变量中了……有人可以帮忙吗?
--drop any tables before creating the new ones:
drop table TABLE_TRACKER;
drop table LINK_AND_MAIL;
drop table MV_PRD_SEG_DATA;
drop table bob_table;
--CONNECT AS YOUR USER:
CREATE DIRECTORY ESTIMATES AS '<path_name>';
GRANT READ, WRITE ON DIRECTORY ESTIMATES TO <USER>;
create table TABLE_TRACKER
(
TABLENAME VARCHAR2(35),
CREATED_AT VARCHAR2(20),
PDU_TAB_TRUNCATED VARCHAR2(1),
TRUNCTIME VARCHAR2(40)
)
/
insert into TABLE_TRACKER (TABLENAME, CREATED_AT, PDU_TAB_TRUNCATED, TRUNCTIME)
values ('IN_PROGRESS_20190530052803', '30/05/2019 17:34:09', 'Y', '31/05/2019 16:24:40');
commit;
CREATE TABLE "LINK_AND_MAIL"
( "LINK_NAME" VARCHAR2(35),
"EMAIL_ADDRESS" VARCHAR2(30),
"MDATE" DATE
)
/
insert into LINK_AND_MAIL (LINK_NAME, EMAIL_ADDRESS, MDATE)
values ('DATABASE', 'bob@bob.com', to_date('31-05-2019 16:25:31', 'dd-mm-yyyy hh24:mi:ss'));
commit;
CREATE TABLE "BOB_TABLE"
( "TARGETSCHEMA" VARCHAR2(200),
"PRODUCTIONSCHEMA" VARCHAR2(200),
"PRODUCTIONDATABASE" VARCHAR2(200),
"TABLE_NAME" VARCHAR2(200),
"DRIVER_TABLE" VARCHAR2(200),
"MANDATORY_JOIN" VARCHAR2(200),
"ADDITIONAL_JOINS" VARCHAR2(200),
"TABLE_COMPRESSED" VARCHAR2(200))
/
insert into BOB_TABLE (TARGETSCHEMA, PRODUCTIONSCHEMA, PRODUCTIONDATABASE, TABLE_NAME, DRIVER_TABLE, MANDATORY_JOIN, ADDITIONAL_JOINS, TABLE_COMPRESSED)
values ('SIT_BOB', 'APIBOB', 'DB1', 'PARMS', null, null, null, 'Y');
commit;
CREATE TABLE "MV_PRD_SEG_DATA"
( "LINK" VARCHAR2(35),
"OWNER" VARCHAR2(30),
"SEGMENT_NAME" VARCHAR2(30),
"FLAG" VARCHAR2(30),
"SUM_BYTES" NUMBER)
/
insert into MV_PRD_SEG_DATA (LINK, OWNER, SEGMENT_NAME, FLAG, SUM_BYTES)
values ('DB1', 'BOB', 'GENRC_COLM', 'T', 5);
COMMIT;
/
--This is the start of the procedure, now you've created the tables
--it should compile okay
create or replace procedure ESTIMATE_PROC_BOB is
--variables
l_dblink varchar2(100) := '<WHATEEVS>'; -- put your global_name here to mimic db_link
file_handle UTL_FILE.file_type;
v_ts_name varchar2(30);
v_link_name varchar2(10);
v_csv_name varchar2(100);
TOTAL_ROW_COUNT NUMBER;
TOT_OBJECT_SIZE_MB NUMBER;
FULL_TABLE_COUNT NUMBER;
EST_ONE_ROW_MB NUMBER;
C_TOTAL_ROW_COUNT NUMBER;
SPACE_REQUIRED NUMBER;
v_total_driver_only NUMBER := 0;
--
begin
SELECT tablename into v_csv_name
FROM table_tracker
WHERE
CREATED_AT = (select MAX(CREATED_AT) from table_tracker);
select link_name into v_link_name from link_and_mail where mdate = (select max(mdate) from link_and_mail);
select distinct targetschema into v_ts_name from BOB_TABLE;
file_handle := utl_file.fopen('ESTIMATES_CSV', v_csv_name||'_EST_PROC.csv', 'w', 32767);
--
UTL_FILE.PUT_LINE(file_handle, ' ');
UTL_FILE.PUT_LINE(file_handle, 'The below report shows total row counts in PROD ');
UTL_FILE.PUT_LINE(file_handle, 'for entries with just a driver table only tables in the PDU document');
UTL_FILE.PUT_LINE(file_handle, 'If you see no entries here, you have no valid joins in your file.');
UTL_FILE.PUT_LINE(file_handle, ' ');
utl_file.put_line(file_handle, 'OWNER,TABLE_NAME,TOT_OBJECT_SIZE_MB,TOTAL_ROW_COUNT,FULL_TABLE_COUNT,EST_ONE_ROW_MB,SPACE_REQUIRED');
--main loop, this is the bit I need to be DYN SQL, can you help?
for rws in (
SELECT /*+ monitor parallel (4)*/ a.owner,
a.table_name,
b.driver_table,
b.mandatory_join,
sum(c.sum_bytes) TOT_OBJECT_SIZE_MB,
trunc(TOT_OBJECT_SIZE_MB / FULL_TABLE_COUNT,7) EST_ONE_ROW_MB,
(EST_ONE_ROW_MB * TOTAL_ROW_COUNT) SPACE_REQUIRED
FROM dba_tables a,
BOB_TABLE b,
MV_PRD_SEG_DATA c
WHERE a.table_name IN ( SELECT table_name
FROM BOB_TABLE
WHERE driver_table IS NOT NULL
AND additional_joins IS NULL
)
AND a.owner IN ( SELECT DISTINCT productionschema FROM BOB_TABLE c )
and a.table_name = b.table_name
and a.table_name = c.segment_name
group by a.owner,a.table_name,b.driver_table,b.mandatory_join
ORDER BY table_name
)
loop
execute immediate' select /*+monitor parallel (10)*/ count(*) from ' ||rws.owner||'.'||rws.table_name || '@' || l_dblink||' b '||','||
rws.driver_table || '@' || l_dblink||' a ' ||' where ' ||rws.mandatory_join --||' and '||rws.additional_joins
into TOTAL_ROW_COUNT;
execute immediate' select /*+monitor parallel (10)*/ count(*) from ' ||rws.owner||'.'||rws.table_name || '@' || l_dblink
into C_TOTAL_ROW_COUNT;
utl_file.put_line(file_handle,
rws.OWNER || ',' ||
rws.TABLE_NAME || ',' ||
rws.TOT_OBJECT_SIZE_MB || ',' ||
TOTAL_ROW_COUNT || ',' ||
C_TOTAL_ROW_COUNT || ',' || /* This is actually FULL_TABLE_COUNT*/
round(rws.TOT_OBJECT_SIZE_MB / C_TOTAL_ROW_COUNT,7)|| ',' ||
round(round(rws.TOT_OBJECT_SIZE_MB / C_TOTAL_ROW_COUNT,7) * round(TOTAL_ROW_COUNT,0),0)--SPACE_REQUIRED
);
v_total_driver_only := v_total_driver_only + round(rws.TOT_OBJECT_SIZE_MB / C_TOTAL_ROW_COUNT,7) * round(TOTAL_ROW_COUNT,0);
end loop;
UTL_FILE.PUT_LINE(file_handle, ' ');
utl_file.put_line(file_handle,
'Total Estimated Space Required '|| round(v_total_driver_only,0) ||' MB'
);
--
utl_file.fclose(file_handle);
end ESTIMATE_PROC_BOB;
/
答案 0 :(得分:0)
与不使用动态SQL相比,使用动态SQL的游标循环的语法要复杂得多,但是一旦您看到了一些示例,它就应该变得如此工作。来自PL/SQL User's Guide and Reference - 10g Release 1 (10.1) - OPEN-FOR-USING Statement的简单示例:
DECLARE
TYPE EmpCurTyp IS REF CURSOR; -- define weak REF CURSOR type
emp_cv EmpCurTyp; -- declare cursor variable
my_ename VARCHAR2(15);
my_sal NUMBER := 1000;
BEGIN
OPEN emp_cv FOR -- open cursor variable
'SELECT ename, sal FROM emp WHERE sal > :s' USING my_sal;
...
END;
这是另一个没有USING
子句的示例:Open cursor with a dynamic select statement
Google将向您展示更多示例。搜索“ Oracle开放游标动态SQL”。再举一个例子:Dynamic SQL with ref cursor