Merge sql o stored procedure separate?

venerdì 05 luglio 2013 - 11.23
Tag Elenco Tags  VB.NET  |  .NET 4.0  |  SQL Server 2008 R2

trinity Profilo | Guru

Salve,
ho una tabella anagrafica clienti ed una tabella movimenti. Quando un mio cliente deve inserire i movimenti prima di tutto va ad inserire l'anagrafica del cliente, se non esiste esegue una insert se esiste esegue un update nel caso anche che dovesse cambiare dei parametri nell'anagrafica stessa.
Ora le mie domande sono le seguenti:

1) è possibile con il merge sql gestire come target e come source al stessa tabella? Cioè io devo inserire o aggiornare il record del cliente se ovviamente esiste oppure no senza far riferimento a nessuna altra tabella.
2) nel mio caso se il merge potesse gestire un'unica tabella come target e come source è meglio utilizzare il merge oppure utilizzare due stored separate che eseguono l'insert o l'update del record, in quest'ultimo caso ovviamente dovrei utilizzare anche una terza stored di select per vedere se il record del cliente esiste oppure no.


questo è il codice merge che ho scritto:

BEGIN
Merge dbo.tab_clienti As T Using (Select idcliente From tab_clienti Where idstruttura=@idstruttura) As S On (T.idstruttura=S.idstruttura) When Matched Then Update Set T.cognome=@cognome, T.nome=@nome WHEN NOT MATCHED BY TARGET THEN Insert (T.idstruttura, T.idcliente, T.idtitolo, T.cognome, T.nome, T.sesso, T.datanascita, T.codfiscale, T.indirizzo, T.telefono, T.fax, T.cellulare, T.email, T.idcittadinanza, T.idluogonascita, T.idluogoresidenza, T.iddocumento, T.ndocumento, T.idluogodocumento, T.note) Values (@idstruttura, @idcliente, @idtitolo, @cognome, @nome, @sesso, @datanascita, @codfiscale, @indirizzo, @telefono, @fax, @cellulare, @email, @idcittadinanza, @idluogonascita, @idluogoresidenza, @iddocumento, @ndocumento, @idluogodocumento, @note) OUTPUT $action, Inserted.*; END

e mi esce questo avviso di errore: Msg 10739, Level 15, State 1, Procedure merge, Line 35
The insert column list used in the MERGE statement cannot contain multi-part identifiers. Use single part identifiers instead.

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

alx_81 Profilo | Guru

>Salve,
ciao Fabio

>1) è possibile con il merge sql gestire come target e come source
>al stessa tabella? Cioè io devo inserire o aggiornare il record
>del cliente se ovviamente esiste oppure no senza far riferimento
>a nessuna altra tabella.
come source userei un parametro tabella e poi farei la merge con esso. Un esempio è il seguente:

USE tempdb; GO CREATE TABLE dbo.Anagrafica ( ID int PRIMARY KEY CLUSTERED , Nome varchar(30) NOT NULL , Cognome varchar(30) NOT NULL , Anni tinyint NOT NULL ); GO INSERT INTO dbo.Anagrafica (ID, Nome, Cognome, Anni) VALUES (1, 'Alessandro', 'Alpi', 32), (2, 'Michael', 'Denny', 29), (3, 'Fabio', 'Cirillo', 25) GO CREATE TYPE dbo.AnagraficaTable AS TABLE ( ID int PRIMARY KEY CLUSTERED , Nome varchar(30) NOT NULL , Cognome varchar(30) NOT NULL , Anni tinyint NOT NULL ); GO CREATE PROCEDURE dbo.proc_Anagrafica_Merge @Utenti dbo.AnagraficaTable READONLY AS BEGIN SET NOCOUNT ON; MERGE dbo.Anagrafica DEST USING ( SELECT ID , Nome , Cognome , Anni FROM @Utenti ) SRC ON (SRC.ID = DEST.ID) WHEN MATCHED THEN UPDATE SET Nome = SRC.Nome , Cognome = SRC.Cognome , Anni = SRC.Anni WHEN NOT MATCHED THEN INSERT (ID, Nome, Cognome, Anni) VALUES (SRC.ID, SRC.Nome, SRC.Cognome, SRC.Anni); END; GO -- resultset prima dell'esecuzione SELECT ID , Nome , Cognome , Anni FROM dbo.Anagrafica; -- popolamento del tipo per passarlo alla sp DECLARE @u dbo.AnagraficaTable; INSERT INTO @u (ID, Nome, Cognome, Anni) VALUES (3, 'Fabio', 'Cirillo', 20) -- faccio l'utente Fabio Cirillo più giovane :) INSERT INTO @u (ID, Nome, Cognome, Anni) VALUES (4, 'Alessandro', 'Romanini', 32) -- questo non esiste -- chiamo la sp EXEC dbo.proc_Anagrafica_Merge @Utenti = @u; -- risultati dopo l'esecuzione SELECT ID , Nome , Cognome , Anni FROM dbo.Anagrafica; GO -- pulizia DROP PROCEDURE dbo.proc_Anagrafica_Merge; GO DROP TYPE dbo.AnagraficaTable; GO DROP TABLE dbo.Anagrafica; GO

>2) nel mio caso se il merge potesse gestire un'unica tabella
>come target e come source è meglio utilizzare il merge oppure
>utilizzare due stored separate che eseguono l'insert o l'update
>del record, in quest'ultimo caso ovviamente dovrei utilizzare
>anche una terza stored di select per vedere se il record del
>cliente esiste oppure no.
la merge è molto efficiente e ti permette di utilizzare la stessa transazione, in più, come hai visto nell'esempio sopra, puoi lavorare con un set, il che è un vero grande vantaggio.

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

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

trinity Profilo | Guru

perchè hai creato quest atabella?
>CREATE TYPE dbo.AnagraficaTable AS TABLE
>(
> ID int PRIMARY KEY CLUSTERED
> , Nome varchar(30) NOT NULL
> , Cognome varchar(30) NOT NULL
> , Anni tinyint NOT NULL
>);
>GO
>
>CREATE PROCEDURE dbo.proc_Anagrafica_Merge
> @Utenti dbo.AnagraficaTable READONLY
Perchè hai settato a readonly?


Comunque stando all'esempio che mi hai postato e in base ai miei reali dati analizzando il tutto la mia stored con la merge dovrebbe essere composta così:

prima creo questa tabella:

CREATE TYPE dbo.Tab_clientiTable AS TABLE
con tutti i campi.

Poi creo la stored in questo modo:

CREATE PROCEDURE [dbo].[merge] @utente dbo.tab_clientiTable ReadOnly AS BEGIN SET NOCOUNT ON; MERGE dbo.Tab_clienti DEST USING ( SELECT idstruttura , idcliente , Cognome , nome , sesso , datanascita , idluogonascita , idluogoresidenza , iddocumento , ndocumento , idluogodocumento FROM @Utente ) SRC ON (SRC.ID = DEST.ID) WHEN MATCHED THEN UPDATE SET Nome = SRC.Nome , Cognome = SRC.Cognome , sesso = SRC.sesso , datanascita=SRC.datanascita , idluogonascita=SRC.idluogonascita , idluogoresidenza=SRC.idluogoresidenza , iddocumento=SRC.iddocumento , ndocumento=SRC.idndocumento , idluogodocumento=SRC.idluogodocumento WHEN NOT MATCHED THEN INSERT (idstruttura , idcliente , Cognome , nome , sesso , datanascita , idluogonascita , idluogoresidenza , iddocumento , ndocumento , idluogodocumento) VALUES (SRC.idstruttura , SRC.idcliente , SRC.Cognome , SRC.nome , SRC.sesso , SRC.datanascita , SRC.idluogonascita , SRC.idluogoresidenza , SRC.iddocumento , SRC.ndocumento , SRC.idluogodocumento) END;

è giusta come sintassi?

Una curiosità non mi ricordo a cosa serve la sintassi: SET NOCOUNT ON;

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

alx_81 Profilo | Guru

>perchè hai creato quest atabella?
è un tipo tabella, il tipo che poi passo alla stored procedure

>Perchè hai settato a readonly?
questione di sintassi, se passi un tipo tabella deve essere specificato readonly

>Comunque stando all'esempio che mi hai postato e in base ai miei
>reali dati analizzando il tutto la mia stored con la merge dovrebbe
>essere composta così:
>è giusta come sintassi?
direi di sì, provala e lo vedi tu stesso

>Una curiosità non mi ricordo a cosa serve la sintassi: SET NOCOUNT ON;
evita che l'esecuzione della sp torni messaggi tipo "x rows affected", la doc è qui http://msdn.microsoft.com/it-it/library/ms189837.aspx

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

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

trinity Profilo | Guru

Ultima domanda Alex, al parametro @utente a cui gli dovrei passare il valore che prendo dai campi input, nel tuo esempio dichiari la variabile @u in questo modo: DECLARE @u dbo.AnagraficaTable; e poi la passi alla stored che esegue la merge. Adesso pertanto le mie domande sono le seguenti:
1) Non sarebbe meglio passare dei parametri direttamente alla merge?
2) oppure è meglio salvare i dati presi dai campi input nella tabella per esempio dbo.AnagraficaTable e poi come fai te passi i dati alla merge? (ma in questo modo a livello di velocità non peggioriamo le cose) Poi nella tabella dbo.AnagraficaTable una volta scritti i dati e passati alla merge mi conviene eliminare il contenuto perchè calcola che l'inserimento o update della tabella anagrafica può avvenire da centinaia di clienti contemporaneamente che eseguo i loro inserimento dati, per questo sia opportuno eliminare i dati dalla tabella dbo.AnagraficaTable solo che nell'eliminazione devo eseguire una where altrimenti potrei andare a togliere anche i dati di altri clienti che eseguo nel contempo un inserimento dei dati...in pratica andrei a fare una cosa del genere dopo aver eseguito il merge

Delete dbo.AnagraficaTable where idcliente=@id.

3) Secondo te potrei utilizzare una sola stored dove all'interno salvo i dati nella teballa dbo.AnagraficaTable, poi passi i dati alla merge ed infine elimino i dati transitori della tabella dbo.AnagraficaTable, oppure eseguo 3 stored distinte che fanno il loro bel compito?

ultimissima domanda ma come si crea un indice NOCLUSTERED su la tabella dbo.AnagraficaTable, con lo stesso codice che si utilizza per le tabelle normali?

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

alx_81 Profilo | Guru

>1) Non sarebbe meglio passare dei parametri direttamente alla merge?
nel senso, evitare il param tabella ed usare i parametri singoli? Se sì, come sei più comodo, ma quel tipo di approccio è più innovativo e ti consente di fare ben altro che la semplice merge.. Puoi applicare logiche set based e non è poco.

>2) oppure è meglio salvare i dati presi dai campi input nella tabella per esempio dbo.AnagraficaTable e poi come fai te passi i dati alla merge? (ma in questo modo a livello di velocità non peggioriamo le cose)
Cosa significa questa domanda? Intendi, se è meglio come ti ho passato?

>Poi nella tabella dbo.AnagraficaTable una volta scritti i dati e passati alla merge
>mi conviene eliminare il contenuto perchè calcola che l'inserimento o update della
>tabella anagrafica può avvenire da centinaia di clienti contemporaneamente
>che eseguo i loro inserimento dati, per questo sia opportuno
>eliminare i dati dalla tabella dbo.AnagraficaTable solo che nell'eliminazione
>devo eseguire una where altrimenti potrei andare a togliere anche
>i dati di altri clienti che eseguo nel contempo un inserimento
>dei dati...in pratica andrei a fare una cosa del genere dopo
>aver eseguito il merge
Non ho capito? Quella dichiarazione avrà una chiamata differente per i vari utenti che la effettuano, no?
Non capisco cosa intendi in questo punto..

>3) Secondo te potrei utilizzare una sola stored dove all'interno
>salvo i dati nella teballa dbo.AnagraficaTable, poi passi i dati
>alla merge ed infine elimino i dati transitori della tabella
>dbo.AnagraficaTable, oppure eseguo 3 stored distinte che fanno
>il loro bel compito?
Non capisco perchè dovresti eliminare.. Quello è un parametro di tipo tabella, è un tipo strutturato e se hai la necessità di avere quel parametro chiamato in maniera differente, basta che cambi le insert prima di passarlo..

>ultimissima domanda ma come si crea un indice NOCLUSTERED su
>la tabella dbo.AnagraficaTable, con lo stesso codice che si utilizza
>per le tabelle normali?
è un tipo di dato table, non ecco i limiti direttamente dalla doc:

- A user-defined table type cannot be used as a column in a table or a field in a structured user-defined type.
- Alias types based on a user-defined table type
- The [NOT FOR REPLICATION] option is not allowed.
- CHECK constraints require a computed column to be persisted.
- The primary key on computed columns must be PERSISTED and NOT NULL.
- A nonclustered index cannot be created on a user-defined table type unless the index is the result of creating a PRIMARY KEY or UNIQUE constraint on the user-defined table type. (SQL Server enforces any UNIQUE or PRIMARY KEY constraint by using an index.)
- The user-defined table type definition cannot be modified after it is created.
- User-defined functions cannot be called within the definition of computed columns of a user-defined table type.

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

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

trinity Profilo | Guru

>>1) Non sarebbe meglio passare dei parametri direttamente alla merge?
>nel senso, evitare il param tabella ed usare i parametri singoli?
>Se sì, come sei più comodo, ma quel tipo di approccio è più innovativo
>e ti consente di fare ben altro che la semplice merge.. Puoi
>applicare logiche set based e non è poco.
ok ho capito
>>2) oppure è meglio salvare i dati presi dai campi input nella tabella per esempio dbo.AnagraficaTable e poi come fai te passi i dati alla merge? (ma in questo modo a livello di velocità non peggioriamo le cose)
>Cosa significa questa domanda? Intendi, se è meglio come ti ho
>passato?
questa domanda mi hai risposto alla prima domanda alla fine :)

Comunque in pratica vorrei capire il metodo migliore ossia fare tutto in un'unica stored cioè passare i dati da code behind alla dbo.AnagraficaTable e poi quest'ultima passare i dati alla merge, oppure eseguire due stored ben distinti prima quella che salva i dati nella table dbo.AnagraficaTable e poi quella che la passa alla merge.

Secondo certamente le dichiarazioni nella table dbo.AnagraficaTable hanno chiamate differenti per ogni clienti tanto è vero che io ho creato una table del genere:

CREATE TYPE [dbo].[ClientiTable] AS TABLE( [ID] [int] NOT NULL, [idstruttura] [int] NOT NULL, [idtitolo] [tinyint] NOT NULL, [cognome] [varchar](30) NOT NULL, [nome] [varchar](30) NOT NULL, [sesso] [bit] NOT NULL, [datanascita] [smalldatetime] NOT NULL, [codfiscale] [varchar](16) NOT NULL, [indirizzo] [varchar](50) NOT NULL, [telefono] [varchar](15) NOT NULL, [cellulare] [varchar](15) NOT NULL, [fax] [varchar](15) NOT NULL, [email] [varchar](150) NOT NULL, [idcittadinanza] [smallint] NOT NULL, [idluogonascita] [smallint] NOT NULL, [idluogoresidenza] [smallint] NOT NULL, [iddocumento] [smallint] NOT NULL, [ndocumento] [varchar](15) NOT NULL, [idluogodocumento] [smallint] NOT NULL, [note] [text] NOT NULL, PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (IGNORE_DUP_KEY = OFF) ) GO

dove c'è la colonna id che è la chiave primaria ma anche la colonna idstruttura che identifica il cliente...proprio per questo motivo volevo indicizzare la colonna idstruttura ma non so come fare.

Il discorso dell'eliminazione dei dati della table te l'ho chiesto perchè quin io devo gestire migliaia di record se non milioni pertanto pensavo che fosse più opportuno una volta che la table ha passato i dati alla merge che venisse ripulita altrimenti non diventerebbe enorme? Calcola che alla fine la tabella clienti ossia la tabella su cui la merge lavora per eseguire l'insert o update è la reale tabella che conterrà i dati anagrafici di ogni singolo clienti (dei miei clienti)

una cosa quando citi: "Quello è un parametro di tipo tabella, è un tipo strutturato e se hai la necessità di avere quel parametro chiamato in maniera differente, basta che cambi le insert prima di passarlo.." è qui che mi confondo le idee, significa che se supponiamo 10 miei clienti registrano 100 utenti, questi ipotetici 100 record nella table vengono tutti inseriti oppure come un classico parametro che registra il dato senza accodarlo?

Te che mi consigli?

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

alx_81 Profilo | Guru

>Comunque in pratica vorrei capire il metodo migliore ossia fare
>tutto in un'unica stored cioè passare i dati da code behind alla
>dbo.AnagraficaTable e poi quest'ultima passare i dati alla merge,
>oppure eseguire due stored ben distinti prima quella che salva
>i dati nella table dbo.AnagraficaTable e poi quella che la passa
>alla merge.
il secondo caso mi sembra faccia inutilmente la prima operazione

>dove c'è la colonna id che è la chiave primaria ma anche la colonna
>idstruttura che identifica il cliente...proprio per questo motivo
>volevo indicizzare la colonna idstruttura ma non so come fare.
se proprio ti serve un indice (e solo le analisi di performance) te lo possono dire realmente, puoi sempre scalare in n modi:
- splittare le chiamate facendo chunk di dati e non tutto insieme
- appoggiare i dati in una temp table dentro alla sp e poi indicizzare la temp table

>Il discorso dell'eliminazione dei dati della table te l'ho chiesto
>perchè quin io devo gestire migliaia di record se non milioni
>pertanto pensavo che fosse più opportuno una volta che la table
>ha passato i dati alla merge che venisse ripulita altrimenti
>non diventerebbe enorme? Calcola che alla fine la tabella clienti
>ossia la tabella su cui la merge lavora per eseguire l'insert
>o update è la reale tabella che conterrà i dati anagrafici di
>ogni singolo clienti (dei miei clienti)
Qui nascerebbe un grosso problema di network, perchè passare milioni di righe tra ado.net e sql costa in termini di rete.. e tanto.
Ti conviene trovare una via per splittare le logiche e non fare tutto in una volta.

>una cosa quando citi: "Quello è un parametro di tipo tabella,
>è un tipo strutturato e se hai la necessità di avere quel parametro
>chiamato in maniera differente, basta che cambi le insert prima
>di passarlo.." è qui che mi confondo le idee, significa che se
>supponiamo 10 miei clienti registrano 100 utenti, questi ipotetici
>100 record nella table vengono tutti inseriti oppure come un
>classico parametro che registra il dato senza accodarlo?
è un parametro. Quindi si comporta come un parametro intero o stringa.
Solo che è una struttura.

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

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

trinity Profilo | Guru

>>Comunque in pratica vorrei capire il metodo migliore ossia fare
>>tutto in un'unica stored cioè passare i dati da code behind alla
>>dbo.AnagraficaTable e poi quest'ultima passare i dati alla merge,
>>oppure eseguire due stored ben distinti prima quella che salva
>>i dati nella table dbo.AnagraficaTable e poi quella che la passa
>>alla merge.
>il secondo caso mi sembra faccia inutilmente la prima operazione
>
Quindi mi consigli un'unica stored dove all'interno passo i dati alla table e poi successivamente dalla table alla merge

>>dove c'è la colonna id che è la chiave primaria ma anche la colonna
>>idstruttura che identifica il cliente...proprio per questo motivo
>>volevo indicizzare la colonna idstruttura ma non so come fare.
>se proprio ti serve un indice (e solo le analisi di performance)
>te lo possono dire realmente, puoi sempre scalare in n modi:
>- splittare le chiamate facendo chunk di dati e non tutto insieme
>- appoggiare i dati in una temp table dentro alla sp e poi indicizzare
>la temp table
>
>>Il discorso dell'eliminazione dei dati della table te l'ho chiesto
>>perchè quin io devo gestire migliaia di record se non milioni
>>pertanto pensavo che fosse più opportuno una volta che la table
>>ha passato i dati alla merge che venisse ripulita altrimenti
>>non diventerebbe enorme? Calcola che alla fine la tabella clienti
>>ossia la tabella su cui la merge lavora per eseguire l'insert
>>o update è la reale tabella che conterrà i dati anagrafici di
>>ogni singolo clienti (dei miei clienti)
>Qui nascerebbe un grosso problema di network, perchè passare
>milioni di righe tra ado.net e sql costa in termini di rete..
>e tanto.
Ma qui dipende dal mio cliente che dovrebbe avere una rete abbastanza potente
>Ti conviene trovare una via per splittare le logiche e non fare
>tutto in una volta.
>
>>una cosa quando citi: "Quello è un parametro di tipo tabella,
>>è un tipo strutturato e se hai la necessità di avere quel parametro
>>chiamato in maniera differente, basta che cambi le insert prima
>>di passarlo.." è qui che mi confondo le idee, significa che se
>>supponiamo 10 miei clienti registrano 100 utenti, questi ipotetici
>>100 record nella table vengono tutti inseriti oppure come un
>>classico parametro che registra il dato senza accodarlo?
>è un parametro. Quindi si comporta come un parametro intero o
>stringa.
>Solo che è una struttura.
Capisco ma la cosa che mi sfugge se due clienti distinti usano la stored dove c'è l'utilizzo della table e del merge e scrivono per esempio 5 record ciascuno, nella struttura mi ritroverò 10 record di dati (distinti ovviamente da idcliente) oppure ogni volta che ciascun utente scrive i dati all'interno della struttura si resettano? Ti dico questo perchè vorrei capire si mi trovo poi di fronte ad una situazione di una struttura che contiene moltissimi record di dati inutili dato che c'è la reale tabella anagrafica che deve contenere tutti i dati
>
>Alessandro Alpi | SQL Server MVP
>MCP|MCITP|MCTS|MCT
>
>http://blogs.dotnethell.it/suxstellino
>http://suxstellino.wordpress.com
>http://mvp.microsoft.com/profiles/Alessandro.Alpi

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

trinity Profilo | Guru

Alex, sto creando la merge e quando vado a creare la stored mi esce un messaggio di errore che puoi vedere nell'immagine che ho allegato. Dove sbaglio?

488x397 79Kb

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

alx_81 Profilo | Guru

>Alex, sto creando la merge e quando vado a creare la stored mi
>esce un messaggio di errore che puoi vedere nell'immagine che
>ho allegato. Dove sbaglio?
ma hai provato a crearla? perchè se crei il tipo tabella da script e non aggiorni i metadati (CTRL-SHIFT-R) quegli errori li vedrai anche se va bene tutto.

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

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

alx_81 Profilo | Guru

>Capisco ma la cosa che mi sfugge se due clienti distinti usano
>la stored dove c'è l'utilizzo della table e del merge e scrivono
>per esempio 5 record ciascuno, nella struttura mi ritroverò 10
>record di dati (distinti ovviamente da idcliente) oppure ogni
>volta che ciascun utente scrive i dati all'interno della struttura
>si resettano? Ti dico questo perchè vorrei capire si mi trovo
>poi di fronte ad una situazione di una struttura che contiene
>moltissimi record di dati inutili dato che c'è la reale tabella
>anagrafica che deve contenere tutti i dati
la tabella è del database, quindi se viene riempita viene riempita.. è un normale comportamento, non ti seguo proprio..
è un normalissimo insert/update
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

trinity Profilo | Guru

Ti spiego, io ho una tabella clienti nella quale tutti i clienti scrivono e devono aggiornare i dati anagrafici dei loro rispettivi clienti, ovviamente i miei clienti sono distinti dalla colonna idstruttura e i loro clienti dalla colonna idcliente.
Quello che non riesco a capire è che non vorrei trovarmi nella situazione che in un database ci siano due tabelle che hanno gli stessi dati...La tabella creata come parametro se io ci salvo dei dati da poi passare alla merge e poi un altro cliente salva i suoi dati, ovviamente i dati vengono accodati, cioè vorrei capire che supponiamo il cliente Fabio scrive dati nella tabella parametro e poi successivamente dopo qualche giorno scrive altri dati, questi ultimi dati vengono accodati ai precedenti insieme a tutti i dati degli altri clienti? Per la tabella tab_clienti deve fare da tabella storica ossia contenere ed archiviare tutti i dati, non vorrei trovarmi nella situazione che la tabella parametro avesse migliaia di record di dati archiviati...E' questo che non riesco a capire....

ti posto la stored con la merge finita puoi dargli un'occhiata se ho fatto bene?

CREATE PROCEDURE [dbo].[Set_clienti] @idstruttura as int, @idcliente as int, @idtitolo as smallint, @cognome as varchar(30), @nome as varchar(30), @sesso as smallint, @datanascita as smalldatetime, @codfiscale as varchar(16), @indirizzo as varchar(50), @telefono as varchar(15), @cellulare as varchar(15), @fax as varchar(15), @email as varchar(150), @idcittadinanza as smallint, @idluogonascita as smallint, @idluogoresidenza as smallint, @iddocumento as smallint, @ndocumento as varchar(15), @idluogodocumento as smallint, @note as text, @cliente dbo.ClientiTable READONLY AS --INSERIMENTO ANAGRAFICA CLIENTE BEGIN DECLARE @user dbo.ClientiTable Insert Into @user ( ID, idstruttura, idtitolo, cognome, nome, sesso, datanascita, codfiscale, indirizzo, telefono, cellulare, fax, email, idcittadinanza, idluogonascita, idluogoresidenza, iddocumento, ndocumento, idluogodocumento, note ) Values ( @idcliente, @idstruttura, @idtitolo, @cognome, @nome, @sesso, @datanascita, @codfiscale, @indirizzo, @telefono, @cellulare, @fax, @email, @idcittadinanza, @idluogonascita, @idluogoresidenza, @iddocumento, @ndocumento, @idluogodocumento, @note ) SET NOCOUNT ON; MERGE dbo.Tab_clienti DEST USING ( Select ID, idstruttura, idtitolo, cognome, nome, sesso, datanascita, codfiscale, indirizzo, telefono, cellulare, fax, email, idcittadinanza, idluogonascita, idluogoresidenza, iddocumento, ndocumento, idluogodocumento, note From @cliente )SRC ON (SRC.ID=DEST.idcliente and SRC.idstruttura=DEST.idstruttura) WHEN MATCHED THEN Update Set idtitolo=SRC.idtitolo, cognome=SRC.cognome, nome=SRC.nome, sesso=SRC.sesso, datanascita=SRC.datanascita, codfiscale=SRC.codfiscale, indirizzo=SRC.indirizzo, telefono=SRC.telefono, cellulare=SRC.cellulare, fax=SRC.fax, email=SRC.email, idcittadinanza=SRC.idcittadinanza, idluogonascita=SRC.idluogonascita, idluogoresidenza=SRC.idluogoresidenza, iddocumento=SRC.iddocumento, ndocumento=SRC.ndocumento, idluogodocumento=SRC.idluogodocumento, note=SRC.note WHEN NOT MATCHED THEN Insert ( idcliente, idstruttura, idtitolo, cognome, nome, sesso, datanascita, codfiscale, indirizzo, telefono, cellulare, fax, email, idcittadinanza, idluogonascita, idluogoresidenza, iddocumento, ndocumento, idluogodocumento, note) Values ( SRC.Id, SRC.idstruttura, SRC.idtitolo, SRC.cognome, SRC.nome, SRC.sesso, SRC.datanascita, SRC.codfiscale, SRC.indirizzo, SRC.telefono, SRC.cellulare, SRC.fax, SRC.email, SRC.idcittadinanza, SRC.idluogonascita, SRC.idluogoresidenza, SRC.iddocumento, SRC.ndocumento, SRC.idluogodocumento, SRC.note ); END

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

alx_81 Profilo | Guru

>Quello che non riesco a capire è che non vorrei trovarmi nella
>situazione che in un database ci siano due tabelle che hanno
>gli stessi dati...La tabella creata come parametro se io ci salvo
>dei dati da poi passare alla merge e poi un altro cliente salva
>i suoi dati, ovviamente i dati vengono accodati, cioè vorrei
>capire che supponiamo il cliente Fabio scrive dati nella tabella
>parametro e poi successivamente dopo qualche giorno scrive altri
>dati, questi ultimi dati vengono accodati ai precedenti insieme
>a tutti i dati degli altri clienti?
Fabio è un parametro, e in quanto tale è in MEMORIA solo del chiamante, non è una tabella condivisa come se fosse una tabella del database. Si tratta solo di una struttura (tipo una classe) e di niente di più.
Quando l'utente 1 chiama, passa i suoi dati e come veicolo in memory usa il parametro tabella. Non è condivisa con nessuno.


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

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

trinity Profilo | Guru

Ho capito ed ora questo parametro se un cliente inserisce sempre più dati questi si accumulano nel parametro oppure gli ultimi dati inseriti sovrascrivono quelli precedenti? la mia paura è avere nel corso del tempo spazio e memoria occupata inutilmente
Cirillo Fabio
www.trycontact.com
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/
http://wnetsoftware.blogspot.com

alx_81 Profilo | Guru

>Ho capito ed ora questo parametro se un cliente inserisce sempre
>più dati questi si accumulano nel parametro oppure gli ultimi
>dati inseriti sovrascrivono quelli precedenti? la mia paura è
>avere nel corso del tempo spazio e memoria occupata inutilmente
Non credo in realtà tu abbia capito.
Ogni chiamata in cui riempi il parametro SERVE SOLO per passare alla sp il param, che poi MUORE.
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

trinity Profilo | Guru

ah quindi i dati nella table parametro si puliscono si svuota tutto.....


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

alx_81 Profilo | Guru

>ah quindi i dati nella table parametro si puliscono si svuota tutto.....
è un parametro e si comporta come tale quando muore, non esiste più. Ha solo una forma, che è definita dal tipo.

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

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

trinity Profilo | Guru

Scusa Alex ultima cosa.
Ho creato definitivamente la stored ma non mi salva i dati che gli passo nell'archivio e precisamente nella tabella tab_clienti...
ecco la stored:

CREATE PROCEDURE [dbo].[Set_clienti] @idstruttura as int, @idcliente as int, @idtitolo as tinyint, @cognome as varchar(30), @nome as varchar(30), @sesso as smallint, @datanascita as smalldatetime, @codfiscale as varchar(16), @indirizzo as varchar(50), @telefono as varchar(15), @cellulare as varchar(15), @fax as varchar(15), @email as varchar(150), @idcittadinanza as smallint, @idluogonascita as smallint, @idluogoresidenza as smallint, @iddocumento as smallint, @ndocumento as varchar(15), @idluogodocumento as smallint, @note as text, @cliente dbo.ClientiTable READONLY AS --INSERIMENTO ANAGRAFICA CLIENTE BEGIN DECLARE @user dbo.ClientiTable Insert Into @user ( ID, idstruttura, idtitolo, cognome, nome, sesso, datanascita, codfiscale, indirizzo, telefono, cellulare, fax, email, idcittadinanza, idluogonascita, idluogoresidenza, iddocumento, ndocumento, idluogodocumento, note ) Values ( @idcliente, @idstruttura, @idtitolo, @cognome, @nome, @sesso, @datanascita, @codfiscale, @indirizzo, @telefono, @cellulare, @fax, @email, @idcittadinanza, @idluogonascita, @idluogoresidenza, @iddocumento, @ndocumento, @idluogodocumento, @note ) SET NOCOUNT ON; MERGE dbo.Tab_clienti DEST USING ( Select ID, idstruttura, idtitolo, cognome, nome, sesso, datanascita, codfiscale, indirizzo, telefono, cellulare, fax, email, idcittadinanza, idluogonascita, idluogoresidenza, iddocumento, ndocumento, idluogodocumento, note From @cliente )SRC ON (SRC.ID=DEST.idcliente and SRC.idstruttura=DEST.idstruttura) WHEN MATCHED THEN Update Set idtitolo=SRC.idtitolo, cognome=SRC.cognome, nome=SRC.nome, sesso=SRC.sesso, datanascita=SRC.datanascita, codfiscale=SRC.codfiscale, indirizzo=SRC.indirizzo, telefono=SRC.telefono, cellulare=SRC.cellulare, fax=SRC.fax, email=SRC.email, idcittadinanza=SRC.idcittadinanza, idluogonascita=SRC.idluogonascita, idluogoresidenza=SRC.idluogoresidenza, iddocumento=SRC.iddocumento, ndocumento=SRC.ndocumento, idluogodocumento=SRC.idluogodocumento, note=SRC.note WHEN NOT MATCHED THEN Insert ( idcliente, idstruttura, idtitolo, cognome, nome, sesso, datanascita, codfiscale, indirizzo, telefono, cellulare, fax, email, idcittadinanza, idluogonascita, idluogoresidenza, iddocumento, ndocumento, idluogodocumento, note) Values ( SRC.Id, SRC.idstruttura, SRC.idtitolo, SRC.cognome, SRC.nome, SRC.sesso, SRC.datanascita, SRC.codfiscale, SRC.indirizzo, SRC.telefono, SRC.cellulare, SRC.fax, SRC.email, SRC.idcittadinanza, SRC.idluogonascita, SRC.idluogoresidenza, SRC.iddocumento, SRC.ndocumento, SRC.idluogodocumento, SRC.note ); END

ecco la tabella parametro:

CREATE TYPE [dbo].[ClientiTable] AS TABLE( [ID] [int] NOT NULL, [idstruttura] [int] NOT NULL, [idtitolo] [tinyint] NOT NULL, [cognome] [varchar](30) NOT NULL, [nome] [varchar](30) NOT NULL, [sesso] [bit] NOT NULL, [datanascita] [smalldatetime] NOT NULL, [codfiscale] [varchar](16) NOT NULL, [indirizzo] [varchar](50) NOT NULL, [telefono] [varchar](15) NOT NULL, [cellulare] [varchar](15) NOT NULL, [fax] [varchar](15) NOT NULL, [email] [varchar](150) NOT NULL, [idcittadinanza] [smallint] NOT NULL, [idluogonascita] [smallint] NOT NULL, [idluogoresidenza] [smallint] NOT NULL, [iddocumento] [smallint] NOT NULL, [ndocumento] [varchar](15) NOT NULL, [idluogodocumento] [smallint] NOT NULL, [note] [text] NOT NULL, PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (IGNORE_DUP_KEY = OFF) ) GO

ecco la tabella clienti

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

dove sbaglio?
Mica devo creare due stored un che inserisce i dati nel parametro tabella e un'altra che esegue il merge, ovviamente nella stored che salva in dati nel parametro richiamo la stored merge con un exec passando i valori del parametro.

alx_81 Profilo | Guru

>dove sbaglio?
eh devi debuggare.. Se la chiave di match è corretta devi capire perchè i dati che gli passi non vengono inseriti.
Fai prove al di fuori della stored procedure con dati di test.

>Mica devo creare due stored un che inserisce i dati nel parametro
>tabella e un'altra che esegue il merge, ovviamente nella stored
>che salva in dati nel parametro richiamo la stored merge con
>un exec passando i valori del parametro.
La merge fa la merge, ovvero dato un set di partenza, in base ad una chiave di match, fa le operazioni che chiedi tu (DELETE, INSERT, UPDATE).

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

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/profiles/Alessandro.Alpi

trinity Profilo | Guru

Ciao Alessandro,

dopo un bel pò di tempo mi sono di nuovo imbattuto nel merge sql e stavo rileggendo questo nostro post per rispolverare un pò la memoria.
Unico dubbio, quando si crea la tabella di tipo type è opportuno ogni volta al termine della stored eliminarla e quindi di conseguenza ogni volta che lancio la stored crearla? Oppure si può lasciare all'interno del database?
Anche perchè suppongo che i dati che vengono salvati in questa tabella non restano memorizzati o sbaglio?

Ciao Fabio

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

alx_81 Profilo | Guru

>Ciao Alessandro,
ciao

>Unico dubbio, quando si crea la tabella di tipo type è opportuno
>ogni volta al termine della stored eliminarla e quindi di conseguenza
>ogni volta che lancio la stored crearla? Oppure si può lasciare
>all'interno del database?
è un oggetto salvato sotto programmability/user defined table types, non c'è da dropparla, anche perchè non riesci a farlo.

>Anche perchè suppongo che i dati che vengono salvati in questa tabella non restano memorizzati o sbaglio?
ma certo che no, non è una tabella, è una struttura usata solo per farli passare i dati.

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

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/en-us/mvp/Alessandro%20Alpi-4014222

trinity Profilo | Guru

Grazie mille ciao
Cirillo Fabio
www.trycontact.com
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/
http://wnetsoftware.blogspot.com
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-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5