settembre 2008 - Posts

[SQL 2008] Management Studio Options
17 settembre 08 09.57 | abenedetti | with no comments

La nuova versione di SQL Server porta con sè, oltre a mille caratteristiche e funzionalità, anche diverse nuove possibilità di configurazione dello strumento principe di utilizzo e gestione: SQL Server Management Studio.

Dal menù Tools - Option:

1. Posso decidere cosa venga aperto all'apertura del tool (l'object explorer, una nuova finestra di query, nulla, l'activity monitor, ...)

image

2. Posso decidere di avere la numerazione di linea sui miei script

lineNumber

image

3. Posso includere la query eseguita nella finestra di messaggi

includeQuery 

image 

4. Posso modificare quell'orribile colore della status bar che è impostato di default per query multiserver (Central Management Servers)

image

image

[SQL 2008] Downgrade database
15 settembre 08 12.07 | abenedetti | with no comments

SQL Server non consente il restore (o l'attach) di un database creato con una versione superiore.

Se, infatti, provate ad eseguire un attach di un database creato con la versione 2008 su un'istanza 2005 otterrete questo errore:

image 

Per eseguire un downgrade sarà quindi necessario:

  • generare gli script del database per poterlo ricreare (attenzione all'opzione: "Script for server version")

image

  • copiare i dati sul nuovo database
[SQL 2008] Filestream & Delete
02 settembre 08 01.02 | abenedetti | 2 comment(s)

L’istruzione DELETE su una tabella contenente oggetti FILESTREAM non va vista in prospettiva “eliminazione immediata del file fisico dal disco”.

Questo perchè la cancellazione fisica viene demantata ad una sorta di garbage collector che, al meccanismo di CHECKPOINT, è in grado di riconoscere cosa può e deve essere cancellato.

C’è un modo per accelerare questo processo?

Si, chiamare esplicitamente il CHECKPOINT.

Ovvero:

delete from miaTabella checkpoint go
[Fulltext] Files indicizzabili
01 settembre 08 11.55 | abenedetti | 1 comment(s)

Il motore fulltext, di cui ho fatto una brevissima panoramica qui, di SQL Server non indicizza, nativamente, diversi tipi di files.

Si va dai comuni PDF, ai files ZIP, ai files XPS, ...

Per vedere la lista delle estensioni supportate è sufficiente vedere la vista di sistema [sys.fulltext_document_types], ovvero:

/* la lista dei documenti indicizzabili */ SELECT * FROM sys.fulltext_document_types

Per poter indicizzare i files PDF, Adobe rende disponibile una DLL, sotto il file di installazione “ifilter60.exe”, disponibile e scaricabile da qui (nemmeno 10 MB).

Una volta lanciato il setup di questo file è necessario abilitare SQL Server all’utilizzo, ovvero:

use master go exec sp_fulltext_service 'load_os_resources',1 go exec sp_fulltext_service 'verify_signature', 0 go

Fatto questo è necessario un restart del servizio SQL.

Altri pacchetti che suggerisco (a seconda delle esigenze):

Microsoft Filter Pack

http://www.microsoft.com/downloads/details.aspx?FamilyId=60C92A37-719C-4077-B5C6-CAC34F4227CC&displaylang=en

Il pacchetto include i seguenti iFilters:

  • Metro (.docx, .docm, .pptx, .pptm, .xlsx, .xlsm, .xlsb)
  • Zip (.zip)
  • OneNote (.one)
  • Visio (.vdx, .vsd, .vss, .vst, .vdx, .vsx, .vtx)

Microsoft XPS (XML Paper Specification) Essentials Pack

http://www.microsoft.com/downloads/details.aspx?FamilyId=B8DCFFDD-E3A5-44CC-8021-7649FD37FFEE&displaylang=en

Dopo queste installazioni ho a disposizione 140 estensioni conosciute :-)

image

Filed under:
[Update] Svuotare un database: un meccanismo automatico
01 settembre 08 12.06 | abenedetti | 2 comment(s)

Qualche settimana fa ho postato, sul blog, uno script per poter effettuare uno svuotamento di un database e riportalo al suo stato "iniziale".

Nello script eseguo un controllo, tramite la funzione scalare IDENT_CURRENT, per poter chiamare (per inizializzare nella maniera corretta eventuali campi identity) il comando DBCC CHECKIDENT con 0 oppure con 1.

Questa funzione ha però un piccolo, subdolo, bug.

La funzione scalare IDENT_CURRENT ritorna 1 per una colonna IDENTITY(1,1) sia che non ci siano righe nella tabella, sia che ci sia una sola righa con IDENTITY = 1.

Il problema, quindi, è "solo" questo: non siamo in grado di stabilire se la tabella non sia mai stata utilizzata oppure se conteneva una sola riga con identity = 1.

Analogamente non esiste un modo per conoscere quali sono le tabelle “vergini” (mai utilizzate).

La soluzione diventa abbastanza semplice e consiste esclusivamente in questo:

  • memorizzare le tabelle che hanno una sola riga al loro interno:

/* Memorizzo le tabelle che hanno una sola riga al loro interno */ select tableName into #dbcc from #results where NrRows = 1

  • non effettuare alcun controllo per sapere come chiamare il comando DBCC su queste tabelle
  • chiamare il comando DBCC passando sempre il valore 0:

set @tsql = ' DBCC CHECKIDENT (' + @tName + ', RESEED, 0) '

Questo il codice dello script aggiornato e corretto:

 

/* Meccanismo di delete automatico */ set nocount on print '*** delete' declare @tName nvarchar(100) declare @tSQL nvarchar(2000) declare @nrRows bigint declare @rowCount bigint if object_id('tempdb..#temp') is not null drop table #temp if object_id('tempdb..#results') is not null drop table #results if object_id('tempdb..#dbcc') is not null drop table #dbcc create table #results ( tableName varchar(50), nrRows bigint, reseed int ) /* Recupero la lista delle tabelle del mio db */ select table_name into #temp from information_schema.tables where table_type = 'base table' /* Recupero il numero di righe presenti in ciascuna tabella */ while exists (select 1 from #temp) begin select top 1 @tName = table_name from #temp set @tSQL = 'select ''' + @tName + ''' as TableName, count(*) as NrRows, 0 from [' + @tName + ']' insert into #results exec sp_executesql @tSQL delete from #temp where table_name = @tName end /* Memorizzo le tabelle che hanno una sola riga al loro interno */ select tableName into #dbcc from #results where NrRows = 1 /* verifico se ho delle righe nel db */ select @nrRows = sum(nrRows) from #results select @nrRows as nrRigheIniziali /* se voglio vedere l'elenco delle tabelle con il numero di righe */ select * from #results /* ciclo finchè ho righe */ while (@nrRows > 0) begin /* ciclo finchè ho tabelle su cui eseguire l'operazione di delete */ while exists (select 1 from #results) begin /* costruisco l'operazione di delete */ select top 1 @tName = TableName, @nrRows = NrRows from #results if (@nrRows > 0) begin set @tSQL = 'delete from [' + @tName +']' print @tSQL begin try exec sp_executesql @tSQL set @rowCount = @@rowcount print '@rowCount: ' + cast(@rowCount as varchar(10)) end try begin catch print error_message() end catch end else begin print 'tabella ' + @tName + ' risulta vuota' end print '' /* elimino dal mio contenitore temporaneo la tabella su cui ho eseguito la delete */ delete from #results where tableName = @tName end /* svuoto le mie tabelle temporanee */ truncate table #temp truncate table #results /* riprendo l'elenco delle tabelle */ insert #temp select table_name from information_schema.tables where table_type = 'base table' /* ricalcolo il numero di righe di ciascuna tabella */ while exists (select 1 from #temp) begin select top 1 @tName = table_name from #temp set @tSQL = 'select ''' + @tName + ''' as TableName, count(*) as NrRows, 0 from [' + @tName + ']' insert into #results exec sp_executesql @tSQL delete from #temp where table_name = @tName end /* riconto il numero di righe totali del db */ select @nrRows = sum(nrRows) from #results end /* (re)inizializzazione dei contatori */ print '*** reseed' /* svuoto le mie tabelle temporanee */ truncate table #temp truncate table #results /* riprendo l'elenco delle tabelle */ insert #temp select table_name from information_schema.tables where table_type = 'base table' /* calcolo il numero di righe di ciascuna tabella ed eseguo l'operazione: IDENT_CURRENT('nomeTabella') - IDENT_SEED('nomeTabella') */ while exists (select 1 from #temp) begin select top 1 @tName = table_name from #temp set @tSQL = 'select ''' + @tName + ''' as TableName, count(*) as NrRows, IDENT_CURRENT(''' + @tName + ''') - IDENT_SEED(''' + @tName + ''') from [' + @tName + ']' insert into #results exec sp_executesql @tSQL delete from #temp where table_name = @tName end /* elimino eventuali tabelle che: 1. hanno righe 2. non necessitano la reinizializzazione (non hanno identity) */ delete from #results where nrRows <> 0 or reseed IS NULL /* elimino le tabelle sulle quali chiamerò la DBCC CHECKIDENT successivamente */ delete from #results where tableName IN (select tableName from #dbcc) declare @reseed int select top 1 @tName = tableName, @reseed = reseed from #results /* Se: IDENT_CURRENT('nomeTabella') - IDENT_SEED('nomeTabella') = 0 allora: DBCC CHECKIDENT ('nomeTabella', RESEED, 1) altrimenti: DBCC CHECKIDENT ('nomeTabella', RESEED, 0) */ while exists (select 1 from #results) begin if (@reseed = 0) set @tsql = ' DBCC CHECKIDENT (' + @tName + ', RESEED, 1) ' else set @tsql = ' DBCC CHECKIDENT (' + @tName + ', RESEED, 0) ' print @tsql begin try exec sp_executesql @tsql end try begin catch end catch delete from #results where tableName = @tName select top 1 @tName = tableName, @reseed = reseed from #results end print 'Forced DBCC' select top 1 @tName = tableName from #dbcc while exists (select 1 from #dbcc) begin set @tsql = ' DBCC CHECKIDENT (' + @tName + ', RESEED, 0) ' print @tsql begin try exec sp_executesql @tsql end try begin catch end catch delete from #dbcc where tableName = @tName select top 1 @tName = tableName from #dbcc end print '*** end ***'

This Blog

Syndication