如何搜索所有表(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é的功能与进展报告功能。 它报告三种方式的进展:
- 通过RAISE NOTICE;
- 通过将提供的{progress_seq}序列的值从 {要搜索的总列数}减小到0;
- 通过将进度和找到的表一起写入位于c:\ windows \ temp \ {progress_seq} .txt中的文本文件 。
_
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