美好的一天,
试图绕过这个并设法让它在某种程度上发挥作用 - 但仍然有点挣扎。
我希望在此示例的两列中找到两个值: VARCHAR和DATE 约翰1984-01-01
让我们说这是约翰的出生日期。
我希望能够找到具有DATE值的值JOHN,例如2000表,并使列名称不完全复杂化。数据类型是。
以下选择具有我需要的两个列名的所有表。
SELECT A.TABLE_NAME, A.COLUMN_NAME, B.COLUMN_NAME
FROM all_tab_columns A
JOIN all_tab_columns B
ON A.TABLE_NAME = B.TABLE_NAME
AND B.DATA_TYPE = 'DATE'
AND A.COLUMN_NAME IN ('NAME', 'FULLNAME')
所以,现在我得到了我需要的数据类型为DATE的表,其中列名为NAME和FULLNAME。
所以2000年的表格中我有300个符合我的标准。我想搜索找到约翰的表格,其日期为1984-01-01,其中约翰可以是FULLNAME或NAME,1984-01-01可以是任何列名,即。 DTTM,BDAY,DATEFLD,DTFIELD等。
我希望TABLE_NAME将这两个值存在于同一行中,而不是其他任何内容。
我看过这些类型的例子:
Search All Fields In All Tables For A Specific Value (Oracle)
但不断遇到问题。我错过了什么?
DECLARE
match_count INTEGER;
v_search_string VARCHAR2 (11) := 'JOHN';
BEGIN
FOR t
IN (SELECT A.owner, A.table_name, A.column_name
FROM all_tab_columns A
JOIN all_tab_columns B
ON A.TABLE_NAME = B.TABLE_NAME
AND A.COLUMN_NAME IN ('NAME', 'FULLNAME')
AND B.DATA_TYPE = 'DATE'
AND A.TABLE_NAME LIKE 'DATA%')
LOOP
BEGIN
EXECUTE IMMEDIATE
'SELECT * FROM '
|| t.owner
|| '.'
|| t.table_name
|| ' WHERE '
|| t.column_name
|| ' = :1 '
INTO match_count
USING v_search_string;
IF match_count > 0
THEN
DBMS_OUTPUT.put_line (
t.table_name
);
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
'Error encountered trying to read '
|| t.column_name
|| ' from '
|| t.owner
|| '.'
|| t.table_name);
END;
END LOOP;
END;
/
答案 0 :(得分:1)
我对您的代码做了一些小修改:
before_action :authenticate_user!
答案 1 :(得分:0)
您可以尝试做的是使用all_tab_columns
中的select来构造where子句,并在动态where子句中查询相应的表。
SET serveroutput ON
DECLARE
v_count INTEGER;
BEGIN
FOR r IN (SELECT a.table_name,
' WHERE '
|| LISTAGG(CASE data_type
WHEN 'DATE' THEN column_name
|| ' = DATE '
|| '''1984-01-01'''
ELSE column_name
|| ' = '
|| '''JOHN'''
END, ' or ')
WITHIN GROUP( ORDER BY column_name ) AS where_clause
FROM user_tab_columns a
WHERE column_name IN ( 'NAME', 'FULLNAME' )
OR ( data_type = 'DATE'
AND column_name IN ( 'DTTM', 'BDAY', 'DATEFLD',
'DTFIELD'
) )
GROUP BY table_name) LOOP
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM '|| r.table_name||
r.where_clause
INTO
v_count;
IF v_count > 0 THEN
dbms_output.Put_line(r.table_name);
END IF;
END LOOP;
END;
/
请注意,我给你的是一个给你一些想法的例子,你可以构建它并调整隐式游标循环的查询(在r in ()
内)以使用AND/OR/JOIN
来满足你的需求条件INTERSECT
运算符等但是你想要。我这样做是为了从我的角度测试它。
编辑:另一种选择是强制方法,即使用动态where子句搜索数据库中的所有表,如果找不到where子句中的列,则忽略该异常一张桌子。
SET serveroutput ON
DECLARE
v_count NUMBER;
v_where_clause VARCHAR2(400) :=
' WHERE DTTM = DATE ''1984-01-01'' AND FULLNAME = ''JOHN''';
BEGIN
FOR r IN (SELECT owner,
table_name
FROM all_tables) LOOP
BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM '|| r.owner|| '.'||
r.table_name
||
v_where_clause INTO v_count;
IF v_count > 0 THEN
dbms_output.put_line(r.owner||'.'||r.table_name);
END IF;
EXCEPTION
WHEN OTHERS THEN
NULL; --It is ok in this case as you know why it fails.
END;
END LOOP;
END;
/