Oto krótka i przyjemna wersja wyrażenia „DO”:
DO $$
BEGIN
BEGIN
ALTER TABLE <table_name> ADD COLUMN <column_name> <column_type>;
EXCEPTION
WHEN duplicate_column THEN RAISE NOTICE 'column <column_name> already exists in <table_name>.';
END;
END;
$$
Nie możesz przekazać ich jako parametrów, musisz dokonać podstawienia zmiennych w ciągu znaków po stronie klienta, ale jest to samoistne zapytanie, które wysyła wiadomość tylko wtedy, gdy kolumna już istnieje, dodaje, jeśli nie, i będzie nadal kończyć się niepowodzeniem w przypadku innych błędów (takich jak nieprawidłowy typ danych).
Nie polecam wykonywania ŻADNEJ z tych metod, jeśli są to losowe ciągi pochodzące ze źródeł zewnętrznych. Bez względu na to, jakiej metody użyjesz (ciągi dynamiczne po stronie cleinta lub po stronie serwera, wykonywane jako zapytania), byłaby to recepta na katastrofę, ponieważ otwiera cię na ataki typu SQL injection.
DO $$ BEGIN BEGIN CREATE INDEX type_idx ON table1 USING btree (type); EXCEPTION WHEN duplicate_table THEN RAISE NOTICE 'Index exists.'; END; END;$$;
to samo podejście wCREATE INDEX
;) Dziękuję za odpowiedź,DO $$
kończy się niepowodzeniem. PróbowałemDO $$;
, ale to też się nie powiodło, dopóki nie zacząłem bloku,DO $$DECLARE r record;
który jest podany w przykładzie w dokumentach dev postgres .END; $$
jest błędem składniowym (Postgres 9.3), musiałem użyćEND $$;
zamiast tegoEXCEPTION
) jest nieco bardziej ogólne i można je zastosować do zadań, które nie mająIF NOT EXISTS
składni - na przykładALTER TABLE ... ADD CONSTRAINT
.W przypadku Postgres 9.6 można to zrobić za pomocą opcji
if not exists
źródło
ADD CONSTRAINT IF NOT EXISTS
jeszcze nie ma .Połączenie:
Zwraca
TRUE
po sukcesie, w przeciwnym razieFALSE
(kolumna już istnieje).Podnosi wyjątek dla nieprawidłowej nazwy tabeli lub typu.
Dlaczego inna wersja?
Można to zrobić za pomocą
DO
instrukcji, aleDO
instrukcje nie mogą niczego zwrócić. A jeśli jest do wielokrotnego użytku, utworzyłbym funkcję.Korzystać z rodzajów identyfikator obiektu
regclass
iregtype
w_tbl
i_type
którym a) zapobiega wstrzyknięciu SQL i b) kontroli ważności zarówno bezpośrednio (możliwe najtańszy sposób). Nazwa kolumny_col
nadal musi zostać oczyszczona zaEXECUTE
pomocąquote_ident()
. Więcej wyjaśnień w tej powiązanej odpowiedzi:format()
wymaga Postgres 9.1+. W przypadku starszych wersji połącz ręcznie:Możesz zakwalifikować nazwę swojej tabeli do schematu, ale nie musisz.
Identyfikatory w wywołaniu funkcji można umieszczać w cudzysłowach, aby zachować wielkość liter i słowa zastrzeżone (ale i tak nie należy ich używać).
Pytam
pg_catalog
zamiastinformation_schema
. Szczegółowe wyjaśnienie:Bloki zawierające
EXCEPTION
klauzulę, takie jak aktualnie zaakceptowana odpowiedź, są znacznie wolniejsze. Jest to ogólnie prostsze i szybsze. Dokumentacja:źródło
DO
instrukcji, jest niewielka modyfikacja do zaakceptowaniaDEFAULT
i to działało idealnie!Następujące zapytanie wyboru zwróci
true/false
, używającEXISTS()
funkcji.i użyj poniższej dynamicznej instrukcji SQL, aby zmienić tabelę
źródło
Dla tych, którzy używają Postgre 9.5+ (wierzę, że większość z was to robi), istnieje dość proste i czyste rozwiązanie
źródło
poniższa funkcja sprawdzi kolumnę, jeśli istnieje, zwróci odpowiednią wiadomość, w przeciwnym razie doda kolumnę do tabeli.
źródło
To jest w zasadzie rozwiązanie z Sola, ale tylko trochę wyczyszczone. Jest na tyle inny, że nie chciałem tylko „ulepszać” jego rozwiązania (plus, wydaje mi się, że to niegrzeczne).
Główną różnicą jest to, że używa formatu EXECUTE. Myślę, że jest to trochę czystsze, ale moim zdaniem oznacza, że musisz być na PostgresSQL 9.1 lub nowszym.
Zostało to przetestowane w wersji 9.1 i działa. Uwaga: zgłosi błąd, jeśli schemat / nazwa_tabeli / lub typ_danych są nieprawidłowe. To mogłoby „naprawić”, ale w wielu przypadkach może być poprawnym zachowaniem.
stosowanie:
źródło
Można dodać do migracji skrypty wywołują funkcję i upuszczają po zakończeniu.
źródło
W moim przypadku, ze względu na to, jak został stworzony, naszym skryptom migracji jest trochę trudno przeciąć różne schematy.
Aby obejść ten problem, użyliśmy wyjątku, który właśnie przechwycił i zignorował błąd. Miało to również przyjemny efekt uboczny polegający na tym, że był o wiele łatwiejszy do obejrzenia.
Należy jednak uważać, aby inne rozwiązania miały swoje zalety, które prawdopodobnie przeważają nad tym rozwiązaniem:
źródło
Możesz to zrobić postępując zgodnie z instrukcją.
Więc usunie kolumnę, jeśli już istnieje. A następnie dodaj kolumnę do konkretnej tabeli.
źródło
Po prostu sprawdź, czy zapytanie zwróciło nazwę_kolumny.
Jeśli nie, wykonaj coś takiego:
Gdzie umieścisz coś przydatnego dla 'x' i 'y' i oczywiście odpowiedni typ danych, w którym użyłem int.
źródło