none
Sintassi UPDATE FROM da query RRS feed

  • Domanda

  • Ho fatto questa semplice query:

    DECLARE @GiorniAzzeramentoPesoUnitario AS INTEGER
    SELECT @GiorniAzzeramentoPesoUnitario = (SELECT ValoreOpzione FROM TBL_OPZIONI WHERE NomeOpzione = 'GiorniAzzeramentoPesoUnitario' )


    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

    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 INTEGER
    SELECT @GiorniAzzeramentoPesoUnitario = (SELECT ValoreOpzione FROM TBL_OPZIONI WHERE NomeOpzione = 'GiorniAzzeramentoPesoUnitario' )

    UPDATE TBL_Articoli_Ciclo_Fasi 
    SET 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_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

    ma mi dice che la subquery ritorna più di un valore. Dove sbaglio?


    Grazie
    martedì 7 dicembre 2010 08:39

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
    martedì 7 dicembre 2010 09:29
  • 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
    martedì 7 dicembre 2010 10:32
    Moderatore
  • 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"
    martedì 7 dicembre 2010 10:50
  • Ciao Lorenzo,

     

    si in effetti ho fatto un errore di copiatura:

     

    UPDATE TBL_Articoli_Ciclo_Fasi 
    SET TBL_Articoli_Ciclo_Fasi.PesoUnitario = 0

    I CREATE TABLE li preparo e ve li posto successivamente.

    Intanto grazie.

    martedì 7 dicembre 2010 11:42
  • 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.

    sabato 11 dicembre 2010 09:42