SQL Server ed ALM su database


Il blog di Alessandro Alpi
Archivio Posts
Anno 2018

Anno 2017

Anno 2016

Anno 2015

Anno 2014

Anno 2013

Anno 2012

Anno 2011

Anno 2010

Anno 2009

Anno 2008

Anno 2007

Anno 2006

[SQL Server 2005] Gli schema e le query

L'altro giorno mi è successa una cosa apparentemente strana. Una di quelle cose che quando capitano, se non ci si pensa abbastana, vengono definite dalla frase "MA E' IMPOSSIBILE!!" .
Vi illustro la situazione:

una semplice stored procedure che esegue una select su di una tabella.
Procediamo per step.
Come prima cosa, accedo su di un database con il mio utente, che a sua volta ha dbo come default schema.
SQL Server accede agli oggetti con la seguente logica:

1) Tenta di accedere allo schema di default
2) Tenta di accedere all'oggetto sotto dbo.

Prendiamo la seguente query di esempio:

SELECT * FROM Movimenti

Per accedere alla tabella Movimenti con un ipotetico utente User1 che ha come default schema Schema1, SQL server tenterà prima di accedere all'oggetto Schema1.Movimenti e poi, se non è stato trovato, a dbo.Movimenti.

Detto questo (ricordiamoci che il mio utente ha dbo come schema di default) ricostruiamo lo scenario che mi si è presentato.

Creo lo schema non di default per l'utente, chiamandolo MioSchema

-- creo lo schema
CREATE SCHEMA MioSchema
---------------------------------------------------------------

Successivamente creo due oggetti con lo stesso nome:

-- creo due tabelle con lo stesso nome, ma con schema diverso
---------------------------------------------------------------

CREATE TABLE dbo.Eventi
(
      IDEvento int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
      Evento varchar(100)

)

CREATE TABLE MioSchema.Eventi
(
      IDEvento int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
     
Evento varchar(100)
)

INSERT dbo.Eventi (Evento) VALUES ('Gran premio di formula 1')
INSERT dbo.Eventi (Evento) VALUES ('ATP Tour golf')
INSERT dbo.Eventi (Evento) VALUES ('Tennis Master Series')
INSERT dbo.Eventi (Evento) VALUES ('Campionato di Sci')
INSERT dbo.Eventi (Evento) VALUES ('Mondiali di nuoto')

INSERT MioSchema.Eventi (Evento) VALUES ('SERIE A Tim')
INSERT MioSchema.Eventi (Evento) VALUES ('Premier League')
INSERT MioSchema.Eventi (Evento) VALUES ('Liga')
INSERT MioSchema.Eventi (Evento) VALUES ('Bundesliga')
INSERT MioSchema.Eventi (Evento) VALUES ('Ligue')

---------------------------------------------------------------

Ora, lanciando una selezione dell'intera tabella omettendo lo schema otterremo il seguente risultato:

SELECT * FROM Eventi


Questo è il risultato che ci si aspettava, poichè il primo oggetto ad essere letto è quello identificato da dbo.Eventi poichè dbo è il default schema.
Rilanciando la stessa query, utilizzando un utente che ha come default schema MioSchema (creato all'inizio), il risultato sarà:



Fino a qui tutto ok. Ma ora passiamo a quello che mi ha decisamente ingannato.
Creiamo la seguente stored procedure:

CREATE PROCEDURE MioSchema.proc_Eventi
AS
      SET NOCOUNT ON;

      SELECT * FROM Eventi
GO


Che ci si aspetta? Dati dalla tabella su dbo? dalla tabella di MioSchema?
Erroneamente, e ci sono proprio cascato, mi aspettavo dati da dbo. Ma non è così. I BOL lo evidenziano con la seguente frase passatami da Lorenzo:
"Inside a stored procedure, object names used with statements (for example, SELECT or INSERT) that are not schema-qualified default to the schema of the stored procedure."
In poche parole.. i dati tornati dalla stored procedure in esame sono proprio quelli della tabella MioSchema.Eventi. Questo a prescindere dal default schema del mio utente. Gli oggetti indicati senza schema nella stored proc vengono considerati come oggetti dipendenti dallo stesso schema della stored, in casi di ambiguità.



Nella sitauzione reale, questo problema si è verificato dopo il porting di un database SQL Server 2000 verso la versione 2005. Il mio collega Marco ha aggiunto uno schema per aggiungere nuovi oggetti e non appena si è trovato questa situazione di ambiguità (due viste con lo stesso nome ma diverso schema), si è subito reso conto che qualcosa non andava. I dati che si è trovato di fronte non erano quelli che si aspettava.
La prima operazione eseguita per capire dove stesse il problema (sinceramente non ci abbiamo pensato subito) è stata quella di copia-incollare il contenuto della stored procedure in una nuova query per poi eseguirla al di fuori dello scope della procedura. Il tutto funzionava come ci si aspettava.
Dopo i primi tentativi, siamo arrivati alla conclusione che il problema stesse proprio nello schema sotto cui è salvata la stored proc. E grazie alla frase nei BOL, abbiamo capito definitivamente il problema, anche se a questo punto non lo era più effettivamente
Questo esempio dovrebbe far capire quanto è importante seguire alcune regole molto importanti:
- leggere bene i BOL
- usare SEMPRE la naming NomeSchema.NomeTabella per evitare problemi legati all'ambiguità
- conseguentemente alla precedente regola, indicare anche lo schema dbo che alcuni sicuramente omettono ancora abituati a non utilizzarlo spesso sulla versione 2000.

Personalmente utilizzo sempre la naming NomeSchema.NomeTabella ma questo porting mi ha decisamente "fregato"

Ho deciso di postare questo caso, perchè alcuni di questi errori possono portare a considerazioni errate. Non è da tutti i giorni trovarsi una stored procedure che non torna i dati attesi ed il cui contenuto, con gli stessi parametri, fa quello che deve fare. Si tratta di quelle cose a cui subito, magari, non si pensa.. ma che è sempre bene tenere a mente. Certo è che, seguendo la naming convention, nulla di tutto ciò sarebbe accaduto. Un codice scritto chiaro vince sempre!

Stay tuned!


Categoria: SQL Server 2005
giovedì, 18 ott 2007 Ore. 23.06
Statistiche
  • Views Home Page: 601.393
  • Views Posts: 1.068.912
  • Views Gallerie: 641.208
  • n° Posts: 484
  • n° Commenti: 273



















Copyright © 2002-2007 - Blogs 2.0
dotNetHell.it | Home Page Blogs
ASP.NET 2.0 Windows 2003