英文:
Find all the tables and column which has email in Oracle
问题
在我的Oracle数据库中,我有大约2K个表,想要找到包含电子邮件的表名和列名。
条件:列名可能不会直接包含email
,但列中的值应满足<something>@<anything>.<tail>
的格式。
从之前类似的帖子中寻求帮助,但没有任何输出。
DECLARE
l_cmd VARCHAR2 (2000);
l_found INTEGER;
BEGIN
FOR eachcol IN ( SELECT *
FROM all_tab_cols a
WHERE a.data_type = 'VARCHAR2'
AND owner = 'SEARCHSCHEMANAME'
ORDER BY table_name, column_name)
LOOP
l_cmd :=
'select count(*) c from '
|| eachcol.owner
|| '.'
|| eachcol.table_name
|| ' where '
|| LOWER (eachcol.column_name)
|| q'[ LIKE '%@%.%' AND ROWNUM = 1]';
EXECUTE IMMEDIATE l_cmd INTO l_found;
IF l_found > 0
THEN
DBMS_OUTPUT.put_line (
RPAD (eachcol.owner || '.' || eachcol.table_name || '.' || eachcol.column_name, 92)
|| ' 可能包含电子邮件地址'
);
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (l_cmd);
DBMS_OUTPUT.put_line (SQLERRM);
RAISE;
END;
输出:
英文:
In my Oracle database I have around 2K tables and want to find the table and column name which has email in it.
Condition: May not be column name would have email
tag inside it but the value contained by the column is <something>@<anything>.<tail>
.
Took help from previous similar thread, it is running without any output
DECLARE
l_cmd VARCHAR2 (2000);
l_found INTEGER;
BEGIN
FOR eachcol IN ( SELECT *
FROM all_tab_cols a
WHERE a.data_type = 'VARCHAR2'
AND owner = 'SEARCHSCHEMANAME'
ORDER BY table_name, column_name)
LOOP
l_cmd :=
'select count(*) c from '
|| eachcol.owner
|| '.'
|| eachcol.table_name
|| ' where '
|| LOWER (eachcol.column_name)
|| q'[ LIKE '%@%.%' AND ROWNUM = 1]';
EXECUTE IMMEDIATE l_cmd INTO l_found;
IF l_found > 0
THEN
DBMS_OUTPUT.put_line (
RPAD (eachcol.owner || '.' || eachcol.table_name || '.' || eachcol.column_name, 92)
|| ' may contain email addresses'
);
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (l_cmd);
DBMS_OUTPUT.put_line (SQLERRM);
RAISE;
END;
答案1
得分: 1
如果它没有产生任何输出,则:
- 没有包含此类数据的列
- 也没有错误
- 您可能忘记启用 serveroutput
我稍微修改了您的代码,以便它:
- 从
user_tab_cols
选择数据(没有尝试all_tab_cols
) - 包含内部的
BEGIN-EXCEPTION-END
块,处理可能的异常,但允许循环继续执行(为什么我要在错误时停止执行?不,我希望它继续执行)
在我的模式中它基本上有效,所以我认为它在您的模式中也应该有效(除非您遇到我在开头提到的三种可能性之一)。
SQL> SET LINESIZE 200
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 l_cmd VARCHAR2 (2000);
3 l_found INTEGER;
4 BEGIN
5 FOR eachcol IN ( SELECT *
6 FROM user_tab_cols a
7 WHERE a.data_type = 'VARCHAR2'
8 -- AND owner = 'SEARCHSCHEMANAME'
9 ORDER BY table_name, column_name)
10 LOOP
11 BEGIN
12 l_cmd :=
13 'select count(*) c from '
14 -- || eachcol.owner
15 -- || '.'
16 || eachcol.table_name
17 || ' where '
18 || '"' || eachcol.column_name || '"'
19 || q'[ LIKE '%@%.%' AND ROWNUM = 1]';
20
21 EXECUTE IMMEDIATE l_cmd
22 INTO l_found;
23
24 IF l_found > 0
25 THEN
26 DBMS_OUTPUT.put_line (
27 RPAD ( --eachcol.owner || '.' ||
28 eachcol.table_name || '.' || eachcol.column_name, 92)
29 || ' may contain email addresses');
30 END IF;
31 EXCEPTION
32 WHEN OTHERS
33 THEN
34 DBMS_OUTPUT.put_line (l_cmd);
35 DBMS_OUTPUT.put_line (SQLERRM);
36 --RAISE;
37 END;
38 END LOOP;
39 END;
40 /
Result:
LOGS.LOG1 may contain email addresses
OBR1_IN.E_MAIL may contain email addresses
OBR2_IN.E_MAIL may contain email addresses
...
RPRT_OP.E_MAIL may contain email addresses
RPRT_PO.E_MAIL may contain email addresses
PL/SQL procedure successfully completed.
SQL>
英文:
If it doesn't produce any output, then:
- there are no columns that contain such data
- there are no errors either
- you forgot to enable serveroutput
I slightly modified your code so that it
- selects data from
user_tab_cols
(didn't feel like tryingall_tab_cols
) - contains inner
BEGIN-EXCEPTION-END
block which handles possible exceptions, but lets loop to continue (why would I want to stop execution on error? Nope, I want it to go on)
It kind of works in my schema, so I presume that it should work in yours too (unless you hit one or more of 3 possibilities I mentioned at the beginning).
SQL> SET LINESIZE 200
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 l_cmd VARCHAR2 (2000);
3 l_found INTEGER;
4 BEGIN
5 FOR eachcol IN ( SELECT *
6 FROM user_tab_cols a
7 WHERE a.data_type = 'VARCHAR2'
8 -- AND owner = 'SEARCHSCHEMANAME'
9 ORDER BY table_name, column_name)
10 LOOP
11 BEGIN
12 l_cmd :=
13 'select count(*) c from '
14 -- || eachcol.owner
15 -- || '.'
16 || eachcol.table_name
17 || ' where '
18 || '"' || eachcol.column_name || '"'
19 || q'[ LIKE '%@%.%' AND ROWNUM = 1]';
20
21 EXECUTE IMMEDIATE l_cmd
22 INTO l_found;
23
24 IF l_found > 0
25 THEN
26 DBMS_OUTPUT.put_line (
27 RPAD ( --eachcol.owner || '.' ||
28 eachcol.table_name || '.' || eachcol.column_name, 92)
29 || ' may contain email addresses');
30 END IF;
31 EXCEPTION
32 WHEN OTHERS
33 THEN
34 DBMS_OUTPUT.put_line (l_cmd);
35 DBMS_OUTPUT.put_line (SQLERRM);
36 --RAISE;
37 END;
38 END LOOP;
39 END;
40 /
Result:
LOGS.LOG1 may contain email addresses
OBR1_IN.E_MAIL may contain email addresses
OBR2_IN.E_MAIL may contain email addresses
...
RPRT_OP.E_MAIL may contain email addresses
RPRT_PO.E_MAIL may contain email addresses
PL/SQL procedure successfully completed.
SQL>
答案2
得分: 0
- 使用带引号的标识符来确保标识符具有正确的大小写(而不是使用
LOWER
和未带引号的标识符,Oracle会隐式转换回大写,似乎没有意义); - 您还可以检查其他数据类型,包括
CHAR
、NVARCHAR2
和NCHAR
; 以及 - 确保启用
DBMS_OUTPUT
:
如下所示:
DECLARE
l_cmd VARCHAR2 (2000);
l_found INTEGER;
BEGIN
DBMS_OUTPUT.ENABLE();
FOR eachcol IN (
SELECT owner,
table_name,
column_name
FROM all_tab_cols
WHERE data_type IN ('VARCHAR2', 'CHAR', 'NVARCHAR2', 'NCHAR')
AND owner = 'SEARCHSCHEMANAME'
ORDER BY
table_name,
column_name
)
LOOP
l_cmd := 'SELECT COUNT(*)'
|| ' FROM "' || eachcol.owner || '"."' || eachcol.table_name || '"'
|| ' WHERE "' || eachcol.column_name || '" LIKE ''%@%'''
|| ' AND ROWNUM = 1';
EXECUTE IMMEDIATE l_cmd INTO l_found;
IF l_found > 0 THEN
DBMS_OUTPUT.PUT_LINE(
RPAD (eachcol.owner || '.' || eachcol.table_name || '.' || eachcol.column_name, 92)
|| ' 可能包含电子邮件地址'
);
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(l_cmd);
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
END;
/
英文:
- Use quoted identifiers to ensure that your identifiers have the correct case (rather than using
LOWER
and unquoted identifiers which Oracle will implicitly convert back to upper-case, which seems pointless); - You can also check other data-types including
CHAR
,NVARCHAR2
andNCHAR
; and - Ensure that
DBMS_OUTPUT
is enabled:
Like this:
DECLARE
l_cmd VARCHAR2 (2000);
l_found INTEGER;
BEGIN
DBMS_OUTPUT.ENABLE();
FOR eachcol IN (
SELECT owner,
table_name,
column_name
FROM all_tab_cols
WHERE data_type IN ('VARCHAR2', 'CHAR', 'NVARCHAR2', 'NCHAR')
AND owner = 'SEARCHSCHEMANAME'
ORDER BY
table_name,
column_name
)
LOOP
l_cmd := 'SELECT COUNT(*)'
|| ' FROM "' || eachcol.owner || '"."' || eachcol.table_name || '"'
|| ' WHERE "' || eachcol.column_name || '" LIKE ''%@%.%'''
|| ' AND ROWNUM = 1';
EXECUTE IMMEDIATE l_cmd INTO l_found;
IF l_found > 0 THEN
DBMS_OUTPUT.PUT_LINE(
RPAD (eachcol.owner || '.' || eachcol.table_name || '.' || eachcol.column_name, 92)
|| ' may contain email addresses'
);
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(l_cmd);
DBMS_OUTPUT.PUT_LINE(SQLERRM);
RAISE;
END;
/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论