T-SQL di Insert o update

Ho una domanda per quanto riguarda le prestazioni di SQL Server.

Supponiamo di avere una tabella persons con le seguenti colonne: id, name, surname.

Ora, voglio inserire una nuova riga nella tabella. La regola è la seguente:

  1. Se id non è presente nella tabella, quindi inserire la riga.
  2. Se id è presente, quindi aggiornare.

Ho due soluzioni:

Primo:

update persons
  set id[email protected]p_id, name[email protected]p_name, surname[email protected]p_surname
where id[email protected]p_id
if @@ROWCOUNT = 0 
  insert into persons(id, name, surname)
  values (@p_id, @p_name, @p_surname)

Secondo:

if exists (select id from persons where id = @p_id)
  update persons
    set id[email protected]p_id, name[email protected]p_name, surname[email protected]p_surname
  where id[email protected]p_id
else
  insert into persons(id, name, surname)
  values (@p_id, @p_name, @p_surname)

Quello che è un approccio migliore? Mi sembra che sia la seconda scelta, per aggiornare una riga, questo deve essere cercato in due tempi, mentre la prima opzione – solo una volta. Ci sono altre soluzioni al problema? Sto utilizzando MS SQL 2000.

  • non sono sicuro, ma vorrei solo fare un if ((COUNT(*) ) > 0) quindi aggiornamento per la seconda opzione
InformationsquelleAutor Markus | 2010-02-16

 

5 Replies
  1. 8

    Entrambi funzionano bene, ma io di solito uso l’opzione 2 (pre-mssql 2008), poiché legge un po ‘ più chiaramente. Io non lo stress sulle prestazioni sia qui…Se diventa un problema, è possibile utilizzare NOLOCK in exists clausola. Anche se prima di iniziare a utilizzare NOLOCK ovunque, assicurarsi di aver coperto tutte le basi (indici e immagine grande architettura roba). Se sapete di essere l’aggiornamento di ogni elemento che più di una volta, allora si potrebbe pagare a considerare l’opzione 1.

    Opzione 3 è quello di non utilizzare distruttivo aggiornamenti. Ci vuole più lavoro, ma fondamentalmente si inserisce una nuova riga ogni modifica dei dati (non aggiornare o eliminare dalla tabella) e hanno una vista che seleziona tutte le più recenti righe. È utile se si desidera che la tabella contiene una storia di tutti i suoi stati precedenti, ma può anche essere eccessivo.

  2. 12

    Opzione 1 mi sembra buono. Tuttavia, se siete su SQL Server 2008, è possibile utilizzare anche UNIRE, che può eseguire buona per UPSERT attività.

    Nota che si può desiderare una transazione esplicita e il XACT_ABORT opzione per tali compiti, in modo che la transazione consistenza rimane nel caso di un problema o concomitante cambiamento.

    • Non è chiaro da tali documenti come utilizzare questo con VALUES, invece di unire le righe di un’altra tabella. Mi può dare un esempio?
    • si può sempre sostituire una (sola lettura) la tabella con i VALORI, utilizzare il seguente invece della tabella di riferimento: (VALUES (1,'a'),(2,'b')) AS v(i,s)
  3. 3

    Con l’obiettivo di essere un po ‘ più ASCIUTTO, evitare la scrittura dei valori lista due volte.

    begin tran
    insert into persons (id)
    select @p_id from persons
     where not exists (select * from persons where id = @p_id)
    
    update persons
    set name[email protected]p_name, surname[email protected]p_surname
    where id = @p_id
    
    commit

    Colonne name e surname devono essere nullable.

    Transazione significa che nessun altro utente potrà mai vedere il “vuoto” record.

    Edit: pulitura

    • Elegante, ma si dovrà anche inserire il valore per ogni non null campo nella tabella.
    • Vero. Io tendo ad evitare ogni uso funzionale di not null. L’applicazione deve essere abbastanza tappo caricando i valori null per importanti settori
    • La mia soluzione finale alla fine la logica in PHP, per put – un tentativo di inserire, e se non riesce con $sqlErrors[0][1] == 2627, faccio un aggiornamento completo
    • Accidentalmente downvoted e non si rendono conto fino a quando un po ‘ più tardi. Vorrei eliminare il mio downvote, si può fare qualsiasi tipo di modifica per la tua risposta, in modo che mi permette di farlo?
    • Grazie compagno. Ho fatto un manichino modificare, dare un colpo
  4. 2

    Che si potrebbe utilizzare @@RowCount per vedere se l’aggiornamento ha fatto nulla. Qualcosa come:

        UPDATE MyTable
           SET SomeData = 'Some Data' WHERE ID = 1
        IF @@ROWCOUNT = 0
          BEGIN
            INSERT MyTable
            SELECT 1, 'Some Data'       
          END

Lascia un commento