先创建一张表,该表中包含该库下的所有表,以及时间更新字段等。
此表的作用是为了遍历表及时间字段,也为了标识表含义等。
之后创建另一张表 ,该表中的字段分别为 表名、字段名、字段数据为空量、字段中数据总量、字段为空率及最小更新时间最大更新时间。
接下来就是存储过程了。
CREATE OR REPLACE PROCEDURE "TABLEFIELD"
AS
V_SQL VARCHAR2(2000);
V_FIELD VARCHAR2(200);
V_NUM INT:='0';
V_T_NUM INT:='0';
V_TABLENAME VARCHAR2(200);
V_COUNT INT:='0';
V_T_COUNT INT:='6';
V_BUSTIMEFIELD VARCHAR2(200);
--将表名及时间字段从表中取出 插入到游标中
CURSOR TAB_CURSOR IS
SELECT TABLENAME,BUSTIMEFILED FROM DIC_TABLE ORDER BY TABLENAME;
--将表名及所有的字段从系统表中取出插入到游标中
CURSOR EMP_CURSOR(V_TABLENAME ALL_TAB_COLUMNS.TABLE_NAME%TYPE) IS
SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME=V_TABLENAME;
-- 定义一个表示表中一行记录的变量
TAB TAB_CURSOR%ROWTYPE;
EMP EMP_CURSOR%ROWTYPE;
BEGIN
--先删除表中的数据
DELETE FROM DIC_TABLEINFO;
--打开游标开始循环 因为是两个游标,一个是表名的游标,另一个是字段的游标 所以要嵌套游标进行循环。
OPEN TAB_CURSOR;
LOOP
FETCH TAB_CURSOR INTO TAB ;
EXIT WHEN TAB_CURSOR%NOTFOUND;
BEGIN
OPEN EMP_CURSOR(TAB.TABLENAME);
LOOP
FETCH EMP_CURSOR INTO EMP;
EXIT WHEN EMP_CURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(EMP.COLUMN_NAME);
--插入字段名称
V_SQL :='INSERT INTO DIC_TABLEINFO(CLONAME) VALUES('''||EMP.COLUMN_NAME||''')';
EXECUTE IMMEDIATE V_SQL;
COMMIT;
--更新字段中为NULL的数据量
V_SQL :='UPDATE DIC_TABLEINFO SET COLCOUNT=
( SELECT COUNT(*) AS NUM FROM '||TAB.TABLENAME||' WHERE '||EMP.COLUMN_NAME||' IS NULL)
WHERE CLONAME='''||EMP.COLUMN_NAME||''' AND TABLE_NAME IS NULL';
EXECUTE IMMEDIATE V_SQL;
COMMIT;
--更新表中字段的总量
--DBMS_OUTPUT.PUT_LINE(V_SQL);
V_SQL :='UPDATE DIC_TABLEINFO SET TOTALCOUNT=(SELECT COUNT(*) FROM '||TAB.TABLENAME||') WHERE TABLE_NAME IS NULL';
EXECUTE IMMEDIATE V_SQL;
COMMIT;
--更新为NULL百分比(保留四位小数),当数据总量为零时,直接设置百分比为0
UPDATE DIC_TABLEINFO SET PERSENT=CASE
WHEN CAST(TOTALCOUNT AS FLOAT)=0 THEN 0
ELSE (ROUND(CAST(COLCOUNT AS FLOAT)/CAST(TOTALCOUNT AS FLOAT),2))
END;
END LOOP;
CLOSE EMP_CURSOR;
END;
--更新数据中的表名
V_SQL :='UPDATE DIC_TABLEINFO SET TABLE_NAME ='''||TAB.TABLENAME||''' WHERE TABLE_NAME IS NULL';
EXECUTE IMMEDIATE V_SQL;
COMMIT;
--更新最大业务时间
V_SQL :='UPDATE DIC_TABLEINFO SET MAXDATE=(SELECT MAX('||TAB.BUSTIMEFILED||') FROM '||TAB.TABLENAME||') WHERE TABLE_NAME='''||TAB.TABLENAME||'''';
EXECUTE IMMEDIATE V_SQL;
COMMIT;
--更新最小业务时间
V_SQL :='UPDATE DIC_TABLEINFO SET MINDATE=(SELECT MIN('||TAB.BUSTIMEFILED||') FROM '||TAB.TABLENAME||') WHERE TABLE_NAME='''||TAB.TABLENAME||'''';
EXECUTE IMMEDIATE V_SQL;
COMMIT;
END LOOP;
CLOSE TAB_CURSOR;
END;
到此为止,在外面调用以下即可获取到表中想要的字段了。