2012-05-24 1 views
6

Sto lavorando a un'app OSS basata su Java SqlHawk che, come una delle sue funzionalità, è eseguire script sql di aggiornamento su un server.Come posso supportare l'istruzione SQL GO in un'applicazione Java/jtds?

Microsoft ha creato una convenzione per dividere uno script in batch con l'istruzione GO, che è una buona idea ma richiede solo false corrispondenze sulla stringa.

Al momento ho una molto rudimentale:

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

quale tipo di opere, ma è incline ad essere scattato da cose come quoted GO statements o di rientro problemi.

Penso che l'unico modo per renderlo veramente affidabile sia avere un parser SQL nell'app, ma non ho idea di come procedere, o se possa effettivamente risultare meno affidabile (specialmente dato questo strumento supporta più DBMS).

In che modo è possibile risolvere questo problema? Gli esempi di codice mi sarebbero molto utili qui.

Relevant sqlHawk code su github.

Attualmente si utilizza jtds per eseguire i batch trovati negli script.

+1

Ho fatto a modo tuo quando dovevo fare una cosa simile. È usato solo internamente e funziona bene per noi. – brain

+1

Idem qui ... È tutt'altro che infallibile e devi decidere se vuoi supportare cose come "GO 100". L'ostacolo principale IMHO è quando il GO fa parte di un blocco di commenti/* * /. Questi richiedono un po 'di elaborazione extra. (elimina prima tutti i commenti e il blocco dei commenti, quindi la divisione è ciò che abbiamo fatto) PS: puoi prefisso il codice con 'SET PARSEONLY ON 'e se non c'è' Sintassi errata vicino a GO 'non è necessario dividere il codice .. altrimenti si potrebbe usare il percorso di linea indicato dall'errore per 'individuare dove dividere su un GO' ... potrebbe funzionare, si sente più complesso del necessario anche se ... – deroby

+0

esempio per complicare le cose: 'EXEC ('SET PARSEONLY ON; SELECT * FROM t_entity; GO; PRINT 0')' – deroby

risposta

1

GO è un comando seperatore batch client. Puoi sostituirlo con; Non dovrebbe essere inviato nel tuo SQL dinamico EXEC.

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

dovrebbe essere tradotto in

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

oppure si può scrivere in questo modo:

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

più su GO http://msdn.microsoft.com/en-us/library/ms188037(v=sql.90).aspx

+0

Grazie, ma questo non mi dà alcun indizio su come potrei eseguire in modo affidabile lo split in Java. Penso che tu abbia ragione su EXEC ma non ho controllato. –

1

Ok, quindi questo non sta andando essere esattamente quello che vuoi, ma tu mig lo trovo un inizio. Ho rilasciato SchemaEngine (che costituisce il nucleo della maggior parte dei miei prodotti) come open source here. Lì troverai il codice C# che fa ciò che vuoi in modo affidabile (cioè non inciampare con stringhe, commenti ecc. Ecc.). Supporta inoltre la sintassi 'GO x' per ripetere un batch x volte.

Se lo scarichi e dai un'occhiata a /Atlantis.SchemaEngine/Helpers troverai una classe chiamata BatchParser.cs che contiene un metodo chiamato ParseBatches - che fa praticamente quello che dice sullo stagno.