February 12th, 2007 by depesz | Tags: | 3 comments »
Did it help? If yes - maybe you can help me?

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

  1. 3 comments

  2. # cezio
    Feb 12, 2007

    w sam raz jako dodatek do http://pgfoundry.org/projects/mysqlcompat/ 🙂

  3. # slaweks
    Feb 13, 2007

    Polecenie “DROP TABLE … IF EXISTS” jest juz zaimplementowane w wersji 8.2 PostgreSQL.

  4. # Maciek Dobrzański
    Feb 15, 2007

    W MySQL nie jest jeszcze aż tak różowo, ponieważ, jak dotąd, wykonanie DROP TABLE implikuje automagiczne zamknięcie (commit) aktywnej transakcji.

Leave a comment