2012-05-24 10 views
6

Pracuję nad opartą na języku Java aplikacją OSS SqlHawk, która jako jedna z jego funkcji służy do uruchamiania skryptów aktualizacji sql na serwerze.Jak mogę obsługiwać instrukcję SQL GO w aplikacji Java/jtds?

Firma Microsoft stworzyła konwencję dzielenia skryptu na partie za pomocą instrukcji GO, co jest dobrym pomysłem, ale po prostu pytaniem o fałszywe dopasowania w łańcuchu.

W tej chwili mam bardzo prymitywny:

// split where GO on its own on a line 
Pattern batchSplitter = Pattern.compile("^GO", Pattern.MULTILINE); 
... 
String[] splitSql = batchSplitter.split(definition); 
... 

jaki rodzaj robót, ale ma skłonność do bycia potknął się o takie rzeczy jak quoted GO statements lub wgniecenia zagadnień.

Myślę, że jedynym sposobem, aby uczynić to naprawdę wiarygodnym, jest zastosowanie parsera SQL w aplikacji, ale nie mam pojęcia, jak to zrobić, lub czy w rzeczywistości może się to okazać mniej wiarygodne (zwłaszcza biorąc pod uwagę to narzędzie obsługuje wiele DBMS).

Jak mogę rozwiązać ten problem? Przykłady kodu byłyby bardzo pomocne dla mnie tutaj.

Relevant sqlHawk code na github.

Obecnie używa się jtds do wykonywania partii znalezionych w skryptach.

+1

Zrobiłem to po swojemu, gdy musiałem zrobić coś podobnego. Jest używany tylko wewnętrznie i działa dobrze dla nas. – brain

+1

Idem tutaj ... To daleki od głupich dowodów i musisz zdecydować, czy chcesz wspierać takie rzeczy jak "GO 100". Główną przeszkodą jest IMHO, gdy GO jest częścią/* bloku komentarza * /. Te wymagają sporo dodatkowego przetwarzania. (najpierw usuń wszystkie komentarze i blok komentarzy, a następnie podziel się tym, co zrobiliśmy) PS: Możesz poprzedzić kod przez 'SET PARSEONLY ON' i jeśli nie ma" Niepoprawnej składni w pobliżu GO ", nie ma potrzeby dzielenia kod ... w przeciwnym razie możesz użyć lokalizacji linii wskazanej przez błąd, aby "wskazać, gdzie podzielić na" GO "... może działać, czuje się bardziej złożony niż potrzebny ... – deroby

+0

przykład komplikować rzeczy: 'EXEC ('SET PARSEONLY ON, SELECT * FROM t_entity; GO; PRINT 0')' – deroby

Odpowiedz

1

GO to polecenie seperatora wsadowego klienta. Możesz go zastąpić;. Nie powinien być wysyłany w dynamicznym SQL EXEC.

USE master 
GO --<----- client actually send the first batch to SQL and wait for a response 
SELECT * from sys.databases 
GO 

powinny być przetłumaczone w

Application.Exec("USE master"); 
Application.Exec("SELECT * from sys.databases"); 

lub można napisać to w ten sposób:

Application.Exec("'USE master;SELECT * from sys.databases") 

Więcej o GO http://msdn.microsoft.com/en-us/library/ms188037(v=sql.90).aspx

+0

Dzięki, ale to nie daje mi żadnych wskazówek, jak mogę niezawodnie wykonać podział w Javie. Myślę, że masz rację co do EXEC, ale nie sprawdziłem. –

1

OK, więc to nie będzie być dokładnie co chcesz, ale ty mig To początek. Wydałem SchemaEngine (który stanowi rdzeń większości moich produktów) jako open source here. Tam znajdziesz kod C#, który robi to, co chcesz bardzo niezawodnie (tj. Nie potknie się o ciągi, komentarze itp.). Obsługuje również składnię "GO x", aby powtórzyć serię x razy.

Jeśli pobierzesz i zaglądniesz na stronę /Atlantis.SchemaEngine/Helpers, znajdziesz klasę o nazwie BatchParser.cs, która zawiera metodę o nazwie ParseBatches - która w zasadzie przypomina to, co napisano na puszce.

Powiązane problemy