Angenommen, ich habe einige benutzerdefinierte Typen in der Datenbank erstellt.
dh CREATE TYPE abc ...
Kann dann festgestellt werden, ob der benutzerdefinierte Typ vorhanden ist oder nicht? Vielleicht mit einer der Postgres-Informationstabellen?
Der Hauptgrund dafür ist, dass PostgreSQL nicht zu unterstützen scheint. CREATE OR REPLACE TYPE ...
Wenn ein bestimmter Typ mehr als einmal erstellt wird, möchte ich in der Lage sein, den vorhandenen zuerst zu löschen und dann den neuen neu zu laden.
Antworten:
Ich füge hier die vollständige Lösung zum Erstellen von Typen in einem einfachen Skript hinzu, ohne dass eine Funktion nur für diesen Zweck erstellt werden muss.
--create types DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'my_type') THEN CREATE TYPE my_type AS ( --my fields here... ); END IF; --more types here... END$$;
quelle
regtype
), also scheint es tatsächlich eine bessere Lösung zu sein. 8)Die einfachste Lösung, die ich bisher gefunden habe, um mit Schemata fertig zu werden, die von der Antwort von @ Cromax inspiriert wurden, ist folgende:
DO $$ BEGIN CREATE TYPE my_type AS (/* fields go here */); EXCEPTION WHEN duplicate_object THEN null; END $$;
Genau das, was Sie wirklich erwarten könnten - wir verpacken die Anweisung CREATE TYPE einfach in einen Ausnahmebehandler, damit die aktuelle Transaktion nicht abgebrochen wird.
quelle
EXCEPTION
hier bedeutet. Ist der Typ dann schon überladen oder kann ich ihn so verwenden wie er ist?Sie können in der
pg_type
Tabelle schauen :select exists (select 1 from pg_type where typname = 'abc');
Wenn das stimmt, dann
abc
existiert.quelle
select exists (select 1 from pg_type where typname = 'abc' and typnamespace = (select oid from pg_namespace where nspname = 'my_schema'))
. Ersetzen Sie 'my_schema' durch 'public', wenn Sie eine Einzelschemakonfiguration verwenden.In der Tat hat Postgres keine
CREATE OR REPLACE
Funktionalität für Typen. Der beste Ansatz ist es also, es fallen zu lassen:DROP TYPE IF EXISTS YOUR_TYPE; CREATE TYPE YOUR_TYPE AS ( id integer, field varchar );
Einfache Lösung ist immer die beste.
quelle
DROP
wird ein Fehler ausgegeben . Sie können jedochDROP ... CASCADE
auch abhängige Objekte löschen, wenn der Datenverlust in diesem speziellen Fall akzeptabel ist.Um das Dilemma von @ rog auf die Antwort von @ bluish zu lösen, könnte es angemessener sein, den
regtype
Datentyp zu verwenden. Bedenken Sie:DO $$ BEGIN PERFORM 'my_schema.my_type'::regtype; EXCEPTION WHEN undefined_object THEN CREATE TYPE my_schema.my_type AS (/* fields go here */); END $$;
PERFORM
Die Klausel ist wieSELECT
, aber sie verwirft die Ergebnisse. Im Grunde prüfen wir also, ob es möglich ist , den tatsächlich registrierten Typ umzuwandeln'my_schema.my_type'
(oder nur,'my_type'
wenn Sie nicht schemaspezifisch sein möchten). Wenn der Typ vorhanden ist, passiert nichts "Falsches" undRETURN
endet aufgrund des gesamten Blocks - keine Änderungen, da der Typmy_type
bereits vorhanden ist. Wenn die Besetzung jedoch nicht möglich ist, wird ein Fehlercode mit42704
der Bezeichnung " ausgelöst" ausgegebenundefined_object
. In den nächsten Zeilen versuchen wir, diesen Fehler abzufangen. In diesem Fall erstellen wir einfach unseren neuen Datentyp.quelle
-- All of this to create a type if it does not exist CREATE OR REPLACE FUNCTION create_abc_type() RETURNS integer AS $$ DECLARE v_exists INTEGER; BEGIN SELECT into v_exists (SELECT 1 FROM pg_type WHERE typname = 'abc'); IF v_exists IS NULL THEN CREATE TYPE abc AS ENUM ('height', 'weight', 'distance'); END IF; RETURN v_exists; END; $$ LANGUAGE plpgsql; -- Call the function you just created SELECT create_abc_type(); -- Remove the function you just created DROP function create_abc_type(); -----------------------------------
quelle
Ich versuche das Gleiche zu tun und sicherzustellen, dass ein Typ existiert.
Ich habe psql mit der Option
--echo-hidden
(-E
) gestartet und Folgendes eingegeben\dT
:$ psql -E psql (9.1.9) testdb=> \dT ********* QUERY ********** SELECT n.nspname as "Schema", pg_catalog.format_type(t.oid, NULL) AS "Name", pg_catalog.obj_description(t.oid, 'pg_type') as "Description" FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) AND n.nspname <> 'pg_catalog' AND n.nspname <> 'information_schema' AND pg_catalog.pg_type_is_visible(t.oid) ORDER BY 1, 2; ************************** List of data types Schema | Name | Description --------+------------------+------------- public | errmsg_agg_state | (1 row)
Wenn Sie Schemas und search_path verwenden (ich bin es), müssen Sie wahrscheinlich die
pg_catalog.pg_type_is_visible(t.oid)
Prüfung behalten . Ich weiß nicht, was alle Bedingungen im WO tun, aber sie schienen für meinen Fall nicht relevant zu sein. Derzeit verwendet:SELECT 1 FROM pg_catalog.pg_type as t WHERE typname = 'mytype' AND pg_catalog.pg_type_is_visible(t.oid);
quelle
Eine allgemeinere Lösung
CREATE OR REPLACE FUNCTION create_type(name text, _type text) RETURNS integer AS $$ DECLARE v_exists INTEGER; BEGIN SELECT into v_exists (SELECT 1 FROM pg_type WHERE typname = name); IF v_exists IS NULL THEN EXECUTE format('CREATE TYPE %I AS %s', name, _type); END IF; RETURN v_exists; END; $$ LANGUAGE plpgsql;
und dann können Sie es so nennen:
select create_type('lwm2m_instancetype', 'enum (''single'',''multiple'')');
quelle
Eine andere Alternative
WITH namespace AS( SELECT oid FROM pg_namespace WHERE nspname = 'my_schema' ), type_name AS ( SELECT 1 type_exist FROM pg_type WHERE typname = 'my_type' AND typnamespace = (SELECT * FROM namespace) ) SELECT EXISTS (SELECT * FROM type_name);
quelle
Dies funktioniert gut mit Schemas und vermeidet die Ausnahmebehandlung:
DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_type t LEFT JOIN pg_namespace p ON t.typnamespace=p.oid WHERE t.typname='my_type' AND p.nspname='my_schema' ) THEN CREATE TYPE my_schema.my_type AS (/* fields go here */); END IF; END $$;
quelle