Esaminare codice scritto con using

martedì 22 maggio 2012 - 14.22

trinity Profilo | Guru

Salve ragazzi,
volevo chiedervi se secondo voi tutte queste using che eseguono query vanno bene ossia io leggo un file ascii presente su un client e da web eseguo il codice sotto riportato per leggere lo stream e scrivere i record in tabelle che si trovano un server web remoto...adesso in questo codice ci sono anche query che mi servono per stabilire se ci sono la presenza di record in una tabella e dal risultato determinare se eseguire un'insert o un'update.
La mia domanda è la seguente, dato che tutto funziona ma ci mette una vita ad eseguire il tutto calcolando che il ciclo do loop è di 1400 record, pensavo che le using le avessi scritte mali se c'è la possibilità di eseguire le stored in una maniera + rapida con una scrittura di versa..calcolando che il db lo apro solo all'inizio...ecco sapere secondo, dato che comunque le stored le devo eseguire se il codice scritto va bene oppure si può fare di meglio...

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra
[/code][/code] End Using
End If
Loop Until line Is Nothing
End Using[/code]

in questa parte di codice:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra


io eseguo prima una stored che mi fa una select per controllare la presenza o no di record se ci sono passo un valore alla variabile che nella seconda stored all'interno mi gestisce se eseguire una insert se il record non esiste oppure una update se è da aggiornare...mi domandavo ma se in un'unica stored io prima eseguo la select di controllo e in base al suo result eseguo sempre nella stessa stored l'insert o l'update?
A questo punto togliere del codice scritto in vb e secondo voi velocizzerei un pò la procedura?

Ciao e grazie
Cirillo Fabio
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/
http://wnetsoftware.blogspot.com

alx_81 Profilo | Guru

>Salve ragazzi,
Ciao

>La mia domanda è la seguente, dato che tutto funziona ma ci mette
>una vita ad eseguire il tutto calcolando che il ciclo do loop
>è di 1400 record, pensavo che le using le avessi scritte mali
>se c'è la possibilità di eseguire le stored in una maniera +
>rapida con una scrittura di versa..calcolando che il db lo apro
>solo all'inizio...ecco sapere secondo, dato che comunque le stored
>le devo eseguire se il codice scritto va bene oppure si può fare
>di meglio...
non è una questione di numero di using. La pratica da seguire sarebbe quella di usare using ovunque c'è un oggetto di cui vi è da fare dispose. Anche per pulizia del codice.

>...mi domandavo ma se in un'unica stored io prima eseguo
>la select di controllo e in base al suo result eseguo sempre
>nella stessa stored l'insert o l'update?
>A questo punto togliere del codice scritto in vb e secondo voi
>velocizzerei un pò la procedura?
Dipende dalla versione di SQL Server, dalla 2008 hai il MERGE statement:
http://technet.microsoft.com/en-us/library/bb510625(v=sql.100).aspx

>Ciao e grazie
di nulla!
--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

trinity Profilo | Guru

>>Salve ragazzi,
>Ciao
>
>>La mia domanda è la seguente, dato che tutto funziona ma ci mette
>>una vita ad eseguire il tutto calcolando che il ciclo do loop
>>è di 1400 record, pensavo che le using le avessi scritte mali
>>se c'è la possibilità di eseguire le stored in una maniera +
>>rapida con una scrittura di versa..calcolando che il db lo apro
>>solo all'inizio...ecco sapere secondo, dato che comunque le stored
>>le devo eseguire se il codice scritto va bene oppure si può fare
>>di meglio...
>non è una questione di numero di using. La pratica da seguire
>sarebbe quella di usare using ovunque c'è un oggetto di cui vi
>è da fare dispose. Anche per pulizia del codice.
scusa quale oggetto nel mio ha bisogno del dispose?
>>...mi domandavo ma se in un'unica stored io prima eseguo
>>la select di controllo e in base al suo result eseguo sempre
>>nella stessa stored l'insert o l'update?
>>A questo punto togliere del codice scritto in vb e secondo voi
>>velocizzerei un pò la procedura?
>Dipende dalla versione di SQL Server, dalla 2008 hai il MERGE
>statement:
>http://technet.microsoft.com/en-us/library/bb510625(v=sql.100).aspx

ho letto sembra interessante ma al volo dando un'occhiata ai codici msdn ma una cosa non capisco ossia viene citato quanto segue:

Clausola MERGE che specifica la tabella o la vista di destinazione delle operazioni di inserimento, aggiornamento o eliminazione.

Clausola USING che specifica l'origine dati da unire in join con la destinazione.

solo la clausola merge l'ho capita e sarebbe la tabella di destinazione su sui verranno applicate le insert o update o delete ma la using che non capisco in quanto io i dati da salvare o aggiornare li passo tramite parametri alla stored ma vengono presi dai campi input delle form o delle pagine aspx

dove faccio confusione?
>
>>Ciao e grazie
>di nulla!
>--
>Alessandro Alpi | SQL Server MVP
>MCP|MCITP|MCTS|MCT
>
>http://www.alessandroalpi.net
>http://blogs.dotnethell.it/suxstellino
>http://mvp.support.microsoft.com/profile/Alessandro.Alpi
Cirillo Fabio
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/
http://wnetsoftware.blogspot.com

alx_81 Profilo | Guru

>Clausola USING che specifica l'origine dati da unire in join con la destinazione.
>ma la using che non capisco in quanto io i dati da salvare o aggiornare li
>passo tramite parametri alla stored ma vengono presi dai campi
>input delle form o delle pagine aspx
>dove faccio confusione?
diciamo che puoi usare un trick, creando un record virtuale sulle var passate, tipo:


USE tempdb; GO CREATE TABLE #tempDestination ( id int IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED , valore int , tempo datetime , stringa varchar(20) ); INSERT INTO #tempDestination ( valore, tempo, stringa ) VALUES ( 1, NULL, '' ) , ( 2, NULL, '' ) , ( 3, NULL, '' ); -- prima di inserire o aggiornare SELECT * FROM #tempDestination TD; /* id valore tempo stringa ----------- ----------- ----------------------- -------------------- 1 1 NULL 2 2 NULL 3 3 NULL */ -- dati per una update DECLARE @var1 int = 1; DECLARE @var2 int = 2; DECLARE @var3 datetime = GETDATE(); DECLARE @var4 varchar(20) = 'PROVA'; MERGE #tempDestination DEST USING (SELECT @var1, @var2, @var3, @var4) SRC (New_id, New_valore, New_tempo, New_stringa) ON SRC.New_id = DEST.id WHEN MATCHED THEN UPDATE SET valore = SRC.New_valore , tempo = SRC.New_tempo , stringa = SRC.New_stringa WHEN NOT MATCHED THEN INSERT (valore, tempo, stringa) VALUES (SRC.New_valore, SRC.New_tempo, SRC.New_stringa); -- dopo merge per modifica SELECT * FROM #tempDestination TD; /* id valore tempo stringa ----------- ----------- ----------------------- -------------------- 1 2 2012-05-25 12:20:56.087 PROVA AGGIORNATO IL RECORD CON ID 1 2 2 NULL 3 3 NULL */ -- dati per una insert SET @var1 = 5; SET @var2 = 2; SET @var3 = GETDATE(); SET @var4 = 'PROVA'; -- rieseguo merge MERGE #tempDestination DEST USING (SELECT @var1, @var2, @var3, @var4) SRC (New_id, New_valore, New_tempo, New_stringa) ON SRC.New_id = DEST.id WHEN MATCHED THEN UPDATE SET valore = SRC.New_valore , tempo = SRC.New_tempo , stringa = SRC.New_stringa WHEN NOT MATCHED THEN INSERT (valore, tempo, stringa) VALUES (SRC.New_valore, SRC.New_tempo, SRC.New_stringa); -- dopo merge per inserimento SELECT * FROM #tempDestination TD; /* id valore tempo stringa ----------- ----------- ----------------------- -------------------- 1 2 2012-05-25 12:20:56.087 PROVA 2 2 NULL 3 3 NULL 4 2 2012-05-25 12:20:56.093 PROVA INSERITO IL NUOVO RECORD CON ID 5 */ -- pulizia DROP TABLE #tempDestination;

--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

trinity Profilo | Guru

>CREATE TABLE #tempDestination
>(
> id int IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED
> , valore int
> , tempo datetime
> , stringa varchar(20)
>);
>

In teoria questa tua tabella temp potrebbe nella mia situazione essere la vera tabella del db dovre salevrò o aggiornerò i dati

>INSERT INTO #tempDestination ( valore, tempo, stringa )
>VALUES
> ( 1, NULL, '' )
> , ( 2, NULL, '' )
> , ( 3, NULL, '' );
>
>-- prima di inserire o aggiornare
>SELECT * FROM #tempDestination TD;
>
>/*
>id valore tempo stringa
>----------- ----------- ----------------------- --------------------
>1 1 NULL
>2 2 NULL
>3 3 NULL

Non capisco perchè in questa tabella temp hai dovuto insere dei dati fittizzi...


>-- dati per una update
>DECLARE @var1 int = 1;
>DECLARE @var2 int = 2;
>DECLARE @var3 datetime = GETDATE();
>DECLARE @var4 varchar(20) = 'PROVA';
>
>MERGE #tempDestination DEST
>USING (SELECT @var1, @var2, @var3, @var4) SRC (New_id, New_valore,
>New_tempo, New_stringa)
>ON SRC.New_id = DEST.id
>WHEN MATCHED THEN
> UPDATE
> SET
> valore = SRC.New_valore
> , tempo = SRC.New_tempo
> , stringa = SRC.New_stringa
>WHEN NOT MATCHED THEN
> INSERT (valore, tempo, stringa)
> VALUES (SRC.New_valore, SRC.New_tempo, SRC.New_stringa);
>
>-- dopo merge per modifica
>SELECT * FROM #tempDestination TD;
>
>/*
>id valore tempo stringa
>----------- ----------- ----------------------- --------------------
>1 2 2012-05-25 12:20:56.087 PROVA AGGIORNATO
>IL RECORD CON ID 1
>2 2 NULL
>3 3 NULL

La tabella SCR che poi la usi per eseguire una sorta di join e poi un ON SRC.New_id = DEST.id...dove la dichiari oppure basta scrivere: "USING (SELECT @var1, @var2, @var3, @var4) SRC (New_id, New_valore,
>New_tempo, New_stringa)" e lui in automatico la crea in memoria.....


>-- dati per una insert
>SET @var1 = 5;
>SET @var2 = 2;
>SET @var3 = GETDATE();
>SET @var4 = 'PROVA';
>
>-- rieseguo merge
>MERGE #tempDestination DEST
>USING (SELECT @var1, @var2, @var3, @var4) SRC (New_id, New_valore,
>New_tempo, New_stringa)
>ON SRC.New_id = DEST.id
>WHEN MATCHED THEN
> UPDATE
> SET
> valore = SRC.New_valore
> , tempo = SRC.New_tempo
> , stringa = SRC.New_stringa
>WHEN NOT MATCHED THEN
> INSERT (valore, tempo, stringa)
> VALUES (SRC.New_valore, SRC.New_tempo, SRC.New_stringa);
>
>-- dopo merge per inserimento
>SELECT * FROM #tempDestination TD;
>
>/*
>id valore tempo stringa
>----------- ----------- ----------------------- --------------------
>1 2 2012-05-25 12:20:56.087 PROVA
>2 2 NULL
>3 3 NULL
>4 2 2012-05-25 12:20:56.093 PROVA INSERITO
>IL NUOVO RECORD CON ID 5
>*/

stando al codice e se ho capito bene con un semplice codice di questo:

MERGE #tempDestination DEST
USING (SELECT @var1, @var2, @var3, @var4) SRC (New_id, New_valore,
New_tempo, New_stringa)
ON SRC.New_id = DEST.id
WHEN MATCHED THEN
UPDATE
SET
valore = SRC.New_valore
, tempo = SRC.New_tempo
, stringa = SRC.New_stringa
WHEN NOT MATCHED THEN
INSERT (valore, tempo, stringa)
VALUES (SRC.New_valore, SRC.New_tempo, SRC.New_stringa);


Se trova dei record lui che soddisfa i criteri passati esegue un update altrimenti una insert?

Ovviamente i miei parametri li passo alle variabili Declare....

Quindi creo una bella stored con all'interno questo codice e poi da vb la richiamo con le Using e il gioco è fatto perche con una sola stored eseguo in teoria due ipotetiche nella classica maniera...giusto?

Senti nel tuo post precedente mi dicevi che dovevo eseguire nel mio codice un dispose di un oggetto, quale?
Fosse che ad ogni fine di Using devo eseguire un dispose sul SqlCommand? così pulisco l'oggetto e quando eseguo un altro using successivo l'oggetto è pulito? Anche se credevo che la chiusura dello using pulisse l'oggetto...pertanto dovrei eseguire anche un dispose dell'oggetto che esegue l'apertura del db?



Ciao e grazie
Cirillo Fabio
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/
http://wnetsoftware.blogspot.com

alx_81 Profilo | Guru

>In teoria questa tua tabella temp potrebbe nella mia situazione
>essere la vera tabella del db dovre salevrò o aggiornerò i dati
sì, è una ipotetica destinazione

>Non capisco perchè in questa tabella temp hai dovuto insere dei dati fittizzi...
a titolo di esempio, per farti vedere che posso sia aggiornare i presenti che inserire nuovi

>La tabella SCR che poi la usi per eseguire una sorta di join
>e poi un ON SRC.New_id = DEST.id...dove la dichiari oppure basta
>scrivere: "USING (SELECT @var1, @var2, @var3, @var4) SRC (New_id,
>New_valore,>New_tempo, New_stringa)" e lui in automatico la crea in memoria.....
non c'è da dichiararla, è creata al volo con uno statement SELECT, se scrivessi in una nuova query SELECT 1,2, otterresti un resultset di un record con due campi senza nome che valgono 1 e 2.
Creo con una select al volo il resultset, il cui alias è SRC, per usarlo comodamente poi più avanti.

>Se trova dei record lui che soddisfa i criteri passati esegue un update altrimenti una insert?
la ON definisce la chiave di match, se non hai match (sorgente con una riga che non esiste in destinazione) inserisci, altrimenti aggiorni.

>Quindi creo una bella stored con all'interno questo codice e
>poi da vb la richiamo con le Using e il gioco è fatto perche
>con una sola stored eseguo in teoria due ipotetiche nella classica
>maniera...giusto?
è solo un modo per fare una UPSERT (update/insert) senza usare IF, è un nuovo statement, VB non c'entra nulla.
Non focalizzarti su using o costrutti sul biz.. Per te sul codice è una stored procedure. La Using fa dispose automatico di oggetti che devono essere detachati.
Non mettere insieme le cose.

>Senti nel tuo post precedente mi dicevi che dovevo eseguire nel
>mio codice un dispose di un oggetto, quale?
?? Using, se la stai usando, è perchè l'oggetto che istanzi deve essere "pulito" per bene.

>Fosse che ad ogni fine di Using devo eseguire un dispose sul
>SqlCommand? così pulisco l'oggetto e quando eseguo un altro using
>successivo l'oggetto è pulito? Anche se credevo che la chiusura
>dello using pulisse l'oggetto...pertanto dovrei eseguire anche
>un dispose dell'oggetto che esegue l'apertura del db?
Ma no! leggiti bene la documentazione della Using. Ti risponderai da solo.

--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

trinity Profilo | Guru

Ok leggere bene la guida dello Using..invece per il merge pur leggendo le vari eguide una cosetta non mi entra in testa :(

ossia faccio un esempio sul mio codice reale in modo tale che capisco meglio

supponiamo quando segue:

Ho questa tabella:

CREATE TABLE [dbo].[Albergo](
[Codalb] [int] NOT NULL,
[Descrizione] [varchar](250) NULL,
[Citta] [varchar](250) NULL,
[Tel] [varchar](50) NULL,
CONSTRAINT [PK_Albergo] PRIMARY KEY CLUSTERED
(
[Codalb] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]


POi ecco i record già presenti:

Insert into dbo.albergo (codalbergo,descrizione,citta,tel) Values (1,'albergo prova_1','Terracina','0773/700000')
Insert into dbo.albergo (codalbergo,descrizione,citta,tel) Values (2,'albergo prova_2','Terracina','0773/700000')

Ok nel mio modo cosa avrei fatto:

Avrei eseguito una query per controllare se il record albergo prova_1 esiste, ed in base al risultato valorizzavo una variabile, poi successivamente in base al valore della variabile con delle if se questa fosse stata =0 eseguiva una insert dei dati nuovi che gli passavo altrimenti un'update...diciamo come questo esempio:

CREATE PROCEDURE [dbo].[gest_albergo] ( @CodAlb Int, @desc varchar, @citta varchar, @tel varchar ) AS declare @flag as int begin select @flag=case when codalb >0 then 1 else 2 end from dbo.Albergo where Codalb=@codalb end If @flag=1 --aggiorno BEGIN UPDATE dbo.albergo SET Tel=@tel WHERE Codalb=@CodAlb END If @flag=2 --inserisco BEGIN Insert into dbo.albergo (codalb,descrizione,citta,tel) Values (@codalb,@desc,@citta,@tel) END


adesso prendendo in esame come di solito mi comportavo di fronte a questa situazione se volessi fare il merge x me la tabella di destinazione sarebbe rappresentata dalla tabella albergo ma la tabella source quale sarebbe? dovrei eseguire prima uan select di tutta le tabella e il result utilizzarla come source?
Ti prego se puoi farmi un esempio con i miei codici capirei meglio :)

Ciao e grazie della disponibilità
Cirillo Fabio
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/
http://wnetsoftware.blogspot.com

alx_81 Profilo | Guru

>Ti prego se puoi farmi un esempio con i miei codici capirei meglio
CREATE PROCEDURE [dbo].[gest_albergo_temp] @CodAlb int , @desc varchar , @citta varchar , @tel varchar AS MERGE dbo.Albergo DEST USING (SELECT @CodAlb, @desc, @citta, @tel) SRC (CodAlb_New, Desc_New, Citta_New, Tel_New) ON SRC.CodAlb_New = DEST.codalb WHEN MATCHED THEN UPDATE SET citta = SRC.Citta_New , descrizione = SRC.Desc_New , tel = SRC.Tel_New WHEN NOT MATCHED THEN INSERT (CodAlb, Citta, Descrizione, Tel) VALUES (SRC.CodAlb_New, SRC.Citta_New, SRC.Desc_New, SRC.Tel_New); END; GO
--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi

trinity Profilo | Guru

Grazie mille..
senti al volo mica hai il link dove posso leggere la documentazione della Using?

Ciao e grazie

Cirillo Fabio
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/
http://wnetsoftware.blogspot.com

alx_81 Profilo | Guru

>senti al volo mica hai il link dove posso leggere la documentazione della Using?
http://msdn.microsoft.com/en-us/library/htd05whh(v=vs.100).aspx
--
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.microsoft.com/profiles/Alessandro.Alpi
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5