Tag Archive for 'Sql'

Aggiornare lo schema di una vista con sp_refreshview.

Spero possa essere utile anche a voi quanto sto per scrivere, per me in primis vuole essere un appunto da tenere sempre a portata di mano nei momenti in cui la mente mi abbandona. Vi è capitato di creare e subito dopo modificare viste (view) in SQL Server e di trovarvi in questa situazione: creo una vista che prende dati da un’altro database presente nello stesso server:

CREATE VIEW MyView AS
	SELECT Column1,Column2 FROM Database.dbo.Table

Successivamente creo un’altra vista quasi identica che per determinati motivi si “appoggia” direttamente alla prima facendo una SELECT * (START premettendo che è sbagliato eseguire una select in questo modo in quanto a risentirne di più sono proprio le performance del server SQL).

CREATE VIEW MyView2 AS
	SELECT * FROM MyView

Dopo un pò di tempo torno sulla prima view e ne modifico le colonne, ne aggiungo di nuove. Cosa succede? Che MyView2 interrogata, mi risponde riportando solo le vecchie colonne e non le nuove. Questo succede perchè lo schema della vista non è stato aggiornato correttamente, per ovviare a questa situazione basta un semplice comando:

EXEC sp_refreshview @view = N'MyView2'

Successivamente, la vista contiene l’elenco delle colonne aggiornate!

SQL – Stored Procedure – impaginazione ricerche.

Una delle richieste fatte molto spesso dai clienti con cui sono abituato a lavorare e la possibilità di poter visualizzare i risultati di una ricerca impaginati, cioè presentare N records per pagina. Ora utilizzando Stored Procedure si potrebbero intraprendere due strade differenti ma solo una, secondo me, è la migliore.

Cache memory
Eseguire la stored procedure e caricare in memoria (cache) il risultato della query, successivamente quando l’utente utilizza i cursori, lo spostamento viene effettuato sui dati presenti in cache. Un idea pessima se il contesto in cui lavoriamo prevede enormi quantità di dati e di conseguenza grandi risultati nella ricerca, se poi proviamo a pensare ad un’applicazione web in cui il numero di utenti che la utilizza è davvero elevato potremmo trovarci davvero nei guai. Il traffico generato dalle richiesta inviate da/al Server SQL non solo rischia di portare la rete ad un congestionamento, ma è potrebbe bloccare anche il server stesso.
SQL Cursors
La seconda strada, secondo me la migliore, è quella di creare una stored procedure che implementi l’utilizzo dei cursori internamente alla query.

In questo post voglio spiegare (sperando di essere di aiuto per qualcuno) come scrivere una stored procedure che soddisfi quanto spiegato nel secondo punto. Supponiamo di voler raggiungere il seguente obiettivo: dati in input i parametri e la combinazione di cursori, la stored procedure deve tirar fuori un determinato numero di record.

Prendiamo in esame una semplice tabella (che per comodità conterrà secondo la nostra fantasia tanti tanti records!). Abbiamo la tabella Persona, che al suo interno contiene tre campi: ID, Nome e Cognome (si proprio la più semplice!). Ora dobbiamo creare una stored procedure che soddisfi il nostro obiettivo:

CREATE PROCEDURE CercaPersona
@nome varchar(50) = null,
@cognome varchar(50) = null,
@rpp tinyint,
@start int
AS
CREATE TABLE #T(
ID int not null primary key IDENTITY(1,1),
IDPersona int not null)

INSERT INTO #T(IDPersona)
SELECT ID
FROM Persona
WHERE ((Nome LIKE '%' + @Nome + '%') OR (@Nome IS NULL))
AND ((Cognome LIKE '%' + @Cognome + '%') OR (@Cognome IS NULL))

SELECT p.ID,p.Nome,p.Cognome
FROM Persona AS p
INNER JOIN #T AS t
ON t.IDPersona = p.ID
WHERE p.ID >= @start
AND p.ID < (@start + @rpp)

DROP TABLE #T
go

Penso sia doveroso spiegare come funziona, prima di tutto analizziamo i parametri, oltre al Nome ed il Cognome che rappresentano chiaramente i parametri , ci sono anche:

  • @rpp: questo parametro l'ho chiamato cosi proprio perchè è l'acronimo di righe per pagina, in pratica stiamo dicendo alla stored procedure quante righe vengono stampate in ogni pagina.
  • @start: indica l'indice dell'elemento dei risultati da cui iniziare a leggere.

Osservando nella sua totalità la query si nota che viene prima di tutto creata una tabella temporanea che contiene il risultato completo della query, a questa viene applicata un piccolo indice con il campo:

ID int not null IDENTITY(1,1)

Ogni IDPersona valorizzato caricherà un valore anche per ID, questo dato rappresentarà il nostro indice per la gestione dei cursori, successivamente utilizzando il parametro @start e @rpp possiamo mettere in join le due tabelle e caricare "unicamente" i dati necesari per l'impaginazione di una singola pagina.