Con più domande
Sintassi UPDATE FROM da query

Domanda
-
Ho fatto questa semplice query:
DECLARE @GiorniAzzeramentoPesoUnitario AS INTEGERSELECT @GiorniAzzeramentoPesoUnitario = (SELECT ValoreOpzione FROM TBL_OPZIONI WHERE NomeOpzione = 'GiorniAzzeramentoPesoUnitario' )
SELECT c.IDArticolo, c.Fase, PesoUnitario, PesoControllato, DataRevisione, DateDiff(d,DataRevisione, GetDate()) AS DifferenzaGGFROM TBL_Articoli_Ciclo_Fasi c INNER JOIN TBL_Articoli_Revisioni r ON c.IDArticolo = r.IDArticolo,(SELECT IDArticolo, COUNT(IDArticolo)AS Conteggio FROM dbo.TBL_Articoli_RevisioniGROUP BY IDArticoloHAVING COUNT(IDArticolo) > 1) ArticoliNonNuoviWHERE PesoControllato = 'false' AND c.Data_ultima_modifica < CONVERT(CHAR(8), GETDATE(), 112) and PesoUnitario > 0AND Attiva = 'TRUE' AND ArticoliNonNuovi.IDArticolo = r.IDArticoloAND DateDiff(d,DataRevisione, GetDate()) < @GiorniAzzeramentoPesoUnitario
Che mi tira fuori un elenco di articoli. Ora devo andare su tutti gli articoli del recordset a aggiornare il campo PesoUnitario della tabella TBL_Articoli_Ciclo_Fasi a NULL.Penso si possa usare l'UPDATE FROM in questo modo:
DECLARE @GiorniAzzeramentoPesoUnitario AS INTEGERSELECT @GiorniAzzeramentoPesoUnitario = (SELECT ValoreOpzione FROM TBL_OPZIONI WHERE NomeOpzione = 'GiorniAzzeramentoPesoUnitario' )
UPDATE TBL_Articoli_Ciclo_FasiSET TBL_Articoli_Ciclo_Fasi.PesoUnitario
FROM TBL_Articoli_Ciclo_Fasi c INNER JOIN TBL_Articoli_Revisioni r ON c.IDArticolo = r.IDArticolo,(SELECT IDArticolo, COUNT(IDArticolo)AS Conteggio FROM dbo.TBL_Articoli_RevisioniGROUP BY IDArticoloHAVING COUNT(IDArticolo) > 1) ArticoliNonNuoviWHERE PesoControllato = 'false' AND c.Data_ultima_modifica < CONVERT(CHAR(8), GETDATE(), 112) and PesoUnitario > 0AND Attiva = 'TRUE' AND ArticoliNonNuovi.IDArticolo = r.IDArticoloAND DateDiff(d,DataRevisione, GetDate()) < @GiorniAzzeramentoPesoUnitario
ma mi dice che la subquery ritorna più di un valore. Dove sbaglio?
Grazie
Tutte le risposte
-
Ciao Marco,
La parte 'From' restituisce più valori, ti suggerisco di usare CTE come una soluzione se si dispone di SQL Server 2005 o più:
prova questo query PF :
DECLARE @GiorniAzzeramentoPesoUnitario AS INTEGER SELECT @GiorniAzzeramentoPesoUnitario = (SELECT ValoreOpzione FROM TBL_OPZIONI WHERE NomeOpzione = 'GiorniAzzeramentoPesoUnitario' ) ;With CTE as ( SELECT c.IDArticolo, c.Fase, PesoUnitario, PesoControllato, DataRevisione, DateDiff(d,DataRevisione, GetDate()) AS DifferenzaGG FROM TBL_Articoli_Ciclo_Fasi c INNER JOIN TBL_Articoli_Revisioni r ON c.IDArticolo = r.IDArticolo, ( SELECT IDArticolo, COUNT(IDArticolo)AS Conteggio FROM dbo.TBL_Articoli_Revisioni GROUP BY IDArticolo HAVING COUNT(IDArticolo) > 1 ) ArticoliNonNuovi WHERE PesoControllato = 'false' AND c.Data_ultima_modifica < CONVERT(CHAR(8), GETDATE(), 112) and PesoUnitario > 0 AND Attiva = 'TRUE' AND ArticoliNonNuovi.IDArticolo = r.IDArticolo AND DateDiff(d,DataRevisione, GetDate()) < @GiorniAzzeramentoPesoUnitario ) update CTE set PesoUnitario=NULL
Best regards -
ma mi dice che la subquery ritorna più di un valore. Dove sbaglio?
Ciao marco,
Per rispondere adeguatamente avremmo bisogno della struttura di tutte le tabelle coinvolte comprensive di constraint (CREATE TABLE), alcune righe di prova per ogni tabella (INSERT INTO) ed il risultato atteso. Il primo errore che mi balza all'occhio è quella SET dove manca l'"=" con il relativo valore. Inoltre non vedo una JOIN tra la tabella che vuoi aggiornare e "quel casotto" nella clausola FROM, quindi manca una correlazione tra le righe da aggiornare ed il valore da assegnare alla colonna PesoUnitario.
Ciao!
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo
http://social.microsoft.com/Forums/it-IT/sqlserverit -
Ciao, grazie per la risposta, ma ho lo stesso identico errore. Se faccio la select sulla CTE mi tira fuori 10 records, se faccio l'update mi da l'errore ma perchè? se la select SELECT * FROM cte tira fuori i records. Se invece faccio: update cte set pesounitario = null mi da l'errore del "more than one 1 value"
-
-
Ciao Marco,
Il problema, con ogni probabilità, non nasce dalla sintassi dell'update ma da quella assegnazione iniziale del valore @GiorniAzzeramentoPesoUnitario che tu scrivi come:
SELECT @GiorniAzzeramentoPesoUnitario = (SELECT ValoreOpzione FROM TBL_OPZIONI WHERE NomeOpzione = 'GiorniAzzeramentoPesoUnitario' )
Questa sintassi è usata talvolta da alcuni dba e ha vantaggi e svantaggi. In particolare il vantaggio e lo svantaggio principale coincidono e assumono un valore positivo o negativo a seconda di come la si guardi.
Confrontiamo le due sintassi standard utilizzate per questo tipo di estrazione:
1) SELECT @GiorniAzzeramentoPesoUnitario = (SELECT ValoreOpzione FROM TBL_OPZIONI WHERE NomeOpzione = 'GiorniAzzeramentoPesoUnitario' )
2) SELECT @GiorniAzzeramentoPesoUnitario = ValoreOpzione FROM TBL_OPZIONI WHERE NomeOpzione = 'GiorniAzzeramentoPesoUnitario'
La seconda è di sicuro la più usata e forse la più moderna. Dato il recordset dei risultati della query, per ogni record, viene assegnato al parametro il valore. Alla fine dell'esecuzione della query quindi, il parametro @GiorniAzzeramentoPesoUnitario è popolato con l'ultimo valore che gli è stato assegnato, dove questo "ultimo" è da intendere in modo piuttosto vago a seconda di come il recordset è stato estratto e alle opzioni di parallelizzazione adottate del query optimizer. In ogni caso la query non da mai errore. Data l'aleatorietà del risultato e lo spreco inutile di risorse è ampiamente preferibile una query del tipo:
3) SELECT top 1 @GiorniAzzeramentoPesoUnitario = ValoreOpzione FROM TBL_OPZIONI WHERE NomeOpzione = 'GiorniAzzeramentoPesoUnitario'
che di fatto assegna al parametro un valore non determinabile a priori (nemmeno aggiungendo una order by!) tra quelli per cui NomeOpzione = 'GiorniAzzeramentoPesoUnitario' .
La sintassi 1 invece garantisce la generazione dell'errore se la select estrae più di un valore. Questo può essere visto come un difetto poichè ovviemente si incontra un'eccezione ma anche un pregio perchè segnala l'aleatorietà dell'assegnazione.
Detto in soldoni, a mio avviso, esistono più valori di TBL_OPZIONI per cui NomeOpzione = 'GiorniAzzeramentoPesoUnitario'.
Per risolvere, la cosa più sensata desumibile dal nome della tabella e dei campi è eliminare i doppioni di NomeOpzione in TBL_OPZIONI e immediatamente(!) aggiungere un vincolo di univocità sul campo.
Se invece la tua architettura prevede proprio che più OPZIONI abbiano il medesimo NomeOpzione devi riscrivere l'assegnazione di @GiorniAzzeramentoPesoUnitario in modo che non vada in errore se desideri un assegnamento "casuale" oppure aggiungendo parametri che specifichino esattamente quale Opzione vuoi.
marc.