ฉันจะแก้ไขเจ้าของตารางทั้งหมดในฐานข้อมูล PostgreSQL ได้อย่างไร
ฉันลองแล้วALTER TABLE * OWNER TO new_owner
แต่มันไม่รองรับไวยากรณ์ดอกจัน
ฉันจะแก้ไขเจ้าของตารางทั้งหมดในฐานข้อมูล PostgreSQL ได้อย่างไร
ฉันลองแล้วALTER TABLE * OWNER TO new_owner
แต่มันไม่รองรับไวยากรณ์ดอกจัน
คำตอบ:
REASSIGN OWNED
คำสั่งหมายเหตุ:ในฐานะที่เป็น @trygvis กล่าวถึงในคำตอบดังต่อไปนี้REASSIGN OWNED
คำสั่งที่สามารถใช้ได้อย่างน้อยตั้งแต่รุ่น 8.2 และเป็นวิธีที่ง่ายมาก
เนื่องจากคุณเปลี่ยนความเป็นเจ้าของสำหรับตารางทั้งหมดคุณอาจต้องการมุมมองและลำดับเช่นกัน นี่คือสิ่งที่ฉันทำ:
โต๊ะ:
for tbl in `psql -qAt -c "select tablename from pg_tables where schemaname = 'public';" YOUR_DB` ; do psql -c "alter table \"$tbl\" owner to NEW_OWNER" YOUR_DB ; done
ลำดับ:
for tbl in `psql -qAt -c "select sequence_name from information_schema.sequences where sequence_schema = 'public';" YOUR_DB` ; do psql -c "alter sequence \"$tbl\" owner to NEW_OWNER" YOUR_DB ; done
การเข้าชม:
for tbl in `psql -qAt -c "select table_name from information_schema.views where table_schema = 'public';" YOUR_DB` ; do psql -c "alter view \"$tbl\" owner to NEW_OWNER" YOUR_DB ; done
คุณอาจจะแห้งที่เพิ่มขึ้นเล็กน้อยเนื่องจากคำสั่งเปลี่ยนแปลงเหมือนกันสำหรับทั้งสาม
REASSIGN OWNED BY old_role [, ...] TO new_role
คุณสามารถใช้REASSIGN OWNED
คำสั่ง
REASSIGN OWNED BY old_role [, ...] TO new_role
สิ่งนี้จะเปลี่ยนวัตถุทั้งหมดที่เป็นold_role
ของบทบาทใหม่ คุณไม่ต้องคิดเกี่ยวกับวัตถุชนิดใดที่ผู้ใช้มีพวกเขาทั้งหมดจะถูกเปลี่ยน โปรดทราบว่าจะใช้กับวัตถุที่อยู่ในฐานข้อมูลเดียวเท่านั้น ไม่เปลี่ยนแปลงเจ้าของฐานข้อมูลเอง
มันสามารถใช้ได้อย่างน้อย 8.2 เอกสารออนไลน์ของพวกเขากลับไปไกลมาก
ERROR: unexpected classid 3079
. ฉันเดาว่าจะไม่ทำงานหากมีส่วนขยายใด ๆ
นี้: http://archives.postgresql.org/pgsql-bugs/2007-10/msg00234.phpเป็นวิธีที่ดีและรวดเร็วและทำงานได้หลาย schemas ในฐานข้อมูลเดียว:
ตาราง
SELECT 'ALTER TABLE '|| schemaname || '.' || tablename ||' OWNER TO my_new_owner;'
FROM pg_tables WHERE NOT schemaname IN ('pg_catalog', 'information_schema')
ORDER BY schemaname, tablename;
ลำดับ
SELECT 'ALTER SEQUENCE '|| sequence_schema || '.' || sequence_name ||' OWNER TO my_new_owner;'
FROM information_schema.sequences WHERE NOT sequence_schema IN ('pg_catalog', 'information_schema')
ORDER BY sequence_schema, sequence_name;
เข้าชม
SELECT 'ALTER VIEW '|| table_schema || '.' || table_name ||' OWNER TO my_new_owner;'
FROM information_schema.views WHERE NOT table_schema IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name;
มุมมองที่ปรากฏ
ตามคำตอบนี้
SELECT 'ALTER TABLE '|| oid::regclass::text ||' OWNER TO my_new_owner;'
FROM pg_class WHERE relkind = 'm'
ORDER BY oid;
สิ่งนี้จะสร้างคำสั่ง/ ALTER TABLE
/ ที่จำเป็นทั้งหมดคัดลอกสิ่งเหล่านี้และวางลงใน plsql เพื่อเรียกใช้ALTER SEQUENCE
ALTER VIEW
ตรวจสอบงานของคุณเป็น psql โดยทำ:
\dt *.*
\ds *.*
\dv *.*
หากคุณต้องการที่จะทำมันในหนึ่งคำสั่ง sql คุณจะต้องกำหนดฟังก์ชั่น exec () ดังกล่าวในhttp://wiki.postgresql.org/wiki/Dynamic_DDL
CREATE FUNCTION exec(text) returns text language plpgsql volatile
AS $f$
BEGIN
EXECUTE $1;
RETURN $1;
END;
$f$;
จากนั้นคุณสามารถเรียกใช้คิวรีนี้มันจะเปลี่ยนเจ้าของตารางลำดับและมุมมอง:
SELECT exec('ALTER TABLE ' || quote_ident(s.nspname) || '.' ||
quote_ident(s.relname) || ' OWNER TO $NEWUSER')
FROM (SELECT nspname, relname
FROM pg_class c JOIN pg_namespace n ON (c.relnamespace = n.oid)
WHERE nspname NOT LIKE E'pg\\_%' AND
nspname <> 'information_schema' AND
relkind IN ('r','S','v') ORDER BY relkind = 'S') s;
$ NEWUSER เป็นชื่อใหม่ postgresql ของเจ้าของใหม่
ในสถานการณ์ส่วนใหญ่คุณจะต้องเป็น superuser ในการดำเนินการนี้ คุณสามารถหลีกเลี่ยงได้โดยเปลี่ยนเจ้าของจากผู้ใช้ของคุณเองเป็นกลุ่มบทบาทที่คุณเป็นสมาชิก
ขอบคุณ RhodiumToad ใน#postgresql ที่ช่วยเหลือสิ่งนี้
ฉันเพิ่งเปลี่ยนความเป็นเจ้าของของวัตถุทั้งหมดในฐานข้อมูล แม้ว่าตารางมุมมองทริกเกอร์และลำดับจะค่อนข้างง่ายเปลี่ยนวิธีการข้างต้นล้มเหลวสำหรับฟังก์ชั่นเนื่องจากลายเซ็นเป็นส่วนหนึ่งของชื่อฟังก์ชั่น ได้รับฉันมีพื้นหลัง MySQL และไม่คุ้นเคยกับ Postgres
อย่างไรก็ตามpg_dumpอนุญาตให้คุณดัมพ์เฉพาะสกีมาและสิ่งนี้มีALTER xxx OWNER TO yyy; งบที่คุณต้องการ นี่คือเวทย์มนตร์เชลล์ของฉันในหัวข้อ
pg_dump -s YOUR_DB | grep -i 'owner to' | sed -e 's/OWNER TO .*;/OWNER TO NEW_OWNER;/i' | psqL YOUR_DB
grep
คำสั่ง ฉันใหม่สำหรับ Linux ด้วยตัวเอง แต่จากความเข้าใจของฉันดูเหมือนว่าใช้ได้sed
ดีโดยเฉพาะอย่างยิ่งเมื่อคุณระบุการจับคู่แบบตรงและตัวพิมพ์เล็ก
ง่ายมากลองดูสิ ...
select 'ALTER TABLE ' || table_name || ' OWNER TO myuser;' from information_schema.tables where table_schema = 'public';
ง่ายมาก
เสร็จแล้ว
ฉันเช่นนี้เพราะมันปรับเปลี่ยนตาราง , มุมมอง , ลำดับและฟังก์ชั่นเจ้าของบางสคีในหนึ่งไป (ในหนึ่งคำสั่ง SQL) โดยไม่ต้องสร้างฟังก์ชั่นและคุณสามารถใช้งานได้โดยตรงในpgAdmin IIIและpsql :
(ทดสอบใน PostgreSql v9.2)
DO $$DECLARE r record;
DECLARE
v_schema varchar := 'public';
v_new_owner varchar := '<NEW_OWNER>';
BEGIN
FOR r IN
select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.tables where table_schema = v_schema
union all
select 'ALTER TABLE "' || sequence_schema || '"."' || sequence_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.sequences where sequence_schema = v_schema
union all
select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.views where table_schema = v_schema
union all
select 'ALTER FUNCTION "'||nsp.nspname||'"."'||p.proname||'"('||pg_get_function_identity_arguments(p.oid)||') OWNER TO ' || v_new_owner || ';' as a from pg_proc p join pg_namespace nsp ON p.pronamespace = nsp.oid where nsp.nspname = v_schema
LOOP
EXECUTE r.a;
END LOOP;
END$$;
จากคำตอบของ @rkj, @AlannaRose, @SharoonThomas, @ user3560574 และคำตอบนี้โดย @a_horse_with_no_name
ขอบคุณมาก.
ยังดีกว่า: เปลี่ยนฐานข้อมูลและเจ้าของสคีมาด้วย
DO $$DECLARE r record;
DECLARE
v_schema varchar := 'public';
v_new_owner varchar := 'admin_ctes';
BEGIN
FOR r IN
select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.tables where table_schema = v_schema
union all
select 'ALTER TABLE "' || sequence_schema || '"."' || sequence_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.sequences where sequence_schema = v_schema
union all
select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.views where table_schema = v_schema
union all
select 'ALTER FUNCTION "'||nsp.nspname||'"."'||p.proname||'"('||pg_get_function_identity_arguments(p.oid)||') OWNER TO ' || v_new_owner || ';' as a from pg_proc p join pg_namespace nsp ON p.pronamespace = nsp.oid where nsp.nspname = v_schema
union all
select 'ALTER SCHEMA "' || v_schema || '" OWNER TO ' || v_new_owner
union all
select 'ALTER DATABASE "' || current_database() || '" OWNER TO ' || v_new_owner
LOOP
EXECUTE r.a;
END LOOP;
END$$;
information_schema.sequences
ว่างเปล่าแม้ว่าSELECT c.* FROM pg_class c WHERE c.relkind = 'S';
จะเรียงลำดับ ทำไมพวกเขาถึงไม่ตรงกัน
ALTER
แบบสอบถามที่สองไม่ควรALTER SEQUENCE
ใช่หรือไม่
ฉันต้องเปลี่ยนความเป็นเจ้าของของตารางมุมมองและลำดับและพบทางออกที่ดีที่โพสต์โดย @rjk ทำงานได้ดี - แม้จะมีหนึ่งรายละเอียด: ถ้าชื่อวัตถุเป็นกรณีผสม (เช่น "TableName") สิ่งนี้จะล้มเหลวด้วย " ไม่พบ "-error
ในการหลีกเลี่ยงสิ่งนี้ให้ล้อมชื่อวัตถุด้วย '"' ดังนี้:
SELECT 'ALTER TABLE \"'|| schemaname || '.' || tablename ||'\" OWNER TO my_new_owner;'
FROM pg_tables WHERE NOT schemaname IN ('pg_catalog', 'information_schema')
ORDER BY schemaname, tablename;
SELECT 'ALTER SEQUENCE \"'|| sequence_schema || '.' || sequence_name ||'\" OWNER TO my_new_owner;'
FROM information_schema.sequences WHERE NOT sequence_schema IN ('pg_catalog', 'information_schema')
ORDER BY sequence_schema, sequence_name;
SELECT 'ALTER VIEW \"'|| table_schema || '.' || table_name ||'\" OWNER TO my_new_owner;'
FROM information_schema.views WHERE NOT table_schema IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name;
คุณสามารถลองสิ่งต่อไปนี้ใน PostgreSQL 9
DO $$DECLARE r record;
BEGIN
FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public'
LOOP
EXECUTE 'alter table '|| r.tablename ||' owner to newowner;';
END LOOP;
END$$;
ไม่มีคำสั่งดังกล่าวใน PostgreSQL แต่คุณสามารถหลีกเลี่ยงได้โดยใช้วิธีที่ฉันได้อธิบายเมื่อไม่นานมานี้สำหรับ GRANTs
จากคำตอบของ elyschนี่คือวิธีแก้ปัญหาสำหรับ schema หลาย ๆ ตัว:
DO $$
DECLARE
r record;
i int;
v_schema text[] := '{public,schema1,schema2,schema3}';
v_new_owner varchar := 'my_new_owner';
BEGIN
FOR r IN
select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.tables where table_schema = ANY (v_schema)
union all
select 'ALTER TABLE "' || sequence_schema || '"."' || sequence_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.sequences where sequence_schema = ANY (v_schema)
union all
select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.views where table_schema = ANY (v_schema)
union all
select 'ALTER FUNCTION "'||nsp.nspname||'"."'||p.proname||'"('||pg_get_function_identity_arguments(p.oid)||') OWNER TO ' || v_new_owner || ';' as a from pg_proc p join pg_namespace nsp ON p.pronamespace = nsp.oid where nsp.nspname = ANY (v_schema)
union all
select 'ALTER DATABASE "' || current_database() || '" OWNER TO ' || v_new_owner
LOOP
EXECUTE r.a;
END LOOP;
FOR i IN array_lower(v_schema,1) .. array_upper(v_schema,1)
LOOP
EXECUTE 'ALTER SCHEMA "' || v_schema[i] || '" OWNER TO ' || v_new_owner ;
END LOOP;
END
$$;
คำตอบโดย @Alex Soto เป็นคำตอบที่ถูกต้องและส่วนสำคัญที่อัพโหลดโดย @Yoav Aner สามารถใช้ได้หากไม่มีอักขระพิเศษในชื่อตาราง / มุมมอง (ซึ่งถูกกฎหมายใน postgres)
คุณต้องหลบหนีพวกเขาให้ทำงานและฉันได้อัพโหลดส่วนสำคัญสำหรับสิ่งนั้น: https://gist.github.com/2911117
pg_dump as insert statements
pg_dump -d -O database filename
-d ( data as inserts ) -O ( capital O is no owner )
จากนั้นไพพ์ไฟล์สำรองข้อมูลกลับไปยัง PostgreSQL โดยใช้:
psql -d database -U username -h hostname < filename
เนื่องจากไม่มีเจ้าของรวมอยู่จึงสร้างตาราง schema ฯลฯ ทั้งหมดที่สร้างขึ้นภายใต้ผู้ใช้ที่คุณระบุ
ฉันได้อ่านสิ่งนี้อาจเป็นวิธีที่ดีสำหรับการย้ายระหว่างรุ่น PostgreSQL เช่นกัน
ฉันได้สร้างสคริปต์ที่สะดวกสำหรับสิ่งนั้น pg_change_db_owner.sh สคริปต์นี้เปลี่ยนความเป็นเจ้าของสำหรับตารางมุมมองลำดับและฟังก์ชั่นทั้งหมดในสคีมาฐานข้อมูลและเจ้าของสคีมาเอง
โปรดทราบว่าหากคุณต้องการเปลี่ยนความเป็นเจ้าของของวัตถุทั้งหมดในฐานข้อมูลเฉพาะเป็นเจ้าของโดยบทบาทฐานข้อมูลเฉพาะจากนั้นคุณสามารถใช้คำสั่งREASSIGN OWNED
แทน
เริ่มต้นใน PostgreSQL 9.0 คุณมีความสามารถในการGRANT [priv name] ON ALL [object type] IN SCHEMA
ที่[priv name]
เป็นปกติSELECT, INSERT, UPDATE, DELETE, etc
และ[object type]
สามารถเป็นหนึ่งใน:
TABLES
SEQUENCES
FUNCTIONS
เอกสารของ PostgreSQL GRANT
แล้วREVOKE
ไปดูรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้ ในบางสถานการณ์ก็ยังจำเป็นต้องใช้ลูกเล่นที่เกี่ยวข้องกับแคตตาล็อกระบบ ( pg_catalog.pg_*
) แต่มันก็ไม่ได้เป็นเรื่องธรรมดา ฉันมักจะทำต่อไปนี้:
BEGIN
ธุรกรรมเพื่อแก้ไข privsDATABASES
เป็น "บทบาท DBA"SCHEMAS
เป็น "บทบาท DBA"REVOKE ALL
PRIVS ในทุกTABLES
, SEQUENCES
และFUNCTIONS
จากบทบาททั้งหมดGRANT SELECT, INSERT, UPDATE, DELETE
บนตารางที่เกี่ยวข้อง / เหมาะสมกับบทบาทที่เหมาะสมCOMMIT
ธุรกรรม DCLโซลูชันที่ได้รับการยอมรับไม่ได้ดูแลความเป็นเจ้าของฟังก์ชั่นดังต่อไปนี้โซลูชันจะดูแลทุกอย่าง (ในขณะที่ตรวจสอบฉันสังเกตเห็นว่ามันคล้ายกับ @magiconair ด้านบน)
echo "Database: ${DB_NAME}"
echo "Schema: ${SCHEMA}"
echo "User: ${NEW_OWNER}"
pg_dump -s -c -U postgres ${DB_NAME} | egrep "${SCHEMA}\..*OWNER TO"| sed -e "s/OWNER TO.*;$/OWNER TO ${NEW_OWNER};/" | psql -U postgres -d ${DB_NAME}
# do following as last step to allow recovery
psql -U postgres -d postgres -c "ALTER DATABASE ${DB_NAME} OWNER TO ${NEW_OWNER};"
สคริปต์เชลล์ที่เรียบง่ายต่อไปนี้ใช้ได้กับฉัน
#!/bin/bash
for i in `psql -U $1 -qt -c "select tablename from pg_tables where schemaname='$2'"`
do
psql -U $1 -c "alter table $2.$i set schema $3"
done
โดยที่อินพุต $ 1 - ชื่อผู้ใช้ (ฐานข้อมูล) $ 2 = สคีมาที่มีอยู่ $ 3 = ถึงสคีมาใหม่
เหมือนกับแนวทางของ @ AlexSoto สำหรับฟังก์ชั่น:
IFS=$'\n'
for fnc in `psql -qAt -c "SELECT '\"' || p.proname||'\"' || '(' || pg_catalog.pg_get_function_identity_arguments(p.oid) || ')' FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_proc p ON p.pronamespace = n.oid WHERE n.nspname = 'public';" YOUR_DB` ; do psql -c "alter function $fnc owner to NEW_OWNER" YOUR_DB; done
export user="your_new_owner"
export dbname="your_db_name"
cat <<EOF | docker run -i --rm --link postgres:postgres postgres sh -c "psql -h \$POSTGRES_PORT_5432_TCP_ADDR -p \$POSTGRES_PORT_5432_TCP_PORT -U postgres -d $dbname" | grep ALTER | docker run -i --rm --link postgres:postgres postgres sh -c "psql -h \$POSTGRES_PORT_5432_TCP_ADDR -p \$POSTGRES_PORT_5432_TCP_PORT -U postgres -d $dbname"
SELECT 'ALTER TABLE '||schemaname||'.'||tablename||' OWNER TO $user;' FROM pg_tables WHERE schemaname = 'public';
SELECT 'ALTER SEQUENCE '||relname||' OWNER TO $user;' FROM pg_class WHERE relkind = 'S';
EOF