পোস্টগ্রিস ডাটাবেসে সমস্ত টেবিল ছিন্ন করা


155

পুনঃনির্মাণের আগে আমার নিয়মিত আমার পোস্টগ্রিজ এসকিউএল ডাটাবেস থেকে সমস্ত ডেটা মুছতে হবে। আমি কীভাবে সরাসরি এসকিউএল এ এটি করব?

এই মুহুর্তে আমি একটি এসকিউএল স্টেটমেন্ট নিয়ে এসেছি যা আমাকে কার্যকর করার জন্য প্রয়োজনীয় সমস্ত কমান্ড প্রদান করে:

SELECT 'TRUNCATE TABLE ' ||  tablename || ';' FROM pg_tables WHERE tableowner='MYUSER';

আমি একবার এগুলি প্রোগ্রাম করার পরে তাদের চালানোর কোনও উপায় দেখতে পাচ্ছি না।

উত্তর:


226

হতাশাগ্রস্থ উইথফোর্ডস ডিজাইনার সঠিক, 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');

1
কিছুটা নতুন করে উঠতে হয়েছিল তবে তার পরে এটি কবজির মতো কাজ করেছিল! আমি এর আগে কখনও plpgsql ব্যবহার করি নি তাই এটি আমার বয়সের হয়ে উঠত। ধন্যবাদ! যার যার প্রয়োজন এটির জন্য আমি এই পোস্টের নীচে ব্যবহার করে কোডটি যুক্ত করেছি।
সিগ

দুঃখিত, আমি সম্ভবত ওরাকল পিএল / SQL এর যে চিন্তা ছিল :( আমি উপরে আমার কোডে বাক্যগঠন ত্রুটি সংশোধন করা হয়েছে।
Henning

1
আপনি SELECT স্টেটমেন্টটি সরাসরি ফর লুপেও স্থানান্তর করতে পারেন। DECLARE r RECORD;তারপরে লুপের জন্য: FOR r IN SELECT tablename FROM pg_tables LOOP
মাইকেল বুয়েন


3
ঈশ্বর!! আমি কেবলমাত্র আমার সমস্ত টেবিলগুলি "পাবলিক" স্কিমাতে কাটা করেছি .... পিএলএস "স্কিমা" এর অন্য একটি প্যারামিটার যুক্ত করে যাতে ফাংশনটি কেবলমাত্র প্রদত্ত স্কিমাতেই টেবিলগুলি কেটে দেয়!
roneo

95

স্পষ্টত কার্সারগুলি খুব কমই plpgsql এ প্রয়োজন। একটি লুপের সহজ এবং দ্রুত অন্তর্নিহিত কার্সার ব্যবহার করুন FOR:

দ্রষ্টব্য: যেহেতু টেবিলের নামগুলি প্রতিটি ডাটাবেস অনুসারে অনন্য নয়, আপনার নিশ্চিত হওয়ার জন্য আপনার সারণি-যোগ্যতার তালিকা থাকতে হবে। এছাড়াও, আমি ফাংশনটি ডিফল্ট স্কিমা 'সর্বজনীন' এর মধ্যে সীমাবদ্ধ করি। আপনার প্রয়োজন অনুযায়ী মানিয়ে কিন্তু সিস্টেম স্কিমের অগ্রাহ্য নিশ্চিত করা 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একসাথে একাধিক টেবিল করতে পারি আমাদের কোনও কার্সার বা লুপের প্রয়োজন নেই:

সমস্ত সারণির নাম একত্রিত করুন এবং একটি বিবৃতি কার্যকর করুন ute সহজ, দ্রুত:

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');

পরিশোধিত ক্যোয়ারী

এমনকি আপনার কোনও ফাংশনের দরকার নেই। পোস্টগ্রিস 9.0+ এ আপনি একটি DOবিবৃতিতে গতিশীল কমান্ডগুলি কার্যকর করতে পারেন । এবং পোস্টগ্রিস 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;

এটি অত্যন্ত দ্রুত , কারণ পোস্টগ্রিস ফাইলের স্তরে পুরো কাঠামোটি অনুলিপি করে। কোনও সম্মতিযুক্ত সমস্যা বা অন্যান্য ওভারহেড আপনাকে ধীর করে দিচ্ছে না।

যদি সমবর্তী সংযোগগুলি আপনাকে ডিবি বাদ দিতে দেয় তবে বিবেচনা করুন:


1
এটি লক্ষণীয় যে এই শেষ ফাংশনটি সমস্ত ডাটাবেস মুছে ফেলেছিল। শুধু বর্তমানে সংযুক্ত একজনকে নয় ... হ্যাঁ ... আমাকে নাইভ বলুন তবে সত্যিই এই পোস্টটি থেকে তা পরিষ্কার ছিল না।
অমলগোভিনাস

@ আমালগোভিনাস: শেষ কোন কাজ? আমার উত্তরের কোনও কার্যই বর্তমান ডাটাবেসের বাইরে কিছু স্পর্শ করে না ( DROP DATABASE mydbস্পষ্টতই, বাদে )। আপনি কি ডাটাবেসগুলির সাথে স্কিমগুলি বিভ্রান্ত করছেন ?
এরউইন ব্র্যান্ডস্টেটার

3
@ আমালগোভিনাস: না, এটা অসম্ভব। DOকমান্ড (অন্য কোন SQL বক্তব্য মত) বর্তমান ডাটাবেসের মধ্যে কার্যকর একচেটিয়াভাবে । পোস্টগ্রিসের একই লেনদেনে অন্যান্য ডাটাবেসগুলিতে অ্যাক্সেস করার কোনও উপায় নেই। এটি করতে আপনাকে dblink বা FDW ব্যবহার করতে হবে। কিন্তু এটা না যদি না আপনি যোগ - বর্তমান ডাটাবেসের মধ্যে সমস্ত স্কিমের প্রভাবিত WHERE t.schemaname = 'public'এই বিশেষ ক্ষেত্রে একটি বিশেষ স্কিমায় প্রভাব সীমিত করতে।
এরউইন ব্র্যান্ডসেটেটার

1
এই টেমপ্লেটগুলি সম্পর্কে জানতে পেরে সত্যিই দুর্দান্ত। এটি স্বয়ংক্রিয় পরীক্ষার দৃশ্যেও আমাকে দরকারী করতে পারে, যেখানে একটি ডাটাবেস পুনরায় সেট / প্রস্তুতির প্রয়োজন হতে পারে।
hbobenicio 16'17

3
দুর্দান্ত উত্তরের জন্য ধন্যবাদ, আমি "সিঙ্গেল কমান্ড, কোনও লুপ" ব্যবহার করছি যা ট্রানসেট কমান্ডটি ফেরত দেয়, আমি এটি কার্যকর করতে কীভাবে যাব?
মাহায়ার

40

যদি আমাকে এটি করতে হয়, আমি কেবল বর্তমান ডিবি এর স্কিমা স্ক্যুয়াল তৈরি করব, তারপরে ড্রপ ও ডিবি তৈরি করব, তারপরে স্কিমা স্ক্যুয়াল দিয়ে ডিবি লোড করুন।

নীচে জড়িত পদক্ষেপগুলি রয়েছে:

1) ডাটাবেসের স্কিমা ডাম্প তৈরি করুন ( --schema-only)

pg_dump mydb -s > schema.sql

2) ড্রপ ডাটাবেস

drop database mydb;

3) ডাটাবেস তৈরি করুন

create database mydb;

4) আমদানি স্কিমা

psql mydb < schema.sql


9

এক্ষেত্রে কেবলমাত্র একটি খালি ডাটাবেস যা আপনি টেম্পলেট হিসাবে ব্যবহার করেন এবং সম্ভবত আপনাকে তাজাতে হবে, বিদ্যমান ডাটাবেসটি ফেলে দিন এবং টেমপ্লেট থেকে একটি নতুন তৈরি করুন সম্ভবত এটি ভাল।


3

আপনি প্রতিটি বিবৃতি ঘুরিয়ে কার্যকর করতে গতিশীল এসকিউএল ব্যবহার করতে পারেন? এটি করার জন্য আপনাকে সম্ভবত একটি PL / pgSQL স্ক্রিপ্ট লিখতে হবে।

http://www.postgresql.org/docs/8.3/static/plpgsql-statements.html (বিভাগ 38.5.4। ডায়নামিক কমান্ড কার্যকর করা)


3

আপনি এটিকে বাশ দিয়েও করতে পারেন:

#!/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 "{}"

আপনার স্কিমার সাথে মেলে তুলতে আপনাকে স্কিমা নাম, পাসওয়ার্ড এবং ব্যবহারকারী নাম ব্যবহার করতে হবে to


3

পরিস্কারের 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;

3

বলছি আরও ভাল এবং পরিষ্কার উপায় হ'ল:

1) ডাটাবেসের স্কিমা ডাম্প তৈরি করুন (- কেবলমাত্র-কেবল) পিজি_ডাম্প মাইডিবি-এস> স্কিমা.এসকিউএল

2) ড্রপ ডাটাবেস ড্রপ ডাটাবেস mydb;

3) ডাটাবেস তৈরি করুন ডাটাবেস মাইডিবি তৈরি করুন;

4) আমদানি স্কিমা পিএসকিএল মাইডিবি <স্কিমা.এসকিউএল

এটা আমার জন্য কাজ!

আপনার দিনটি শুভ হোক. হিরাম ওয়াকার


2

আপনি যদি পিএসকিএল ব্যবহার করতে পারেন তবে \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 

নোট যা \gexec9.6 সংস্করণে প্রবর্তিত হয়েছে


1

ডেটা অপসারণ এবং টেবিল-কাঠামো সংরক্ষণের জন্য পিজিএডমিনে আপনি এটি করতে পারেন:

  • ডেক্স ক্লিক করুন ডাটাবেস -> ব্যাকআপ, "কেবলমাত্র স্কিমা" নির্বাচন করুন
  • ডাটাবেসটি ফেলে দিন
  • একটি নতুন ডাটাবেস তৈরি করুন এবং এটি পূর্বের মতো নাম দিন
  • নতুন ডাটাবেসটিতে ডান-ক্লিক করুন -> পুনরুদ্ধার করুন -> ব্যাকআপটি নির্বাচন করুন, "কেবলমাত্র স্কিমা" নির্বাচন করুন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.