UGISS Community

Il sito della community dello User Group Italiano di SQL Server
Welcome to UGISS Community Sign in | Join | Help
in Search

Alessandro Alpi's blog

Parliamo di integration services e non solo..

ottobre 2007 - Posts

  • [SQL Server 2005] Interessante articolo su RegExp con CLR

    Vi segnalo un interessante articolo di David Banister sulle regular Expression utilizzate in SQL Server.

    Regular Expressions Make Pattern Matching And Data Extraction Easier
    o in italiano
    Le espressioni regolari semplificano l'estrazione dei dati e delle corrispondenze dei modelli

    L'articolo è molto interessante e spiega come sfruttare il CLR con SQL Server per scrivere funzioni che facilitino le ricerche basati su pattern.
    Questo dovrebbe spingere molti sviluppatori T-SQL che magari non fanno uso o cercano di evitare il CLR, di integrarlo maggiormente nelle loro applicazioni.
    Per ora, preferisco dimenticare le extended stored procedure o l'integrazione di oggetti OLE con le sp_OA..

    Stay tuned!
     

  • [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!


  • [SSIS] Altro metodo per scrivere Log su SQL Server: PRECISAZIONE

    Volevo puntualizzare una cosa che ho scritto sul mio precedente post, per evitare incomprensioni. Anche Michael Coles ha aggiunto la nota sul suo post.

    NOTA: La stored procedure sp_dts_addlogentrynon è una stored procedure di "sistema" come ho indicato superficialmente nel precedente post (ho erroneamente utilizzato la parola per indicare un oggetto non creato dall'utente).. In effetti è una stored procedure creata dal Provider di Log di SSIS se già non esiste. Mentre se già esiste non la tocca. Questo significa che intervenire a quel livello è comunque una pratica che è possibile seguire senza entrare nel contesto degli oggetti di sistema per definizione.

    Questo giusto per chiarezza

    Stay tuned!

  • [SSIS] Altro metodo per scrivere Log su SQL Server

    Sfogliando il mio rss reader mi sono accorto di un post interessante riguardante i Log di SSIS..
    Come anche Jamie Thomson nel suo post indica, due metodi possibili per effettuare log sono l'utilizzo degli Event Handlers e definirsi un provider di Log.
    Inoltre ognuno di noi ha la possibilità di utilizzare gli script task proprio per creare file da consultare alla fine del processo.
    Ma il post di Jamie è importante per il link che consiglia di visitare, di Michael Coles (sqlservercentral.com).
    Michael si pone di introdurre un nuovo metodo per costruire un log su sql server.
    Ora, come vedrete, il metodo obbliga a modificare una stored procedure di sistema, la  sp_dts_addlogentry aggiungendo la scrittura su di una tabella creata adhoc in precedenza. Magari non è così ortodosso eseguire un'operazione simile, visto che si tende sempre a lasciare invariate quei particolari oggetti, ma lo trovo una via da non sottovalutare..
    Anche perchè una volta eseguita la modifica, è sufficiente definire un Provider di Log per SQL Server sul pacchetto ed il gioco è fatto.
    Voi che ne pensate?


    Stay tuned!

  • Finalmente "riapre" il blog sulle RegExp di Mike

    Dopo innumerevoli giorni di stop ho convinto il mio amico Mike a mettersi lì a scrivere il suo secondo post.
    Tralasciamo le motivazioni del tempo di attesa.. ora speriamo che sia costante nel pubblicare.
    Perchè il suo argomento è uno dei più affascinanti ed allo stesso tempo evitati o ignorati di tutti.
    Quindi, ecco il suo secondo post..
    Leggete e mediate!

    Stay tuned!

  • [SSIS] I Dataflow - Le destinazioni

    Ritorniamo sui post di formazione, anche se so che molti di voi ora saranno già esperti di SSIS .
    L'ultima volta ci siamo lasciati con le sorgenti, ora riprendiamo con le destinazioni.
    Le possibili sono le seguenti:



    Quelle comunemente utilizzate (alcune sono presenti anche nell'elenco delle sorgenti) sono la DataReader Destination, la Excel Destination, la Flat File destination, la OLEDB Destination e la SQL Server Destination. Quest'ultimo è un task dedicato al caricamento di massa (bulk load) su di un server locale, solamente locale, mai remoto.
    Per approfondire leggere SQL Server Destination.

    Ovviamente, a differenza dai source task, questi necessitano metadati in input e non ritornano metadati di output. Possiamo dire che sono la parte finale di ogni dataflow, anche se non è necessario terminare le nostre logiche con un destination task.

    Come possiamo vedere dall'elenco, ci sono tre task, che non sono proprio destinazioni a tutti gli effetti:
    - Data Mining Model Training
    - Dimension Processing
    - Partition Processing

    Sono task dedicati a chi ha necessità di lavorare con OLAP, con la BI e/o con il datawarehousing. Gli ultimi due riguardano le parti fondamentali di un CUBO.
    A grandissime linee, consentono di processare una o più dimensioni di un modello multidimensionale (dove per dimensione si intende l'entità che consente la navigazione di un CUBO) e di processare una partizione di un CUBO. Con il termine processare si intende una sorta di "compilazione", in questo caso delle dimensioni e delle partizioni di un CUBO.
    Fino a che un process non è terminato, la dimensione o il cubo non sono interrogabili.
    Per il primo task invece, consiglio di leggere qui, essendo il data mining un discorso delicato, basato su particolari algoritmi.

    Le rimanenti consentono di scrivere su recordset, file raw e versioni Compact Edition di SQL Server. Per ulteriori informazioni su quest'ultima destinazione, leggere qui.

    Prendiamo una destinazione di esempio, la OLEDB Destination, e vediamo come sono composte. Facendo doppio click, la prima sezione è la Connection Manager:


    Tramite questa interfaccia è possibile definire quale connection manager utilizzare come destinazione, il livello di accesso ai dati (se possibile, per ottenere maggiori prestazioni, utilizzare il fast load) ed alcune importanti opzioni.
    Keep Identity - Per imporre alla destinazione di non ricalcolare gli autoincrementanti, utilizzando quelli della sorgente (solo se fast load)
    Keep nulls - Per imporre alla destinazione di copiare i null (solo se fast load).
    Table lock - Per tenere bloccata la risorsa.
    Check constraints - Per imporre alla destinazione di controllare tutti gli eventuali vincoli.
    Rows per batch - Per indicare quante righe per batch devono essere considerate (textbox vuoto o -1 indicano mancanza di controllo sul numero di righe). Indicativamente è il numero approssimativo delle righe lette.
    Maximum insert commit size - Per specificare le dimensioni del batch per le quali la destinazione OLEDB tenta di eseguire il commit

    La sezione mappings indica come la sorgente deve essere riferita alla destinazione.



    Se i nomi sono identici SSIS propone il suo mapping, in caso contrario è sufficiente indicare il corretto match nei drop down sotto, oppure fare trascinare i campi sorgente sopra a quelli destinazione. Con quest'ultima operazione i drop down si popoleranno dinamicamente.
    Inoltre, premendo il tasto destro del mouse sulla zona dei legami, è possibile selezionare alcune opzioni rapide, per mappare o gestire più velocemente un numero considerevole di campi.
    La sezione Error Output è del tutto identica a quella di ogni task, e quindi permette la gestione di eventuali errori.

    E' molto importante valorizzare bene, nel caso degli OLEDB Destination Task, le due opzioni Rows per batch e Maximum insert commit size.
    A questo proposito consiglio di leggere questo link, e comunque consiglio di effettuare tante prove per capire quali valori sono i più indicati per il miglioramento delle prestazioni, non esistendo una formula specifica per calcolarli.

    Stay tuned!