Mit CONSTRAINT als SELECT ERSTELLEN?

7

Ich habe ein Stück SQLdavon erstellt eine TABLEForm eine SELECTAnweisung in PostgreSQL; Ich möchte der Tabelle Einschränkungen hinzufügen, damit beispielsweise eine Spalte nicht vorhanden sein kann null.

Ich kann dafür kein gültiges SQL in der Postgres-Dokumentation finden, daher scheint es nicht möglich zu sein.

Was wäre der beste Ansatz, um diese Art von Funktionalität zu erreichen? Ich möchte, dass die Erstellung der Tabelle fehlschlägt, wenn die Einschränkung verletzt wird.

Ich kann die Tabelle mit der Einschränkung nicht im Voraus erstellen, da einige Spalten möglicherweise variieren, da sie das Ergebnis eines dynamischen Prozesses sind.

RobAu
quelle

Antworten:

10

Eine Variation der Antwort von @ a_horse_with_no_name besteht darin, zuerst die Tabelle mit der Einschränkung zu erstellen und dann in die Tabelle einzufügen, wobei immer noch eine Transaktion verwendet wird, sodass bei Verstößen gegen die Einschränkung alles zurückgesetzt wird. Dies sollten Sie berücksichtigen, wenn die einzufügenden Zeilen viel sind (dh Hunderttausende oder Millionen).

Wenn es schwierig ist, die create tableAnweisung dynamisch zu erstellen , können Sie diesen Teil in zwei Anweisungen unterteilen:

begin transaction ;
    create table new_table                       -- create the table
    as
    select v.*
    from (select ....) as v                      -- as before
    where false ;                                -- but insert 0 rows

    alter table new_table add constraint ... ;   -- add the constraint

    insert into new_table                        -- and then attempt
    select ... ;                                 -- the insert
end ;

Der Unterschied zur anderen Methode besteht darin, dass die Einschränkung vorhanden ist, bevor eine Zeile in die Tabelle eingefügt wird. Und da NOT NULLund CHECKEinschränkungen nicht aufschiebbar sind, sondern immer sofort überprüft werden, wenn eine Zeile eingefügt oder geändert wird (und nicht am Ende der Anweisung), schlägt Ihre Einfügeanweisung mit der ersten Zeile, die gegen die Einschränkung (en) verstößt, fehl (und wird zurückgesetzt) platziert haben.

Wenn Sie mehrere Millionen Zeilen einfügen, ist dies schneller, sowohl weil ein Fehler möglicherweise schneller gefunden wird, als auch weil weniger Einfügungen rückgängig gemacht werden müssen.

ypercubeᵀᴹ
quelle
2
Sehr guter Punkt
a_horse_with_no_name
5

Sie müssen dies mit zwei Anweisungen tun:

create table new_table
as
select ....;

alter table new_table add constraint ...;

Stellen Sie sicher, dass Sie dies in einer einzelnen Transaktion ausführen (z. B. indem Sie das automatische Festschreiben in Ihrem SQL-Client deaktivieren oder mit einem umschließen begin transaction ...

Wenn dies alter tablefehlschlägt, können Sie alles zurücksetzen und die Tabelle ist ebenfalls verschwunden.

ein Pferd ohne Name
quelle