Valutazione 4.87/ 5 (100.00%) 5838 voti

Condividi:        

MS SQL e INSERT di record non presenti

Problemi di HTML? Di PHP, ASP, .NET, JSP, Perl, SQL, JavaScript, Visual Basic..?
Vuoi realizzare programmi in C, C++, Java, Ruby o Smalltalk, e non sai da che parte cominciare?
Entra qui e troverai le risposte!

Moderatori: Triumph Of Steel, archimede

MS SQL e INSERT di record non presenti

Postdi Dylan666 » 04/06/14 23:47

Ciao a tutti, prima di tutto scusatemi se sarà prolisso ma lo scenario è un po' complesso.
In soldoni ho un problema nel modificare una query di INSERT.
La situazione è questa: ho due tabelle che chiameremo Tabella1 e Tabella2, una contenenti degli Ordini e l'altra delle Distinte.
In ciascuna delle 2 tabelle ha due colonne, una con un ID univoco del documento (IdDocORD o IdDocDST) e l'altra con un numero (NumOrd o NumDis)
In un vista chiamata "Vista_Correlazione" ho la corrispondenza tra i due tipi di documenti in base al loro numero.
La vista è fatta di 2 colonne chiamate NRORD e NRDST dove a coppie sono indicati i documenti correlati
A me interessa leggere queste correlazioni, prendere i relativi IdDocORD e IdDocDST di queste coppie e scriverle in una tabella chiamata IdDocLinks.
Siccome le correlazioni sono bilaterali (cioè se l'ordine 23 corrisponde ala distina 57 è vero pure il contrario) sono ricorso a questi due INSERT

Codice: Seleziona tutto
INSERT Into IdDocLinks (IdDocSource, IdDocDest)
SELECT Tabella1.IdDoc as IdDocORD, Tabella2.IdDoc as IdDocDST
  FROM Vista_Correlazione
join Tabella1 on NumOrd  = NRORD
join Tabella2 on NumDis  = NRDST

INSERT Into IdDocLinks (IdDocDest, IdDocSource)
SELECT Tabella1.IdDoc as IdDocORD, Tabella2.IdDoc as IdDocDST
  FROM Vista_Correlazione
join Tabella1 on NumOrd  = NRORD
join Tabella2 on NumDis  = NRDST


Se faccio girare il codice la prima volta è tutto ok.
Ma le correlazioni potrebbero aumentare dopo qualche ora e se rilancio quei comandi ho questo errore:
Violazione del vincolo PRIMARY KEY 'IdDocLinksPK'. Impossibile inserire la chiave duplicata nell'oggetto 'dbo.IdDocLinks'

Vorrei quindi poter rifare i due INSERT ma importando solo i record che non erano già presenti in IdDocLinks.
Ho provato a usare dei NOT EXISTS ma forse a causa del doppio join non sono riuscito a farlo funzionare.
Lo stesso dicasi di NOT IN o MERGE.
Quale soluzione mi suggerite?

Grazie
Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Sponsor
 

Postdi archimede » 05/06/14 09:56

C'è qualcosa che mi sfugge.

Hai una vista (o una tabella?) che contiene le coppie di idORD e idDST e vuoi creare una tabella che contiene le stesse informazioni?

Puoi postare 3 o 4 righe di esempio di tabella1, tabella2 e vista e il risultato che vorresti ottenere?

Ho la sensazione che in realtà ti basti una vista, non una nuova tabella.

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi Dylan666 » 05/06/14 10:37

la tabella che vado a popolare (che è IdDocLinks) non la posso cambiare con una vista per vari motivi.

Il concetto è che la vista chiamata Vista_Correlazione correla i documenti ma in base al loro numero e non al loro ID.
La procedura di INSERT serve a estrapolare dalle tabelle Tabella1 e Tabella2 i relativi ID di quei documenti e mettere queste coppie di ID in IdDocLinks.

Le INSERT sono 2 perchè se è vero che il documento con ID 23 e collegato col 57 è pure vero che viceversa il 57 è collegato col 23.
Ecco uno schema esemplificativo:
http://imageshack.com/a/img839/6929/5i6d.png

Il problema è: se rilancio quelle due insert per vedere se ci sono nuove correlazioni da inserire ricevo l'errore che è sopra.
Vorrei quindi modificare i due INSERT per aggiungere in IdDocLinks solo i record nuovi se presenti

PS: se fosse facile o meglio una soluzione con una vista mi andrebbe bene crearne una di "appoggio" e poi usarla per mettere sempre e solo i nuvi record in IdDocLinks
Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Postdi Dylan666 » 05/06/14 10:53

Scusa, il link alla immagine corretto è questo:
http://imageshack.com/a/img845/594/4ch4.png
Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Postdi Dylan666 » 05/06/14 11:15

Altra modifica alla immagine, c'era un errorino:
http://imageshack.com/a/img836/8440/9ua3.png
Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Postdi archimede » 05/06/14 11:36

Dylan666 ha scritto:la tabella che vado a popolare (che è IdDocLinks) non la posso cambiare con una vista per vari motivi.
Questo mi incuriosisce non poco, ma non vorrei andare fuori tema...

Suppongo sia un caso che nell'immagine di esempio i due campi di vista_correlazione abbiano sempre lo stesso valore, giusto?

Ora non ho tempo di fare molte prove, ma la prima stupidata che mi viene in mente è:

query_simple:
Codice: Seleziona tutto
select t1.iddocord iddocsource, t2.iddocdst iddocdest
  from tabella1 t1, tabella2 t2, vista_correlazione v
 where t1.numord = v.nrord
   and t2.numdis = v.nrdst;

query_doppi:
Codice: Seleziona tutto
select iddocsource, iddocdest
  from query_simple
  union
select iddocdest, iddocsource
  from query_simple;

A questo punto per me avresti finito. Se proprio vuoi duplicare questi dati:
Codice: Seleziona tutto
delete from iddoclinks;
insert into iddoclinks select + from query_doppi;
HTH.

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi Dylan666 » 05/06/14 12:03

archimede ha scritto:
Dylan666 ha scritto:la tabella che vado a popolare (che è IdDocLinks) non la posso cambiare con una vista per vari motivi.
Questo mi incuriosisce non poco, ma non vorrei andare fuori tema...

La tabella è in pratica in uso da un programma, non potendo modificare il programma devo mantenergli le tabelle che ha

Suppongo sia un caso che nell'immagine di esempio i due campi di vista_correlazione abbiano sempre lo stesso valore, giusto?

Hai assolutamente ragione, per chiarezza di chi ci leggerà ho rifatto la figura per bene:
http://imageshack.com/a/img841/9328/948s.png

Ora non ho tempo di fare molte prove, ma la prima stupidata che mi viene in mente è:

Vedendo i tuoi comandi (ma se sbaglio perdonami) non vedo dove si discriminano i nuovi record rispetto a quelli vecchi.
Cioè se mi appare una nuova coppia di valori nelli vista vista_correlazione vorrei che in IdDocLinks finisse solo questa nuova coppia di valori (più la stessa copia a elementi invertiti sempre per la biredizionalità).
Ho visto che tu fai un "delete from iddoclinks ma io vorrei evitarlo, sia per una questione di prestazioni sia perché in futuro la tabella potrebbe essere popolata anche per alcuni record da un altro processo (qundi lo script ricreerebbe solo i valori presi dalla vista e quelli di questo processo andrebbero persi).
Il comando che a naso va più vicino a quello che vorrei pare questo:
http://technet.microsoft.com/it-it/libr ... 05%29.aspx

Approfitto per dire che uso appunto MS SQL 2008
Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Postdi archimede » 05/06/14 12:14

Dylan666 ha scritto:La tabella è in pratica in uso da un programma, non potendo modificare il programma devo mantenergli le tabelle che ha
Se il programma la usa solo in lettura, puoi tranquillamente droppare la tabella e creare una vista con lo stesso nome. Se la usa anche in scrittura, allora mi sfugge come sta in piedi il tutto.
Dylan666 ha scritto:non vedo dove si discriminano i nuovi record rispetto a quelli vecchi.
Non lo faccio: cancello la tabella e riscrivo tutto (ovviamente con una query non dovresti preoccuparti di questo aspetto). Se non hai milioni di records non credo che perdi molto in performance, altrimenti quello che vai cercando è probabilmente questo.

HTH.

Alessandro

PS: mi era sfuggito "la tabella potrebbe essere popolata anche per alcuni record da un altro processo"; allora devi usare il MERGE direi.

PS2: o, in alternativa (esatta sintassi da verificare)
Codice: Seleziona tutto
insert into iddoclinks
select * from query_doppi where (iddocsource, iddocdest) not in (select iddocsource, iddocdest from iddoclinks);

PS3: ma quindi non cancelli MAI records dalla iddoclinks?
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi Dylan666 » 05/06/14 13:24

archimede ha scritto:
Dylan666 ha scritto:La tabella è in pratica in uso da un programma, non potendo modificare il programma devo mantenergli le tabelle che ha
Se il programma la usa solo in lettura, puoi tranquillamente droppare la tabella e creare una vista con lo stesso nome. Se la usa anche in scrittura, allora mi sfugge come sta in piedi il tutto.


La tabella IdDocLinks si può popolare in varie maniere. Una può essere interagire col programma tramite l'interfaccia grafica, un'altra è usando script (come sto facendo io).

Dylan666 ha scritto:non vedo dove si discriminano i nuovi record rispetto a quelli vecchi.
Non lo faccio: cancello la tabella e riscrivo tutto (ovviamente con una query non dovresti preoccuparti di questo aspetto). Se non hai milioni di records non credo che perdi molto in performance, altrimenti quello che vai cercando è probabilmente questo.

Ok, saresti così corstese da integrare quel comando nella mia queri dell'inizio?
Grazie

PS2: o, in alternativa (esatta sintassi da verificare)
Codice: Seleziona tutto
insert into iddoclinks
select * from query_doppi where (iddocsource, iddocdest) not in (select iddocsource, iddocdest from iddoclinks);

Questa la provo, potrebbe essere un'idea
PS3: ma quindi non cancelli MAI records dalla iddoclinks?

Adesso come adesso lancio i due INSERT all'inizio dopo un bel "delete from IdDocLinks" ma volevo fare uno step in più riscendo a capire se potevo evitarlo e riuscivo a mettere solo i record nuovi
Avatar utente
Dylan666
Moderatore
 
Post: 38040
Iscritto il: 18/11/03 16:46

Postdi archimede » 06/06/14 09:24

Dylan666 ha scritto:Questa la provo, potrebbe essere un'idea
Ha funzionato?

Alessandro
archimede
Moderatore
 
Post: 2755
Iscritto il: 07/11/02 12:41
Località: Genova


Torna a Programmazione


Topic correlati a "MS SQL e INSERT di record non presenti":


Chi c’è in linea

Visitano il forum: Nessuno e 3 ospiti