mysql ma fajną rzecz – drop table if exists.
pozwala to na pisanie bezpiecznych skryptów sql'owych które nawet przy obudowaniu w transakcję się prawidłowo wykonają.
przykład?
załóżmy, że chcemy stworzyć tabelę i cośtam jeszcze zrobić – wszystko w transakcji.
BEGIN; CREATE TABLE test (x serial PRIMARY KEY, test_value TEXT); ... COMMIT;
wygląda niewinnie.
no tak, ale co jeśli ta tabela już istnieje – bo np. ktoś ma zainstalowaną wcześniejszą wersję bazy? trywiał zmieniamy na:
BEGIN; DROP TABLE test; CREATE TABLE test (x serial PRIMARY KEY, test_value TEXT); ... COMMIT;
i już działa.
ale nie. jeśli jednak odpalimy tego sql'a na bazie w której naszej tabeli nie ma – drop table sie nie uda, więc cała transakcja zostanie zrollbackowania.
no cóż, to może tak?
DROP TABLE test; BEGIN; CREATE TABLE test (x serial PRIMARY KEY, test_value TEXT); ... COMMIT;
teraz – drop jest poza transakcją, więc jak się wywali to nie problem.
hmm .. ale co jeśli tabela test jest, ale nasze zapytania po create table się wywalą? tabela test zostanie permanentnie skasowana, a polecenie zakładające zostanie zrollbackowane. tragedia.
czy nie da się tego sensownie zrobić? da się.
trzeba użyć funkcji execute() o której pisałem wczoraj.
dzięki niej, mogę zrobić swojego sql'a tak:
BEGIN; SELECT EXECUTE('DROP TABLE test') WHERE EXISTS (SELECT * FROM information_schema.tables WHERE table_schema = 'public' AND TABLE_NAME = 'test'); CREATE TABLE test (x serial PRIMARY KEY, test_value TEXT); COMMIT;
i uzyskuję w ten sposób funkcjonalny odpowiednik DROP TABLE … IF EXISTS;
oczywiście składnia jest trudniejsza, ale nie wydaje się to być dużym problemem – jeśli jest – no cóż. zawsze można napisać własną funkcję która zrobi ‘drop table' tylko jeśli tabela istnieje. ale wykorzystanie ogólnego mechanizmu ‘execute' wydaje się być zdecydowanie potężniejsze
w sam raz jako dodatek do http://pgfoundry.org/projects/mysqlcompat/ 🙂
Polecenie “DROP TABLE … IF EXISTS” jest juz zaimplementowane w wersji 8.2 PostgreSQL.
W MySQL nie jest jeszcze aż tak różowo, ponieważ, jak dotąd, wykonanie DROP TABLE implikuje automagiczne zamknięcie (commit) aktywnej transakcji.