Benutzer-Werkzeuge

Webseiten-Werkzeuge


datenbank:postgresql

Dies ist eine alte Version des Dokuments!


PostgreSQL

Anleitungen bzw. Beispiele

passwortloser login mit ~/.pgpass:

> touch ~/.pgpass
> chmod 0600 ~/.pgpass
> vi ~/.pgpass
hostname:port:database:username:password

> vi ~/.bashrc
PGPASSFILE="$HOME/.pgpass"

> echo "\dt;" | psql database

individuelle Konfiguration mit ~/.psqlrc:

> echo "\dt;" | psql postgresql://username:password@address:5432/database
> echo '\timing on' >> ~/.psqlrc
> echo '\c postgresql://username@address:5432/database' >> ~/.psqlrc

PG-User ändert sein eigenes Passwort:

> psql -U dbuser -d dbname
dbname=> \password
Enter new password for user "dbuser":
Enter it again:
dbname=> quit

SHOW USERS:

> echo "\du" | psql -U postgres -d postgres

SHOW DATABASES:

> psql -U postgres -l
> echo -e "\l" | psql -U username -d postgres

SHOW TABLES:

> echo "\dt" | psql -U username -d database
> echo "SELECT * FROM pg_catalog.pg_tables;" | psql -U username -d database

SELECT FROM TABLE:

> echo "echo "SELECT COUNT(*) FROM tabellenname;" | psql -U username -d database

CREATE DATABASE:

> echo "CREATE DATABASE database OWNER = username;" | psql -U postgres

CREATE TABLE:

> echo "CREATE TABLE tabellenname (...);" | psql -U username -d database

CREATE TABLE mit "Auto Increment" ("Auto Increment" heißt in PostgreSQL SERIAL oder BIGSERIAL):

> echo "CREATE TABLE film (ID BIGSERIAL PRIMARY KEY, verzeichnis varchar(1000), datei varchar(100), name varchar(100), type varchar(100), jahr integer, laufzeit integer, altersfreigabe integer, genre varchar(100), produzent varchar(100), regie varchar(100), schauspieler varchar(10000), handlung varchar(100000), UNIQUE (pfad, dateiname));" | psql -U username -d database

Tabellenstruktur anzeigen:

> echo "\d+ tabellenname" | psql -U username -d database

soll die ~/.psqlrc nicht berücksichtigt werden, dann braucht man -X

> echo "SELECT COUNT(*) FROM tabellenname;" | psql -X -U username -d database

SHOW CREATE TABLE:

> pg_dump --schema-only -U username -d database -t tabellenname

ADD PRIMARY KEY:

> ALTER TABLE tabellenname ADD PRIMARY KEY(spalte1, spalte2);

DROP TABLE:

> echo "DROP TABLE tabellenname;" | psql -U username -d database

SHOW FULL PROCESSLIST:

> echo "SELECT * FROM pg_stat_activity;" | psql -U username
> echo "SELECT datname, pid, state, query, age(clock_timestamp(), query_start) AS age FROM pg_stat_activity WHERE state <> 'idle' AND query NOT LIKE '% FROM pg_stat_activity %' ORDER BY age;" | psql -U username -h 10.1.1.10

TEMP TABLE

DROP TABLE IF EXISTS TmpTabNamen;
BEGIN TRANSACTION;
  CREATE TEMP TABLE TmpTabNamen AS SELECT ... FROM TabNamen WHERE ...;
COMMIT;

SELECT * FROM TmpTabNamen WHERE ...;
DROP TABLE IF EXISTS TmpTabNamen;

PostgreSQL 12 auf Debian 11 installieren

Repository einrichten

> apt update && apt -y full-upgrade
> wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc > /etc/apt/keyrings/pgdg.asc
> apt -y install gnupg2
> echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list
> apt update

den Postgresql-Client installieren

> apt install postgresql-client-12

den Postgresql-Server (incl. Client) installieren

> apt install postgresql-12

PostgreSQL-Wartung

Werkzeug für die PostgreSQL-Leistungsüberwachung, ähnlich top:

[root@freebsd12 ~]# cd /usr/ports/www/p5-LWP-UserAgent-WithCache && make clean && make && make install ; make clean
[root@freebsd12 ~]# cd /usr/ports/databases/pgtop && make clean && make && make install ; make clean

[root@freebsd12 ~]# touch ~/.pgtop
[root@freebsd12 ~]# chmod 0600 ~/.pgtop
[root@freebsd12 ~]# vi ~/.pgtop
user=postgres
pass=
host=localhost
port=5432
db=test

[root@erde ~]# su - postgres -c "echo 'CREATE DATABASE test OWNER = postgres;' | psql postgres"
CREATE DATABASE

[root@erde ~]# su - postgres -c "echo '\l' | psql postgres"
                                  List of databases
      Name      |  Owner   | Encoding | Collate |    Ctype    |   Access privileges   
----------------+----------+----------+---------+-------------+-----------------------
 ...
 test           | postgres | UTF8     | C       | de_DE.UTF-8 | 
 ...

[root@freebsd12 ~]# pgtop

Manueller Aufruf für die DB-Wartung, gelöschte Bereiche wieder frei zugeben.

eine einzelne DB:

[root@freebsd12 ~]# su - postgres -c "echo 'vacuum verbose' | psql DatenbankName"
...
...
...
VACUUM

alle DBs:

[root@freebsd12 ~]# su - postgres -c "vacuumdb -aefz"
SELECT pg_catalog.set_config('search_path', '', false)
SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;
SELECT pg_catalog.set_config('search_path', '', false)
vacuumdb: vacuuming database "postgres"
VACUUM (FULL, ANALYZE);
SELECT pg_catalog.set_config('search_path', '', false)
vacuumdb: vacuuming database "template1"
VACUUM (FULL, ANALYZE);

PostgreSQL-Datenbank bläht sich auf

Dealing with significant Postgres database bloat — what are your options?

Das Aktualisieren eines vorhandenen Datensatzes führt zu einem toten Tupel, der vorherigen Version des Datensatzes sowie einem neuen Datensatz. Wenn die Rate der erstellten toten Tupel die Fähigkeit der Datenbank überschreitet, tote Tupel automatisch zu bereinigen, tritt ein Aufblähen auf. Stellen wir uns ein Szenario vor, in dem eine Anwendung Datensätze mit durchschnittlich 1.000 Datensätzen pro Sekunde aktualisiert oder löscht und der Autovacuum-Daemon tote Tupel mit einer durchschnittlichen Rate von 800 pro Sekunde entfernt. Jede Sekunde treten 200 Tupel Blähungen auf. Beachten Sie, dass dies ein hypothetisches Szenario ist. Es ist nicht möglich, den Autovakuum-Daemon so einzustellen, dass tote Tupel mit 800/s entfernt werden.

Autovacuum-Daemon aktivieren:

> vi /etc/postgresql/10/main/postgresql.conf

> cp /usr/local/share/postgresql/postgresql.conf.sample /usr/local/pgsql/data/postgresql.conf
> vi /usr/local/pgsql/data/postgresql.conf
...
track_counts = on
...
autovacuum = on
...

erste Schritte in PostgreSQL

Übrigens! ChatGPT kann einem ruck-zuck die richtigen Befehle nennen und das auch noch wenn man die Frage in umgangssprachlichem Deutsch gestellt hat.

ein Backup einer Datenbank anlegen:

pg_dump -d filme -f postgres_backup_-_filme.sql

einen Benutzer "indy" anlegen:

createuser -U postgres --no-superuser --no-createdb --no-createrole indy
echo "\du" | psql

einem DB-Benutzer Rechte über eine ganze DB erteilen:

echo "GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO indy;" | psql -d filme

einem DB-Benutzer Rechte über eine Tabelle erteilen:

echo "GRANT INSERT, UPDATE, DELETE ON TABLE tabellenname TO indy;" | psql -d filme

einen Benutzer löschen:

echo "DROP USER indy;" | psql

ein Datenbank-Backup in ein leeres DBMS einspielen:

echo "CREATE DATABASE filme;" | psql
psql -d filme -f postgres_backup_-_filme.sql

alle Datenbanken anzeigen:

echo "\l" | psql

alle Tabellen aus einer Datenbank anzeigen:

echo "\dt" | psql database_name

Anzeigen der Struktur einer bestimmten Tabelle:

echo "\d table_name" | psql database_name

eine Tabelle löschen:

echo "DROP TABLE table_name;" | psql database_name

eine DB löschen:

echo "DROP DATABASE database_name;" | psql
  Indexe anzeigen: \di
  Fremdschlüssel anzeigen: \dfk
  VIEWs anzeigen: \dv
  Funktionen anzeigen: \df
psql postgres -l
echo "\l" | psql
echo "\dt" | psql -U indy -d filme

MySQL: SHOW FULL PROCESSLIST

SELECT * FROM pg_stat_activity;

1. Benutzer in PostgreSQL anlegen

zum PostgreSQL-root-User werden:

> su - postgres

User anlegen:

$ createuser fritz

wieder ausloggen und wieder "ich" werden:

$ exit

User anzeigen:

> echo "\dg" | psql postgres
                                      Liste der Rollen
 Rollenname |                            Attribute                            | Mitglied von 
------------+-----------------------------------------------------------------+--------------
 fritz      |                                                                 | {}
 postgres   | Superuser, Rolle erzeugen, DB erzeugen, Replikation, Bypass RLS | {}

2. Benutzer in PostgreSQL anlegen

zum PostgreSQL-root-User werden:

> su - postgres

Syntax anzeigen:

$ echo "\h CREATE USER;" | psql postgres
Anweisung:    CREATE USER
Beschreibung: definiert eine neue Datenbankrolle
Syntax:
CREATE USER Name [ [ WITH ] Option [ ... ] ]

wobei Option Folgendes sein kann:

      SUPERUSER | NOSUPERUSER
    | CREATEDB | NOCREATEDB
    | CREATEROLE | NOCREATEROLE
    | CREATEUSER | NOCREATEUSER
    | INHERIT | NOINHERIT
    | LOGIN | NOLOGIN
    | REPLICATION | NOREPLICATION
    | BYPASSRLS | NOBYPASSRLS
    | CONNECTION LIMIT Verbindungslimit
    | [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'Passwort'
    | VALID UNTIL 'Zeit'
    | IN ROLE Rollenname [, ...]
    | IN GROUP Rollenname [, ...]
    | ROLE Rollenname [, ...]
    | ADMIN Rollenname [, ...]
    | USER Rollenname [, ...]
    | SYSID Uid

User anlegen:

$ echo "CREATE USER fritz;" | psql postgres
$ echo "CREATE USER fritz WITH CREATEDB PASSWORD 'geheim';" | psql postgres

Passwort ändern:

$ echo "ALTER USER fritz WITH PASSWORD 'geheim';" | psql postgres

fritz alle Privilegien nehmen:

$ echo "REVOKE ALL ON ALL TABLES IN SCHEMA public FROM fritz;" | psql postgres

allen Usern alle Privilegien nehmen:

$ echo "REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC;" | psql postgres

User löschen

$ echo "DROP USER fritz;" | psql postgres

User anlegen:

$ echo "CREATE USER fritz WITH CREATEDB;" | psql postgres

wieder ausloggen und wieder "ich" werden:

$ exit

User anzeigen:

> echo "\dg" | psql postgres
                                      Liste der Rollen
 Rollenname |                            Attribute                            | Mitglied von 
------------+-----------------------------------------------------------------+--------------
 fritz      | DB erzeugen                                                     | {}
 postgres   | Superuser, Rolle erzeugen, DB erzeugen, Replikation, Bypass RLS | {}

> echo "\du" | psql postgres
                                      Liste der Rollen
 Rollenname |                            Attribute                            | Mitglied von 
------------+-----------------------------------------------------------------+--------------
 fritz      | DB erzeugen                                                     | {}
 postgres   | Superuser, Rolle erzeugen, DB erzeugen, Replikation, Bypass RLS | {}
> echo "ALTER USER fritz RESET tabellen_name;" | psql postgres
> echo "GRANT UPDATE ON tabellen_name TO fritz;" | psql postgres
> echo "REVOKE ALL PRIVILEGES ON tabellen_name FROM fritz;" | psql postgres
> echo "REVOKE ALL PRIVILEGES ON tabellen_name FROM PUBLIC;" | psql postgres
> echo "REVOKE ALL PRIVILEGES ON datenbank FROM fritz;" | psql postgres

PostgreSQL-Hilfe

Datenbanken auflisten:

> echo "\l" | psql postgres
                                  Liste der Datenbanken
   Name    | Eigentümer | Kodierung | Sortierfolge | Zeichentyp  |  Zugriffsprivilegien
-----------+------------+-----------+--------------+-------------+-----------------------
 postgres  | postgres   | UTF8      | C            | de_DE.UTF-8 |
 template0 | postgres   | UTF8      | C            | de_DE.UTF-8 | =c/postgres          +
           |            |           |              |             | postgres=CTc/postgres
 template1 | postgres   | UTF8      | C            | de_DE.UTF-8 | =c/postgres          +
           |            |           |              |             | postgres=CTc/postgres
(3 Zeilen)

Tabellen auflisten:

> echo "\dt" | psql postgres

Zugriffsprivilegien für Tabellen, Sichten und Sequenzen auflisten

> echo "\dp" | psql postgres

alle Konfigurationsparameter anzeigen:

> echo "SHOW ALL;" | psql postgres

Hilfe:

> psql --help
> echo "\h" | psql postgres
> echo "\?" | psql postgres
...
  Hilfe
  \? [commands]          Hilfe über Backslash-Befehle anzeigen
  \? options             Hilfe über psql-Kommandozeilenoptionen anzeigen
  \? variables           Hilfe über besondere Variablen anzeigen
  \h [NAME]              Syntaxhilfe über SQL-Anweisung, * für alle Anweisungen
...

Verbindungen anzeigen:

> echo "\conninfo" | psql postgres
Sie sind verbunden mit der Datenbank "postgres" als Benutzer "fritz" via Socket in "/tmp" auf Port "5432".

Datenbank in PostgreSQL anlegen

Datenbank anlegen:

> createdb dbname

oder so

> echo "CREATE DATABASE dbname OWNER = fritz;" | psql postgres
CREATE DATABASE

neue DB anzeigen:

> echo "\l" | psql postgres
                                 Liste der Datenbanken
   Name    | Eigentümer | Kodierung | Sortierfolge | Zeichentyp  | Zugriffsprivilegien 
-----------+------------+-----------+--------------+-------------+---------------------
 dbname    | fritz      | UTF8      | C            | de_DE.UTF-8 | 
 postgres  | pgsql      | UTF8      | C            | de_DE.UTF-8 | 
 template0 | pgsql      | UTF8      | C            | de_DE.UTF-8 | =c/pgsql           +
           |            |           |              |             | pgsql=CTc/pgsql
 template1 | pgsql      | UTF8      | C            | de_DE.UTF-8 | =c/pgsql           +
           |            |           |              |             | pgsql=CTc/pgsql
(4 Zeilen)

Backup erstellen:

> pg_dump dbname > dbname.pgdump

Backup zurück spielen:

> cat dbname.pgdump | psql dbname

Tabelle in PostgreSQL anlegen

Tabelle anlegen:

> echo "CREATE TABLE film (ID serial, verzeichnis varchar(1000), datei varchar(100), name varchar(100), type varchar(100), jahr integer, laufzeit integer, altersfreigabe integer, genre varchar(100), produzent varchar(100), regie varchar(100), schauspieler varchar(10000), handlung varchar(100000), PRIMARY KEY (ID));" | psql dbname

Index (name_idx) in der Tabelle (film) auf eine Spalte (Name) angelegt:

> echo "CREATE INDEX name_idx ON film (name);" | psql dbname
CREATE INDEX

Tabelle löschen:

> echo "DROP TABLE film;" | psql dbname
DROP TABLE

mal reinschauen:

> echo "SELECT * FROM film;" | psql filme
 id | verzeichnis | datei | name | type | jahr | laufzeit | altersfreigabe | genre | produzent | regie | schauspieler | handlung 
----+-------------+-------+------+------+------+----------+----------------+-------+-----------+-------+--------------+----------
(0 Zeilen)

Datensätze in der Tabelle

zwei Datensätze eintragen:

INSERT INTO film (verzeichnis, datei, name, type, jahr, laufzeit, altersfreigabe, genre, produzent, regie, schauspieler, handlung) VALUES ('/Filme/','Otto_der_Film.mp4','Otto der Film','Film',1985,5100,0,'Komödie','Horst Wendlandt','Xaver Schwarzenberger, Otto Waalkes','Otto Waalkes',''), ('/Filme/','Grosse_Pointe_Blank.mp4','Ein Mann - ein Mord','Film',1997,6420,16,'Komödie','Susan Arnold, Roger Birnbaum','George Armitage','John Cusack','');

beide Datensätze nacheinander ändern:

UPDATE [Tabellenname] SET [Spaltenname1]='Inhalt1', [Spaltenname2] = 'Inhalt2' WHERE [Spaltenname3] = 'Inhalt3';

UPDATE film SET genre='Filmkomödie', handlung = 'Otto wächst im beschaulichen Ostfriesland auf.' WHERE datei = 'Otto_der_Film.mp4';
UPDATE film SET genre='Filmkomödie', handlung = 'Martin Blank ist Profikiller. Nicht immer läuft alles nach Plan, weshalb seine Auftraggeber unzufrieden sind.' WHERE datei = 'Grosse_Pointe_Blank.mp4';

eine Tabelle umbenennen

ALTER TABLE [alter Tabellenname] RENAME TO [neuer Tabellenname];

eine Spalte zur Tabelle hinzufügen

https://oracleplsql.info/alter-table-postgresql.html

ALTER TABLE [Tabellenname] ADD [Spaltenname] [Spaltentyp];
ALTER TABLE order_details ADD sort_datum date;

Es gibt keine Möglichkeit, hier eine Anweisung mit zugeben, um die Spalte an einer bestimmten Stelle einzufügen!

eine neue Tabelle anlegen, die genau die gleichen Spalten hat wie eine bereits vorhandene

CREATE TABLE [neuer Tabellenname] (LIKE [alter Tabellenname]);

Volltextsuche (case-insensitive)

> echo "SELECT * FROM Tabelle WHERE Spalte ILIKE ('%suchzeichen%');" | psql -U Benutzer -d Datenbank

weitere PostgreSQL-Kommandos

Verbindungen: echo "\conninfo" | psql postgres
User anzeigen: echo "\dg" | psql postgres
Zugriffsprivilegien: echo "\dp" | psql dbname
Standard-Zugriffsprivilegien: echo "\ddp" | psql dbname
Datentypen: echo "\dT" | psql dbname

alle Datenbanken anzeigen: echo "\l" | psql postgres
alle Relationen (Tabellen+Indizes+...): echo "\d" | psql dbname

Tabellen: echo "\dt" | psql dbname
Tablespaces: echo "\db" | psql dbname

Indizes: echo "\ds" | psql dbname
Schemas: echo "\dn" | psql dbname

Trigger: echo "\dy" | psql dbname
Domänen: echo "\dD" | psql dbname
Funktionen: echo "\df" | psql dbname
Objektbeschreibungen: echo "\dd" | psql dbname
Large Objects: echo "\dl" | psql dbname
Operatoren: echo "\do" | psql dbname
installierten Erweiterungen: echo "\dx" | psql dbname
Aggregatfunktionen: echo "\da" | psql dbname
Konversionen: echo "\dc" | psql dbname
Textsuchekonfigurationen: echo "\dF" | psql dbname
Textsuchewörterbücher: echo "\dFd" | psql dbname
Textsucheparser: echo "\dFp" | psql dbname
Textsuchevorlagen: echo "\dFt" | psql dbname
Liste der prozeduralen Sprachen: echo "\dL" | psql dbname
Liste der Operatoren: echo "\do" | psql dbname
Liste der Sortierfolgen: echo "\dO" | psql dbname

Stringausgabe: echo "\echo" | psql dbname
Zeichensatzkodierung: echo "\encoding" | psql dbname
Zeldtrennzeichen: echo "\f ' '" | psql dbname
Ausgabe direkt in eine Datei: echo "\o '/tmp/datenbankausgabe.txt'" | psql dbname
Ausgabe in eine Datei: echo "\w '/tmp/datenbankausgabe.txt'" | psql dbname
Ausgabe einem Kommando übergeben: echo "\w '| /bin/systembefehl'" | psql dbname

SQL

UNION und UNION DISTINCT entfernen alle doppelten Zeilen, UNION ALL gibt dagegen auch die doppelten Zeilen aus, um schneller zu sein.

(SELECT * FROM tabelle1) UNION (SELECT * FROM tabelle2)

INTERSECT zeigt alle Zeilen, die in beiden Ausgaben vorhanden sind, doppelten Zeilen werden entfernt, INTERSECT ALL gibt dagegen auch die doppelten Zeilen aus, um schneller zu sein.

(SELECT * FROM tabelle1) INTERSECT (SELECT * FROM tabelle2)

EXCEPT gibt alle Zeilen zurück, die im Ergebnis von SELECT * FROM tabelle1, aber nicht im Ergebnis von SELECT * FROM tabelle2 enthalten sind. (Dies wird manchmal als Unterschied zwischen zwei Abfragen bezeichnet.) Auch hier werden Duplikate entfernt, sofern nicht EXCEPT ALL verwendet wird.

(SELECT * FROM tabelle1) EXCEPT (SELECT * FROM tabelle2)

Damit die Gegenüberstellung der beiden Ausgaben funktioniert, müssen beide Ausgaben die gleiche Anzahl an Zeilen haben und vom gleichen Datentyp sein.

Mehrfacheinträge in einer Tabelle finden

mehrfache.sql
DROP TABLE mehrfach_vorhanden;
CREATE TABLE mehrfach_vorhanden ( anzahl INT, zeile VARCHAR(10000) );
 
DO $$
DECLARE
        eine_zeile VARCHAR(10000);
BEGIN
        FOR eine_zeile IN
                SELECT name
                FROM liste
                GROUP BY 1
        LOOP
                INSERT INTO mehrfach_vorhanden SELECT COUNT(name), eine_zeile FROM kino WHERE name = eine_zeile;
        END LOOP;
END;
$$ LANGUAGE PLPGSQL;
 
DELETE FROM mehrfach_vorhanden WHERE ANZAHL = 1;
SELECT anzahl, zeile FROM mehrfach_vorhanden ORDER BY 1 ASC;

Am Ende werden in der zweiten Spalte alle mehrfach vorhandenen Einträge (Namen) und in der ersten Spalte die Anzahl dieser Einträge ausgegeben:

cat mehrfache.sql | psql -h 192.168.0.100 -p 5432 -U dbnutzer datenbank

Summierung von Spesenabrechnungen

So können beispielsweise die Gesamtausgaben (Spesen) jeder (mehrfach) eingetragenen Person leicht berechnet werden:

echo "SELECT SUM(ausgaben), name FROM spesen GROUP BY 2 ORDER BY 1 ASC;" | psql -h 192.168.0.100 -p 5432 -U buchhaltung db2019

PostgreSQL-Replikation (Cluster)

PgPool

/home/http/wiki/data/attic/datenbank/postgresql.1708789590.txt · Zuletzt geändert: von manfred