Segnalo che sul "sempre ottimo" sito http://www.sqlservercentral.com/ ieri e' stato pubblicato un elenco delle build di Sql 2005, una di quelle cose che, quando ne ho bisogno, non ricordo mai dove trovare 
L'elenco lo trovate qui: http://www.sqlservercentral.com/articles/Administration/2960/
Buone news per i Sassisti in ascolto che lavorano in SqlServer: nella versione Sql2008 saranno presenti due funzionalita' che ricordano molto da vicino cio' che si ha (da illore tempo) a disposizione in SAS.
Mi riferisco allo statement MERGE che consente, in un singola operazione atomica, di effettuare Insert, Delete ed Update su una tabella target sulla base dei dati presenti in una tabella source.
E' qualcosa che consente facilmente in Sql di effettuare quelle operazioni di aggiornamento che si fanno in un data step SAS con lo statement merge [stesso nome, appunto
] e l'opzione IN dei dataset.
Ecco un esempio di come aggiornare le informazioni presenti nella tabella Attivita sulla base di quelle presenti nella tabella UpdAttivita
/* setup test */
use tempdb
go
create table dbo.Attivita (Id int, Label varchar(20),Durata int);
go
create table dbo.UpdAttivita (Id int, Label varchar(20),Durata int);
go
insert into dbo.Attivita values (1,'Alfa',120),(2,'Beta',200),(3,'Gamma',80);
insert into dbo.UpdAttivita values (4,'Echo',10),(2,'Beta',210),(3,'GammaNew',801);
/* applico le variazioni */
merge into dbo.Attivita AS TGT
using dbo.UpdAttivita AS SRC
on TGT.id = SRC.id
when MATCHED then
update set
TGT.label = SRC.label,
TGT.durata = SRC.durata
when NOT MATCHED then
insert (id, label, durata)
values (SRC.id, SRC.label, SRC.durata)
when SOURCE NOT MATCHED then
delete
;
/* verifica */
select * from dbo.Attivita;
Per i curiosi in SAS, in questo caso, bastava scrivere:
data
Attivita;
merge Attivita (in=a) UpdAttivita(in=b);
by Id;
if a and not b then delete;
run
;
Che in effetti e' un po' piu' compatto 
L'altra funzionalita' introdotta e' quella dei GROUPING SETS che ci fanno ritrovare praticamente "pari pari" la Proc Summary all'interno di SqlServer.
Appoggiandosi a tale funzionalita' possiamo ottenere, con un unica query, piu' raggruppamenti, uno per ogni combinazione dei campi indicati nell'istruzione Grouping Sets del Group By che diviene l'equivalente dell'istruzione CLASS della Proc Summary.
Ad esempio se volessimo, in un colpo solo, la somma delle vendite della tabella Vendite sia per IdProdotto che per PuntoVendita insieme alle somme per ogni combinazione di PuntoVendita e IdProdotto ed anche il Totalone con i Grouping Sets possiamo scrivere:
use tempdb
go
-- creazione tabella di esempio
if OBJECT_ID ('dbo.Vendite') is not null drop table dbo.Vendite;
create table dbo.Vendite (
PuntoVendita varchar(20),
IdProdotto int,
Quantita int
);
go
-- inserimento dati esempio
insert into dbo.Vendite (PuntoVendita,IdProdotto,Quantita)
Values
('Milano',1,120),
('Milano',2,124),
('Milano',3,210),
('Roma',1,300),
('Roma',2,155),
('Roma',3,38),
('Napoli',2,35)
;
/* calcolo i vari totali */
select PuntoVendita, IdProdotto, SUM(Quantita) as Quantita
from dbo.Vendite
group by
GROUPING Sets(
(),
(PuntoVendita ),
(IdProdotto),
(PuntoVendita,IdProdotto )
)
order by PuntoVendita , IdProdotto
;
Per gli interessati l'equivalente SAS sarebbe:
proc Summary data = Vendite print sum;
var Quantita;
class PuntoVendita IdProdotto ;
run;
Mi piacciono, si mi piacciono veramente molto queste nuove possibilita' di Sql2008 
Ieri ho litigato con Virtual PC (versione 6.0) che, senza una ragione apparente, non presentava piu' la finestra di console: l'icona stava "comodamente" funzionante nella system tray, ma se cliccavo due volte o chiedevo di vedere la console... Nisba
Roba da non crederci!!
Dopo un po' di fatica (e la solita mezz'ora buttata) con santo Google la soluzione mi e' stata fornita da questo post http://marcellotonarelli.wordpress.com/2007/06/02/show-microsoft-virtual-pc-2007-console/ di Marcello Tonarelli (GRAZIE).
Pari pari dal suo blog riporto la soluzione al fastidioso problema:
Dare un occhio al file di configurazione
C:\Documents and Settings\__Name_Of_Your_Windows_Account__\Application\Data\Microsoft\Virtual PC\Options.xml
e verificare che i valori delle dimensioni e della posizione per la sezione <console> "abbiano senso" (io mi ritrovavo la left e right position con valori stellari invece di un sano 0).
Buoni valori sono ad esempio:
<console>
<height type=”integer”>575</height>
<left_position type=”integer”>0</left_position>
<top_position type=”integer”>0</top_position>
<visible type=”boolean”>true</visible>
<width type=”integer”>359</width>
</console>
Morale (la solita):
in rete c'e' un mucchio di gente che ti da una mano e ci consente di sopravvivere con le bizze del software 
In questi giorni parlando con vari utenti ho realizzato che, a volte, c'e' un po' di confusione in merito alla possibilita' di avere transazioni annidate in Sql Server.
Forse vale la pena di fare un po' di chiarezza: SqlServer NON supporta "Transazioni Annidate".
In altre parole per ciascuna connessione puo' esistere solo una transazione attiva.
E il fatto che sia possibile (almeno sintatticamente) sottomettere piu' statement BEGIN TRANSACTION complica e confonde le cose 
In realta' ogni volta che viene sottomesso un BEGIN TRAN SqlServer semplicemente incrementa un contatore interno il cui valore e' recuperabile con una select sulla funzione @@trancount.
Ad ogni commit il valore di @@trancount diminuisce di un unita' e solo l'ultimo commit (che riporta @@trancount a zero) committa realmente la transazione.
In compenso qualunque rollback provoca l'annullamento di tutte le operazioni a partire dal primo begin tran (ovvero viene annullata la transazione piu' esterna).
Pertanto sottomettendo il seguente codice:
begin
tran;
insert into Test values (1);
begin tran;
insert into Test values (2);- rolback di tutto (anche l'insert col valore 1)
rollback;
-- questo commit da errore: la transazione e' chiusa
commit;
Nella tabella Test non verra' inserito alcun valore, in quanto il primo rollback cancella tutte le attivita' iniziate con la transazione piu' esterna.
Inoltre, per committare davvero, bisogna prestare attenzione a sottomettere un numero di COMMIT uguale al numero di BEGIN TRAN (@@trancount) altrimenti si rischia di lasciare aperta la transazione con tutti i pericoli di lock che seguono.
Attenzione che ci sono situazioni (ad esempio se l'utente ha dato un cancel) in cui, anche se viene generato un errore, non viene chiusa la transazione
Pertanto e' buona norma verificare se ci sono transazioni attive prima di risottomettere nuovamente un BEGIN TRAN e trovarsi con qualche "parentesi non chiusa" 
Mi accodo anch'io al post di Andrea e riporto la mia top five: forse non sono le novita' piu' eclatanti, ma ripensando alla mia attivita' in Sql degli ultimi tempi quelle che seguono sono le cose che piu' mi mancavano...
-
Statement MERGE
-
Date & Time datatypes
-
Table-Valued parameters
-
Grouping Sets
-
Transparent Data Encryption
e la 5 + 1 e' il Change Data Capture
e la 6 +1 e' il Resource Governor ... e la 7 +1 ... 
Come comunicato nel blog della Delaney http://sqlblog.com/blogs/kalen_delaney/archive/2008/01/19/did-you-know-a-terrific-new-community-website.aspx in rete e' nato un nuovo sito dedicato a risorse tips & tricks per Sql Server.
Il sito e' questo: http://www.sqlcommunity.com
Da un primo occhio mi sembra valido, vediamo se col tempo manterra' le promesse.
Spesso si sente dire che determinate operazioni (il truncate, per esempio) NON vengono loggate in Sql... Tale affermazione e’ da prendere “con le pinze” in quanto e’ quasi sempre falsa. 
Sql Server (almeno in recovery model FULL o BULK_LOGGED) logga tutte le operazioni che vengono effettuate sui dati e sugli oggetti del database in quanto, altrimenti, non potrebbe, durante il restoring, ricostruire correttamente e completamente lo stato del database.
Se mai quello che cambia e’ il modo in cui l’operazione viene loggata, ovvero quali informazioni vengono registrate nel log.
Un esempio “esemplare” di cio’ ci e’ proprio fornito dall’istruzione TRUNCATE: in questo caso SQL non ha la necessita’ di loggare ogni singolo delete (che in effetti non viene compiuto), ma registrera’ la singola operazione truncate (che corrisponde al deallocamento delle pagine su cui sono memorizzati i dati della tabella).
Questo “minimum logging” consente comunque a Sql di garantire la transazionalita’ dell'esecuzione e la possibilita' del restore.
Pertanto anche l'istruzione TRUNCATE puo' essere eseguita all’interno di una transazione e subisce la fase di Redo durante il restore.
Potete verificare facilmente entrambe le cose con il seguente codice.
USE [master]
GO
-- Creazione db e tabelle di test
IF
EXISTS (SELECT name FROM sys.databases WHERE name = N'TestTruncate')DROP DATABASE TestTruncate
GO
CREATE
DATABASE TestTruncate ON PRIMARY
( NAME = N'TestTruncate', FILENAME = N'C:\Temp\TestTruncate.mdf' ,
SIZE = 5MB , MAXSIZE = UNLIMITED, FILEGROWTH = 1MB )
LOG ON ( NAME = N'TestTruncate_log', FILENAME = N'C:\Temp\TestTruncate_log.ldf' ,
SIZE = 1MB , MAXSIZE = UNLIMITED, FILEGROWTH = 1MB)
GO
-- setto il recovery model a FULL
alter
database TestTruncate set recovery Full;
GO
use TestTruncate
go
-- Creo la tabella (con un campo identity) e inserisco dei record
create
table dbo.ForTruncateExample
(
Codice int identity (1,1),
Valore
varchar(10))
go
insert
into dbo.ForTruncateExample values ('Alfa');
insert
into dbo.ForTruncateExample values ('Beta');
select
* from dbo.ForTruncateExample;
-- truncate sotto transazione
begin tran;
truncate table dbo.ForTruncateExample ;
-- non ci sono piu' valori
select * from dbo.ForTruncateExample;
rollback;
-- la truncate e' stata "rollbackata" !!
select * from dbo.ForTruncateExample;
-- verifico che anche l'identity continua a funzionare
insert
into dbo.ForTruncateExample values ('Gamma');select * from dbo.ForTruncateExample;
-- backup dati
backup
database TestTruncate to disk = 'c:\temp\TestTruncate_FULL01.bck' with init;
-- Effettuo la truncate e poi backupp il log
truncate
table dbo.ForTruncateExample ;
backup
log TestTruncate to disk = 'c:\temp\TestTruncate_Log01.bck' with init;
-- restore Dati + Log
use
master;
go
restore
database TestTruncate from disk = 'c:\temp\TestTruncate_FULL01.bck' with NORECOVERY , REPLACE;
restore
log TestTruncate from disk = 'c:\temp\TestTruncate_Log01.bck' with RECOVERY;
-- la tabella e' troncata
select
* from TestTruncate.dbo.ForTruncateExample;
Ulteriori interessanti notizie sulla TRUNCATE (e sulle differenze con la DELETE) le trovate in questo articolo http://www.sqlservercentral.com/links/335083/14505
Posto una particolarita' del comportamento del file di log la cui utilita' pratica rasenta lo zero, ma puo' essere utilizzata per vincere un caffe' facendo una scommessa
Domanda: e' possibile che un database in cui vengono effettuate numerose operazioni di scrittura, settato in modalita'di recovery FULL e per cui non venga mai effettuato un backup del log non presenti un aumento delle dimensioni del suo file di log (o per lo meno esso non tenda ad "esplodere") ?
Risposta: (sorprendente): SI.
Capita in una condizione piuttosto particolare: se non e' mai stato effettuato un backup completo dei dati da quando il database e' in recovery model FULL.
Questo e' dovuto al fatto che, in realta', la condizione che il log "non cresca", ovvero che recuperi via via lo spazio utilizzato dalle transazioni committate ed effettivamente scritte nel database (truncation del log) non e' legata "esattamente" al modello di recovery
, ma piu' precisamente al fatto che SQL Server abbia dedotto che, per quel database, non viene mantenuta una sequenza di backup del log.
In altre parole, se SQL capisce che non abbiamo intenzione di utilizzare il log nella nostra strategia di backup-restore, correttamente non si preoccupa (se ne frega...) di salvare le transazioni gia' scritte nel database (dato che non ci servono per il restore) e recupera appena puo', con un bel truncate, lo spazio a loro allocato.
Ok, e quando SQL puo' essere sicuro che non ci interessa il restore dal log ??? Nei seguenti tre casi:
e, dulcis in fundo...
Eh, si, c'e' poco da fare SqlServer e' ... furbo !! 
PS: vi interessa sapere (in Sql2005) quali database sono in questa situazione (ovvero in autotruncate mode) ? Lo vedete da questa select:
SELECT
db_name(database_id)
FROM sys.database_recovery_status
WHERE
last_log_backup_lsn is NULL
Ho modificato uno script pubblicato dalla Delaney per farmi restituire, per tutti i database, le dimensioni dei dati, del file di log, la sua % di occupazione ed il modello di recovery attivo.
Lo script, valido per Sql2005, e' veramente semplice, ma potrebbe comunque essere utile per cui eccolo.
/* restituisce per tutti i database le dimensioni dei dati, del log la % di occupazione del log ed il modello di recovery */
select
rtrim (pc1.instance_name) as [Database Name],
pc3
.cntr_value/1024.0 as [Data Size (MB)],
pc1
.cntr_value/1024.0 as [Log Size (MB)],
cast (pc2.cntr_value*100.0/pc1.cntr_value as dec (5,2)) as [Log Space Used (%)],db.recovery_model_desc
from
sys.dm_os_performance_counters as pc1,
sys.dm_os_performance_counters as pc2,
sys.dm_os_performance_counters as pc3,sys.databases as db
where pc1.instance_name = pc2.instance_name
and pc1.instance_name = pc3.instance_nameand pc1.instance_name = db.name
and pc1.counter_name = 'Log file(s) Size (KB)'
and pc2.counter_name = 'Log file(s) Used Size (KB)'
and pc3.counter_name = 'Data File(s) Size (KB)'and pc1.cntr_value > 0
order by pc1.instance_name;
In merito al recovery model SIMPLE spesso girano dubbi e spesso capita di sentirsi chiedere cosa logga e se le sue dimensioni crescono e perche' crescono e quando si "sgonfia" etc etc. Sperando di fare cosa utile in questo post provero' a fare un po' di chiarezza in merito...
Innazitutto chiariamo che una modalita' di logging SIMPLE non significa che non loggo ... Tutt'altro: SIMPLE significa solo che il transaction log non potra' essere utilizzato in fase di restore (infatti in questa modalita' non e' concesso il backup del log), ma che comunque viene assicurata tutta l'attivita' relativa alla gestione delle transazioni ... e ci mancherebbe che non lo facesse !!!! 
Pertanto, anche in questa modalita', il transaction log conterra' tutte le informazioni necessarie a Sql per poter gestire un eventuale roll back. Questo comporta che il file di log avra' una dimensione tale da memorizzare tutte le transazioni non ancora committate o, piu' precisamente, conterra' "almeno" tutte le transazioni avvenute a partire dalla piu' vecchia presente ancora non committata.
Per questa ragione, in presenza di transazioni ricche di dati, anche in modalita' SIMPLE il file di log crescera' e potrebbe assumere dimensioni anche elevate.
La differenza con le altre due modalita di recovery (FULL e BULK_INSERT) risiede nel fatto che, man mano che le transazioni vengono committate lo spazio a loro associato viene riutilizzato per memorizzare nuove transazioni.[per dirla piu' correttamente viene riutilizzato lo spazio associato alle transazioni antecedenti alla piu' vecchia non committata]. Questo in FULL e BULK_INSERT avviene dopo il backup del log.
Nella modalita' SIMPLE periodicamente e con una frequenza legata alle dimensioni del file di log e al suo grado di riempimento, viene verificata la posizione della transazione attiva piu' vecchia e viene marcato come riutilizzabile lo spazio del log allocato a tutte le transazioni antecedenti a questa. Tale attivita' prende il nome di Troncamento (truncation) del log.
Il Log truncation e' un attivita' di tipo logico: ad essa non e' associata una riduzione fisica del log.
La diminuzione del file di log e' legata all'attivita' di Shrink che, se non e' abilitata tramite l'opzione AUTO_SHRINK ON (cosa da non fare MAI
), avverra' solo dietro un preciso comando (ad esempio un DBCC SHRINKDATABASE).
Detto cio' bisogna ricordare che il recovery model SIMPLE, visto che non consente il recovery tramite log, andrebbe usato raramente: di fatto solo con DB in read only o di test... Averlo in produzione significa sapere che, in caso di failure, verranno perse tutte le transazioni intercorse dall'ultimo backup (full o differenziale) cosa che ritengo sia accettabile in ben poche situazioni....
Di seguito, per i curiosi, un po' di codice "pronto all'uso" per vedere la crescita del file di log in modalita' SIMPLE.
Ciao.
-- Test sul recovery model Simple
USE [master]
GO
-- Creazione db e tabelle di test
-- Il file di log e' VOLUTAMENTE inizializzato piccolo con bassa crescita
-- per valutarne l'aumento di dimensioni
IF
EXISTS (SELECT name FROM sys.databases WHERE name = N'TestRecoverySimple')DROP DATABASE TestRecoverySimple
GO
CREATE
DATABASE TestRecoverySimple ON PRIMARY
(
NAME = N'TestRecoverySimple', FILENAME = N'C:\Temp\TestRecoverySimple.mdf' ,
SIZE = 20480KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1MB )
LOG ON ( NAME = N'TestRecoverySimple_log', FILENAME = N'C:\Temp\TestRecoverySimple_log.ldf' ,
SIZE = 1MB , MAXSIZE = UNLIMITED, FILEGROWTH = 1MB)
GO
-- setto il recovery model a SIMPLE
alter
database TestRecoverySimple set recovery Simple;
GO
-- disabilito l'auto shrink del DB(da non abilitare mai)
alter
database TestRecoverySimple set Auto_Shrink OFF;
GO
--- Creo la tabella di test
use TestRecoverySimple
GO
create
table BigInsert (Id int identity(1,1),
Data
datetime default getdate(),
Valore
varchar (8000));
GO
-- creo la store procedure di inserimento record
create
procedure fpsp_InsertBigRecord (@NumRecord int, @Testo char(1))as
declare @Counter intset @Counter = 1
while @Counter <= @NumRecord Begin
insert into dbo.BigInsert (Valore) values (replicate(@Testo,8000));
set @Counter = @Counter + 1;
end
GO
-- creo la Store procedures (per comodita) che presenta i dati sul log
create
procedure fpsp_ShowLogDimension (@InstanceName varchar(50))
as
select Instance_Name, Counter_name, cntr_value
from sys.dm_os_performance_counterswhere instance_name= 'TestRecoverySimple'
and cntr_type = 65792 and Counter_Name like '%Log%'
;
GO
-- leggo i valori iniziali del log
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- 1016 Kb (40% utilizzato), 0 Shrinks, 0 Growths, 1 Truncation
--- effettuo degli insert
exec
fpsp_InsertBigRecord 2000, 'A';
--Leggo le dimensioni del log
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- NON e' aumentato: 1016 Kb (53% utilizzato), ma ha subito 75 Truncations
-- Inserimenti sotto transazione
begin
tran;
exec fpsp_InsertBigRecord 100, 'B';
-- Rileggo le dimensioni del log
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- E' aumentato: 2040 Kb (73% utilizzato), 1 Growths e 2 truncation rispetto a prima (ora il valore e' 77)
commit
;
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- L'autoshrink e' disabilitato per cui Non scende la dimensione (2040 Kb)
-- altri inserimenti senza transazioni attive
exec
fpsp_InsertBigRecord 2000, 'C';
-- valuto di nuovo il log
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- Nessun inserimento da committare: Non ha avuto bisogno di aumentare (2040 Kb)
-- e' solo aumentato il numero di truncation effettuate (ora 96)
-- effettuo uno shrink
DBCC
SHRINKDATABASE (TestRecoverySimple);
-- valuto di nuovo il log
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- le dimensioni sono scese:1016 Kb (36% utilizzato)
-- nuovi inserimenti sotto transazione
begin
tran;
exec fpsp_InsertBigRecord 200, 'D';
-- valuto di nuovo il log
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- ha subito due grow (il valore ora e' 3) le dimensioni sono: 3064 Kb (83% usato) - log truncation = 123
commit
;
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- 3064 kb (72%)
--effettuo lo shrink
DBCC
SHRINKDATABASE (TestRecoverySimple);
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- ritorno alle dimensioni minime iniziali 1016 kb (35% occupato)
-- effettuo un select into
select
* into dbo.NewBigTable from dbo.BigInsert;
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- Log size 2040 Kb (61% usato) l'attivita' di insert ha richiesto piu' spazio per il log
-- nuovo select into
select
* into dbo.NewBigTable2 from dbo.BigInsert;
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- Non e' aumentato l'operazione era uguale a prima e non ha richiesto altro spazio
-- Log size 2040 Kb (57% usato)
-- nuovo select into
select
* into dbo.NewBigTable3 from dbo.BigInsert;
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- Continua a non aumentare 2040 Kb (61% usato)
-- ora select into sotto transazione
begin
tran
-- 1° select into
select
* into dbo.NewBigTable4 from dbo.BigInsert;
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- non aumenta
---2° select into
select
* into dbo.NewBigTable5 from dbo.BigInsert;
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- siamo sotto transazione la richiesta di spazio aumenta 3064 Kb (78% usate)
---3° select into
select
* into dbo.NewBigTable6 from dbo.BigInsert;
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- siamo sotto transazione la richiesta di spazio aumenta ancora 4088 Kb (83% usate)
---4° select into
select
* into dbo.NewBigTable7 from dbo.BigInsert;
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
-- siamo sotto transazione la richiesta di spazio aumenta ancora 5112 Kb (83% usate)
-- annullo
Rollback
exec
fpsp_ShowLogDimension 'TestRecoverySimple';
Questa e' carina...
In presenza di un database Master corrotto l'istanza di SqlServer potrebbe non partire, pertanto sara' necessario procedere al restore di una copia valida del Master backuppata precedentemente. Ma, per poter effettuare il restore, occorre che l'istanza di Sql sia su... e ... ci troviamo in una situazione di stallo 
Una soluzione drastica e' reinstallare SqlServer, ma esiste una via piu' comoda: reinstallare solo i DB di sistema tramite il seguente comando (documentato nel BOL)
start /wait <CD or DVD Drive>\setup.exe /qn INSTANCENAME=<Instance> REINSTALL=SQL_Engine REBUILDDATABASE=1 SAPWD=<NewStrongPassword> e, poi, procedere al restore del "nostro" master.
Questa info l'ho letta nel seguente post dedicato a questa "complicata" situazione: http://blogs.msdn.com/sqlserverstorageengine/archive/2006/09/26/772550.aspx
Inoltre in quel post viene anche illustrato il procedimento, leggermento piu' lungo, da seguire qualora ci si trovi in presenza di un Sql Express
Non se la cosa era nota a tutti (tranne che a me)... In ogni caso mo' me la sono appuntata qui.. non si sa mai.....
Se il database e' settato in recovery model FULL tutte le scritture legate ad un create index o a un rebuild verranno tracciate nel file di log. Pertanto il transaction log puo' aumentare le proprie dimensioni in modo molto elevato (pensate alle scritture legate ad un indice cluster) aumentando anche i tempi necessari al rebuild stesso.
Questo non accade se il recovery model e' settato a BULK_LOGGED: in tal caso viene tracciato solo il fatto che l'operazione e' stata compiuta oltre ad alcune altre informazioni (tipo gli extended modificati) che serviranno a garantire la corretta esecuzione di un eventuale restore. In tal modo anche la ricreazione degli indici risulta piu' veloce.
Per quello che mi riguarda, dopo aver costruito ed attivato un piano di manutenzione che ricreava un bel po' di indici e essermi trovato un file transaction "esploso"
ho pensato bene di portare il recovery a BULK_LOGGED prima di iniziare l'attivita' e di riportarlo a FULL una volta terminata la manutenzione.
In tal modo le dimensioni del file di log non crescono (se non in minima parte) durante le operazioni di rebuild degli indici e sono anche un po' piu' veloci, ma...attenzione: quando viene effettuato il backup del transaction log Sql provvede a fare in modo che nel file di backup siano presenti tutte le infomazioni necessarie al restore. Pertanto recupera tutte le modifiche fatte alle pagine e le riporta nel file di backup.
Quindi il file di log rimane "snello", ma il suo backup si ingrossa fino ad assumere le dimensioni che avrebbe avuto il log in un recovery FULL ed il tempo di backup si allunga.
In tal modo e' garantito un restore completo sia con il modello FULL che con il BULK_LOGGED con tempi analoghi.
Oltre alla creazione degli indici anche diverse altre operazioni (bcp, BULK INSERT, SELECT INTO...) vengono loggate in modo differente nei due modelli di recovery e, questa, e' una buona ragione per approfondire e capire meglio le differenze tra FULL e BULK_LOGGED.
(Se lo faro' sara' argomento per un prossimo post)
Quanto detto vale per Sql2005, ho il sospetto che in Sql2000 le cose fossero un po' differenti, ma non ho avuto il modo di verificarlo (altro post in arrivo ?)
Buon backup a tutti !! 
Mi sono imbattuto in un comportamento di SqlServer che, di prima battuta, non mi aspettavo, anche se riflettendoci un momento e' assolutamente corretto e sensato (oltre che documentato). Comunque lo posto perche' potrebbe essere inaspettato anche per qualcun altro.
Se fate un "truncate table" di una tabella che contiene un campo identity il suo valore viene riazzerato e, al primo insert, lo trovate valorizzato al suo seed iniziale. In altre parole la truncate fa "perdere" a Sql il valore attuale del contatore,
Da questo luogo provero' anch'io a segnalare caratteristiche e situazioni Sql che mi hanno colpito o semplicemente interessato. Un modo per ricordarsele e, magari, in qualche caso, essere utile.
Ma sono solo uno sviluppista quindi non aspettatevi nulla di straordinario: in fondo unisco le incompentenze di entrambe le figure
... Pero', non si sa mai, come dice un vecchio saggio tosco-emiliano "ho visto a volte che anche un topo sa ruggire ed anche un' aquila precipitata".... per cui... stay tuned !!
Franco (aka OrsoCurioso)