답변:
FrustratedWithFormsDesigner가 정확하면 PL / pgSQL이이를 수행 할 수 있습니다. 스크립트는 다음과 같습니다.
CREATE OR REPLACE FUNCTION truncate_tables(username IN VARCHAR) RETURNS void AS $$
DECLARE
statements CURSOR FOR
SELECT tablename FROM pg_tables
WHERE tableowner = username AND schemaname = 'public';
BEGIN
FOR stmt IN statements LOOP
EXECUTE 'TRUNCATE TABLE ' || quote_ident(stmt.tablename) || ' CASCADE;';
END LOOP;
END;
$$ LANGUAGE plpgsql;
그러면 저장된 함수 (한 번만 수행하면 됨)가 생성되어 나중에 다음과 같이 사용할 수 있습니다.
SELECT truncate_tables('MYUSER');
DECLARE r RECORD;
그때 for 루프 : FOR r IN SELECT tablename FROM pg_tables LOOP
plpgsql에서는 명시 적 커서가 거의 필요하지 않습니다. 루프 의 더 간단하고 빠른 암시 적 커서 를 사용하십시오 FOR
.
참고 : 테이블 이름은 데이터베이스마다 고유하지 않으므로 테이블 이름을 스키마로 한정해야합니다. 또한 함수를 기본 스키마 'public'으로 제한합니다. 여러분의 필요에 적응하지만, 시스템 스키마를 제외해야 pg_*
하고 information_schema
.
이 기능에 매우주의 하십시오 . 그들은 당신의 데이터베이스를 핵화합니다. 어린이 안전 장치를 추가했습니다. 폭탄을 프라이밍하기 위해 RAISE NOTICE
줄을 주석 처리하고 주석 EXECUTE
을 제거하십시오 ...
CREATE OR REPLACE FUNCTION f_truncate_tables(_username text)
RETURNS void AS
$func$
DECLARE
_tbl text;
_sch text;
BEGIN
FOR _sch, _tbl IN
SELECT schemaname, tablename
FROM pg_tables
WHERE tableowner = _username
AND schemaname = 'public'
LOOP
RAISE NOTICE '%',
-- EXECUTE -- dangerous, test before you execute!
format('TRUNCATE TABLE %I.%I CASCADE', _sch, _tbl);
END LOOP;
END
$func$ LANGUAGE plpgsql;
format()
Postgres 9.1 이상이 필요합니다. 이전 버전에서는 다음과 같이 쿼리 문자열을 연결합니다.
'TRUNCATE TABLE ' || quote_ident(_sch) || '.' || quote_ident(_tbl) || ' CASCADE';
TRUNCATE
한 번에 여러 테이블을 사용할 수 있으므로 커서 나 루프가 전혀 필요하지 않습니다.
모든 테이블 이름을 집계하고 단일 명령문을 실행하십시오. 더 간단하고 빠르게 :
CREATE OR REPLACE FUNCTION f_truncate_tables(_username text)
RETURNS void AS
$func$
BEGIN
RAISE NOTICE '%',
-- EXECUTE -- dangerous, test before you execute!
(SELECT 'TRUNCATE TABLE '
|| string_agg(format('%I.%I', schemaname, tablename), ', ')
|| ' CASCADE'
FROM pg_tables
WHERE tableowner = _username
AND schemaname = 'public'
);
END
$func$ LANGUAGE plpgsql;
요구:
SELECT truncate_tables('postgres');
기능이 필요하지 않습니다. Postgres 9.0 이상에서는 DO
명령문 에서 동적 명령을 실행할 수 있습니다 . 그리고 Postgres 9.5 이상에서는 구문이 더 간단 할 수 있습니다.
DO
$func$
BEGIN
RAISE NOTICE '%',
-- EXECUTE
(SELECT 'TRUNCATE TABLE ' || string_agg(oid::regclass::text, ', ') || ' CASCADE'
FROM pg_class
WHERE relkind = 'r' -- only tables
AND relnamespace = 'public'::regnamespace
);
END
$func$;
사이의 차이에 대해 pg_class
, pg_tables
그리고 information_schema.tables
:
정보 regclass
및 인용 테이블 이름 :
바닐라 구조와 모든 빈 테이블을 사용 하여 "템플릿"데이터베이스 (이름을 지정 my_template
)를 작성하십시오. 그런 다음 DROP
/CREATE DATABASE
주기를 수행하십시오.
DROP DATABASE mydb;
CREATE DATABASE mydb TEMPLATE my_template;
이다 매우 빠른 , 파일 수준에서 포스트 그레스 복사 전체 구조 때문이다. 동시성 문제 또는 기타 오버 헤드가 느려지지 않습니다.
동시 연결로 인해 DB가 삭제되지 않으면 다음을 고려하십시오.
DROP DATABASE mydb
확실히 제외하십시오 ). 스키마 와 데이터베이스 를 혼동 하고 있습니까?
DO
명령 (다른 SQL 문 같은) 현재 데이터베이스에서 실행되는 독점적으로 . Postgres는 동일한 트랜잭션에서 다른 데이터베이스에 액세스 할 수있는 방법이 없습니다. 그렇게하려면 dblink 또는 FDW를 사용해야합니다. 그러나 않습니다 추가하지 않는 - 현재 데이터베이스의 모든 스키마에 영향을주는 WHERE t.schemaname = 'public'
이 특별한 경우에 하나의 특정 스키마에 대한 효과를 제한 할 수 있습니다.
이 작업을 수행 해야하는 경우 단순히 현재 db의 스키마 sql을 만든 다음 삭제 및 db를 생성 한 다음 schema sql로 db를로드합니다.
다음은 관련 단계입니다.
1) 데이터베이스의 스키마 덤프 생성 ( --schema-only
)
pg_dump mydb -s > schema.sql
2) 데이터베이스 삭제
drop database mydb;
3) 데이터베이스 생성
create database mydb;
4) 가져 오기 스키마
psql mydb < schema.sql
동적 SQL을 사용하여 각 명령문을 차례로 실행할 수 있습니까? 이 작업을 수행하려면 PL / pgSQL 스크립트를 작성해야합니다.
http://www.postgresql.org/docs/8.3/static/plpgsql-statements.html (섹션 38.5.4. 동적 명령 실행)
bash를 사용 하여이 작업을 수행 할 수도 있습니다.
#!/bin/bash
PGPASSWORD='' psql -h 127.0.0.1 -Upostgres sng --tuples-only --command "SELECT 'TRUNCATE TABLE ' || schemaname || '.' || tablename || ';' FROM pg_tables WHERE schemaname in ('cms_test', 'ids_test', 'logs_test', 'sps_test');" |
tr "\\n" " " |
xargs -I{} psql -h 127.0.0.1 -Upostgres sng --command "{}"
스키마와 일치하도록 스키마 이름, 비밀번호 및 사용자 이름을 조정해야합니다.
청소 AUTO_INCREMENT
버전 :
CREATE OR REPLACE FUNCTION truncate_tables(username IN VARCHAR) RETURNS void AS $$
DECLARE
statements CURSOR FOR
SELECT tablename FROM pg_tables
WHERE tableowner = username AND schemaname = 'public';
BEGIN
FOR stmt IN statements LOOP
EXECUTE 'TRUNCATE TABLE ' || quote_ident(stmt.tablename) || ' CASCADE;';
IF EXISTS (
SELECT column_name
FROM information_schema.columns
WHERE table_name=quote_ident(stmt.tablename) and column_name='id'
) THEN
EXECUTE 'ALTER SEQUENCE ' || quote_ident(stmt.tablename) || '_id_seq RESTART WITH 1';
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql;
당신이 사용할 수있는 경우 psql 프로그램을 당신이 사용할 수있는 \gexec
쿼리 출력을 실행하기 위해 메타 명령을;
SELECT
format('TRUNCATE TABLE %I.%I', ns.nspname, c.relname)
FROM pg_namespace ns
JOIN pg_class c ON ns.oid = c.relnamespace
JOIN pg_roles r ON r.oid = c.relowner
WHERE
ns.nspname = 'table schema' AND -- add table schema criteria
r.rolname = 'table owner' AND -- add table owner criteria
ns.nspname NOT IN ('pg_catalog', 'information_schema') AND -- exclude system schemas
c.relkind = 'r' AND -- tables only
has_table_privilege(c.oid, 'TRUNCATE') -- check current user has truncate privilege
\gexec
참고 \gexec
버전 9.6에 도입