T-SQL "re-runnable" aktualizace databáze skripty - vypuštění sloupec

hlasů
1

Pro databázi SQL Server, používáme systém verzí sledovat aktualizace schématu. Myšlenka je to, že byste měli být schopni spustit tento skript, aby schéma z jakékoliv předchozí verze až na aktuální verzi. Spuštění hlavního skriptu opět by měl plnit pouze nejnovější aktualizace schématu.

Struktura skriptu je takhle:

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=0
 IF (@Installed IS NULL)
 BEGIN
    ...
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 0, GetDate())
 END
 ELSE PRINT 'Version 1.0.0 was already installed on ' + Convert(varchar(10), @Installed)  

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=1
 IF (@Installed IS NULL)
 BEGIN
    ...
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 1, GetDate())
 END
 ELSE PRINT 'Version 1.0.1 was already installed on ' + Convert(varchar(10), @Installed)

To obvykle funguje velmi dobře. Nicméně, jsme narazili na problém, když se aktualizace schématu klesne sloupec, který je obsažen v předcházejícím INSERT ignorovat; to znamená, že máme něco takového:

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=0
 IF (@Installed IS NULL)
 BEGIN
    INSERT IGNORE  [foo] ([a], [b], [OrganizationId]) VALUES (N'a', N'b', N'1');
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 0, GetDate());
 END
 ELSE PRINT 'Version 1.0.0 was already installed on ' + Convert(varchar(10), @Installed)  

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=1
 IF (@Installed IS NULL)
 BEGIN
    ALTER TABLE [foo] DROP COLUMN [OrganizationId];
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 1, GetDate());
 END
 ELSE PRINT 'Version 1.0.1 was already installed on ' + Convert(varchar(10), @Installed)

Tato metoda funguje spolehlivě na prvním místě je proveden; Verze 1.0.1 je vykonán, a kolona se poklesl. Však spuštění skriptu podruhé výnosy:

    Msg 207, úroveň 16 stav 1, řádek 7118
    Neplatný sloupec název ‚OrganizationId‘.

To znamená, že i když INSERT IGNORE uvnitř verze 1.0.0 bloku není prováděn, je to stále analyzován a generování chybu neplatné sloupce.

Nějaké návrhy na to, jak tento problém vyřešit? V ideálním případě bych chtěl chránit INSERT IGNORE se podmíněný, takže to není ani analýzu, ale to se nezdá být pravda. Mohl bych dynamicky provádět INSERT IGNORE je uvnitř sp_executesql () volá, ale já bych přednost tomu, aby (by vyžadovalo hodně dovybavení).

Dík --

--Andy

Položena 27/08/2009 v 01:51
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
1

Ok, jsem mis-číst otázku zpočátku. :-)

Pokud změníte vložce linky od:

INSERT IGNORE  [foo] ([a], [b], [OrganizationId]) VALUES (N'a', N'b', N'1');

na:

exec('INSERT IGNORE  [foo] ([a], [b], [OrganizationId]) VALUES (''a'', ''b'', ''1'')');

Neměli byste mít tento problém, protože SQL „text“ uvnitř exec nebude analyzován až exec () je vlastně volal.

Odpovězeno 27/08/2009 v 02:40
zdroj uživatelem

hlasů
1

Bohužel toto je podobný problém, dostanete, když (uvnitř uložené proc) pustíte dočasné tabulky a poté jej znovu. Analyzátor bude stěžovat, že již existuje, není zdálo se, že si uvědomit, že dočasná tabulka byla právě zrušena.

Pokud ji oddělit s GO prohlášení, pak byste měli najít systém přehodnotí každý oddíl, jak to přijde k němu.

Okrást

Odpovězeno 27/08/2009 v 02:08
zdroj uživatelem

hlasů
0

Už jste vyzkoušeli dynamické SQL? Je smutné, že parser bude kontrolovat celý skript před jeho spuštěním, takže jakýkoli neplatný sloupec se zastavily popravy.

Odpovězeno 27/08/2009 v 02:22
zdroj uživatelem

hlasů
0

Používáme téměř identické nastavení řešit verzování schématu.

Obecně platí, že váš přístup je zcela v pořádku. Byli jsme běží s tímto obecným nastavením po dobu několika let. V podstatě zvládnout případné destruktivní nebo non-kompatibilní změny schématu, narazíme náplasti jako součást automatizovaného CruiseControl.NET stavět.

Takže naše databáze build vypadá takto ...

  • Obnovení z aktuální zálohy produkční verze.
  • Zkontrolujte, zda verze obnovené DB
  • Spustit všechny záplaty (ty jsou pojmenovány podle konvence s využitím major.minor.sql), které jsou novější než verze uvedené v [Versions] tabulky.

Tímto způsobem můžeme přestavět celý den bez problémů bez ohledu na to, co dělá náplast. To také zaručuje, že když jsme se nasadit do výroby nejsou žádné problémy, protože jsme již bylo nasazeno více než při výrobě db 1000x během vývoje.

Odpovězeno 27/08/2009 v 02:12
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more