有類似的問題here,但它適用於Oracle。我對PostgreSQL有同樣的問題。如何搜索所有表(PostgreSQL)中的特定值?
簡而言之,是否有可能在PostgreSQL中搜索每個表的每個字段以獲取特定值?
謝謝。
有類似的問題here,但它適用於Oracle。我對PostgreSQL有同樣的問題。如何搜索所有表(PostgreSQL)中的特定值?
簡而言之,是否有可能在PostgreSQL中搜索每個表的每個字段以獲取特定值?
謝謝。
如何轉儲數據庫中的內容,然後使用grep
?
$ pg_dump --data-only --inserts -U postgres your-db-name > a.tmp
$ grep United a.tmp
INSERT INTO countries VALUES ('US', 'United States');
INSERT INTO countries VALUES ('GB', 'United Kingdom');
相同的實用程序pg_dump可以在輸出中包含列名。只需將--inserts
更改爲--column-inserts
即可。這樣您也可以搜索特定的列名稱。但是如果我在尋找列名,我可能會轉儲模式而不是數據。
$ pg_dump --data-only --column-inserts -U postgres your-db-name > a.tmp
$ grep country_code a.tmp
INSERT INTO countries (iso_country_code, iso_country_name) VALUES ('US', 'United States');
INSERT INTO countries (iso_country_code, iso_country_name) VALUES ('GB', 'United Kingdom');
+1免費且簡單。如果你想要結構pg_dump也可以。此外,如果grep不是你的東西,你可以使用你想要的文件內容搜索工具在被甩出的結構和/或數據上。 – Kuberchaun 2011-03-18 12:17:12
如果您想要grep文本數據(通常使用最新版本的postgres編碼),您可能需要在轉儲數據庫(或其副本)之前對您的數據庫進行ALTER DATABASE SET bytea_output ='escape';'。 (我沒有看到一個方法來指定這只是一個'pg_dump'命令。) – phils 2015-08-10 03:01:10
你能詳細解釋..?如何在所有表中搜索字符串'ABC'? – 2017-01-28 06:47:57
我知道它可以做到這一點的唯一工具是:SQL工作臺/ J:http://www.sql-workbench.net/
一個Java/JDBC基礎工具,它提供了一個特殊(專有)SQL「命令」,通過全搜索(或只是選擇)數據庫中的表:
http://www.sql-workbench.net/manual/wb-commands.html#command-search-data
http://www.sql-workbench.net/wbgrepdata_png.html
你知道是否可以搜索特定列的名稱而不是特定的數據?謝謝。 – 2011-03-18 10:18:58
該工具有另一個命令來搜索所有表的源代碼:http://www.sql-workbench.net/manual/wb-commands.html#command-search-source – 2011-03-18 10:37:10
這是一個pl/pgsql函數,用於查找任何列包含特定值的記錄。 它以文本格式搜索的值作爲參數,要搜索的表名稱數組(缺省爲所有表)和模式名稱數組(缺省爲所有模式名稱)。
它返回模式,表的名稱,名稱欄和僞列ctid
的表結構(表中的行的非持久的物理位置,見System Columns)
CREATE OR REPLACE FUNCTION search_columns(
needle text,
haystack_tables name[] default '{}',
haystack_schema name[] default '{}'
)
RETURNS table(schemaname text, tablename text, columnname text, rowctid text)
AS $$
begin
FOR schemaname,tablename,columnname IN
SELECT c.table_schema,c.table_name,c.column_name
FROM information_schema.columns c
JOIN information_schema.tables t ON
(t.table_name=c.table_name AND t.table_schema=c.table_schema)
WHERE (c.table_name=ANY(haystack_tables) OR haystack_tables='{}')
AND (c.table_schema=ANY(haystack_schema) OR haystack_schema='{}')
AND t.table_type='BASE TABLE'
LOOP
EXECUTE format('SELECT ctid FROM %I.%I WHERE cast(%I as text)=%L',
schemaname,
tablename,
columnname,
needle
) INTO rowctid;
IF rowctid is not null THEN
RETURN NEXT;
END IF;
END LOOP;
END;
$$ language plpgsql;
EDIT :此代碼適用於PG 9.1或更新版本。在測試數據庫使用的
例子:
公共架構中的所有表中搜索:
select * from search_columns('foobar'); schemaname | tablename | columnname | rowctid ------------+-----------+------------+--------- public | s3 | usename | (0,11) public | s2 | relname | (7,29) public | w | body | (0,2) (3 rows)
搜索特定表:
select * from search_columns('foobar','{w}'); schemaname | tablename | columnname | rowctid ------------+-----------+------------+--------- public | w | body | (0,2) (1 row)
表中的一個子集搜索從一個選擇中獲得:
select * from search_columns('foobar', array(select table_name::name from information_schema.tables where table_name like 's%'), array['public']); schemaname | tablename | columnname | rowctid ------------+-----------+------------+--------- public | s2 | relname | (7,29) public | s3 | usename | (0,11) (2 rows)
得到一個結果行與相應的基臺和和CTID:
select * from public.w where ctid='(0,2)'; title | body | tsv -------+--------+--------------------- toto | foobar | 'foobar':2 'toto':1
爲了代替再次測試一個正則表達式的嚴格平等,如grep,這樣:
SELECT ctid FROM %I.%I WHERE cast(%I as text)=%L
可以改變爲:
SELECT ctid FROM %I.%I WHERE cast(%I as text) ~ %L
這裏是@DanielVérité的功能與進展報告功能。 它報告三種方式的進展:
_
CREATE OR REPLACE FUNCTION search_columns(
needle text,
haystack_tables name[] default '{}',
haystack_schema name[] default '{public}',
progress_seq text default NULL
)
RETURNS table(schemaname text, tablename text, columnname text, rowctid text)
AS $$
DECLARE
currenttable text;
columnscount integer;
foundintables text[];
foundincolumns text[];
begin
currenttable='';
columnscount = (SELECT count(1)
FROM information_schema.columns c
JOIN information_schema.tables t ON
(t.table_name=c.table_name AND t.table_schema=c.table_schema)
WHERE (c.table_name=ANY(haystack_tables) OR haystack_tables='{}')
AND c.table_schema=ANY(haystack_schema)
AND t.table_type='BASE TABLE')::integer;
PERFORM setval(progress_seq::regclass, columnscount);
FOR schemaname,tablename,columnname IN
SELECT c.table_schema,c.table_name,c.column_name
FROM information_schema.columns c
JOIN information_schema.tables t ON
(t.table_name=c.table_name AND t.table_schema=c.table_schema)
WHERE (c.table_name=ANY(haystack_tables) OR haystack_tables='{}')
AND c.table_schema=ANY(haystack_schema)
AND t.table_type='BASE TABLE'
LOOP
EXECUTE format('SELECT ctid FROM %I.%I WHERE cast(%I as text)=%L',
schemaname,
tablename,
columnname,
needle
) INTO rowctid;
IF rowctid is not null THEN
RETURN NEXT;
foundintables = foundintables || tablename;
foundincolumns = foundincolumns || columnname;
RAISE NOTICE 'FOUND! %, %, %, %', schemaname,tablename,columnname, rowctid;
END IF;
IF (progress_seq IS NOT NULL) THEN
PERFORM nextval(progress_seq::regclass);
END IF;
IF(currenttable<>tablename) THEN
currenttable=tablename;
IF (progress_seq IS NOT NULL) THEN
RAISE NOTICE 'Columns left to look in: %; looking in table: %', currval(progress_seq::regclass), tablename;
EXECUTE 'COPY (SELECT unnest(string_to_array(''Current table (column ' || columnscount-currval(progress_seq::regclass) || ' of ' || columnscount || '): ' || tablename || '\n\nFound in tables/columns:\n' || COALESCE(
(SELECT string_agg(c1 || '/' || c2, '\n') FROM (SELECT unnest(foundintables) AS c1,unnest(foundincolumns) AS c2) AS t1)
, '') || ''',''\n''))) TO ''c:\WINDOWS\temp\' || progress_seq || '.txt''';
END IF;
END IF;
END LOOP;
END;
$$ language plpgsql;
如果有人認爲這可能會有幫助。這裏是@DanielVérité的函數,另一個參數接受可用於搜索的列的名稱。這樣可以減少處理時間。至少在我的測試中,它減少了很多。
CREATE OR REPLACE FUNCTION search_columns(
needle text,
haystack_columns name[] default '{}',
haystack_tables name[] default '{}',
haystack_schema name[] default '{public}'
)
RETURNS table(schemaname text, tablename text, columnname text, rowctid text)
AS $$
begin
FOR schemaname,tablename,columnname IN
SELECT c.table_schema,c.table_name,c.column_name
FROM information_schema.columns c
JOIN information_schema.tables t ON
(t.table_name=c.table_name AND t.table_schema=c.table_schema)
WHERE (c.table_name=ANY(haystack_tables) OR haystack_tables='{}')
AND c.table_schema=ANY(haystack_schema)
AND (c.column_name=ANY(haystack_columns) OR haystack_columns='{}')
AND t.table_type='BASE TABLE'
LOOP
EXECUTE format('SELECT ctid FROM %I.%I WHERE cast(%I as text)=%L',
schemaname,
tablename,
columnname,
needle
) INTO rowctid;
IF rowctid is not null THEN
RETURN NEXT;
END IF;
END LOOP;
END;
$$ language plpgsql;
波紋管是上面創建的search_function的使用示例。
SELECT * FROM search_columns('86192700'
, array(SELECT DISTINCT a.column_name::name FROM information_schema.columns AS a
INNER JOIN information_schema.tables as b ON (b.table_catalog = a.table_catalog AND b.table_schema = a.table_schema AND b.table_name = a.table_name)
WHERE
a.column_name iLIKE '%cep%'
AND b.table_type = 'BASE TABLE'
AND b.table_schema = 'public'
)
, array(SELECT b.table_name::name FROM information_schema.columns AS a
INNER JOIN information_schema.tables as b ON (b.table_catalog = a.table_catalog AND b.table_schema = a.table_schema AND b.table_name = a.table_name)
WHERE
a.column_name iLIKE '%cep%'
AND b.table_type = 'BASE TABLE'
AND b.table_schema = 'public')
);
不存儲新過程,您可以使用代碼塊並執行以獲取出現的表。您可以按架構,表或列名稱篩選結果。
DO $$
DECLARE
value int := 0;
sql text := 'The constructed select statement';
rec1 record;
rec2 record;
BEGIN
DROP TABLE IF EXISTS _x;
CREATE TEMPORARY TABLE _x (
schema_name text,
table_name text,
column_name text,
found text
);
FOR rec1 IN
SELECT table_schema, table_name, column_name
FROM information_schema.columns
WHERE table_name <> '_x'
AND UPPER(column_name) LIKE UPPER('%%')
AND table_schema <> 'pg_catalog'
AND table_schema <> 'information_schema'
AND data_type IN ('character varying', 'text', 'character', 'char', 'varchar')
LOOP
sql := concat('SELECT ', rec1."column_name", ' AS "found" FROM ',rec1."table_schema" , '.',rec1."table_name" , ' WHERE UPPER(',rec1."column_name" , ') LIKE UPPER(''','%my_substring_to_find_goes_here%' , ''')');
RAISE NOTICE '%', sql;
BEGIN
FOR rec2 IN EXECUTE sql LOOP
RAISE NOTICE '%', sql;
INSERT INTO _x VALUES (rec1."table_schema", rec1."table_name", rec1."column_name", rec2."found");
END LOOP;
EXCEPTION WHEN OTHERS THEN
END;
END LOOP;
END; $$;
SELECT * FROM _x;
你在哪裏指定搜索字符串?或者,這只是傾銷整個數據庫,一桌一桌? – jimtut 2017-08-16 17:24:30
我沒有爲字符串創建參數。您可以對其進行硬編碼並直接作爲塊運行,或者從中創建存儲過程。無論如何,你要搜索的字符串在兩個百分號之間:WHERE UPPER(',rec1。「column_name」,')LIKE UPPER(''','%%',''') – profimedica 2017-08-16 22:13:25
您是否正在尋找工具或鏈接問題中顯示的過程的實現? – 2011-03-18 09:49:11
不,只是在所有字段/表格中查找特定值的最簡單方法。 – 2011-03-18 09:51:29
所以你不想使用外部工具? – 2011-03-18 09:56:52