2013-01-10 28 views
6

Şimdiye kadar bir süredir web’e bakıyordum ve istediğime benzer bir şeye rastlayamıyor gibiyim. Sorgumu yazdığım yolla ilgili bir şey olduğunu biliyorum, ancak herhangi bir yardım memnuniyetle karşılanacaktır.MYSQL INSERT veya UPDATE IF

Yapmak ne çalışıyorum temellerini şudur:

  • Güncelleme bir öğe yoksa o O vardır
  • varlığı söz

    • bir tabloya bazı öğeler yerleştirin

      isim, barkod, öğe, miktar, yer, fiyat ve tarihe

      : formatındaadı - Belirli bir öğe için ancak birkaç yerde olarak öğeyi kullanılabilir - - birkaç sıra halinde barkod kullanılabilir barkod aynıdır fakat Adını miktar içerir - kendini açıklayıcı yeri - Bu farklı yerlerde olabilir fiyat - bu belirli bir öğeye bağlı date - son kez bu ürün satın alındı ​​

      Zor olan şey, bir "isim" farklı fiyatlar için farklı yerlerde çeşitli öğelere (barkod ve öğe) sahip olabilir. Fikir, bir müşterinin belirli bir zamanda bir ürünü ne kadar satın aldığını görebilmesidir, dolayısıyla ne kadar satış yapmaları gerektiğini bilirler.

      Ancak, satın aldıkları fiyat, fiyatın önceki bir satın alma işleminden farklı olması durumunda, tabloda başka bir satır oluşturmaları için değişebilir.

      Her şeyin ardındaki fikir, her bir yerde her bir öğenin ne kadar bir "ad" aldığını ve daha sonra satın aldıkları fiyatı ve en son satın aldıklarını kaydetmektir.

      Bunun mantıklı olmasını umuyorum. psuedo kodunda

      :

      Insert into table if does not exist 
          - name, barcode, item, quantity, location, price and date 
          If name, barcode, item, location and price are the same 
          - Update quantity and date (if more recent) 
      

    cevap

    11

    Birincisi, ad, barkod, öğe, konum ve fiyat üzerinde bir UNIQUE kısıtlamayı ekleyin.

    ALTER TABLE tableX 
        ADD CONSTRAINT tableX_UQ 
        UNIQUE (name, barcode, item, location, price) ; 
    

    Sonra INSERT INTO ... ON DUPLICATE KEY UPDATE kullanabilirsiniz:


    REPLACE

    INSERT INTO tableX 
        (name, barcode, item, location, price, quantity, date) 
    VALUES 
        (?, ?, ?, ?, ?, ?, ?) 
    ON DUPLICATE KEY UPDATE 
        quantity = CASE WHEN VALUES(date) > date 
           THEN quantity + VALUES(quantity)  -- add quantity 
           ELSE quantity       -- or leave as it is 
          END 
    , date = CASE WHEN VALUES(date) > date 
           THEN VALUES(date) ;      -- set date to new date 
           ELSE date        -- or leave as it is 
          END 
    
    da kullanılabilir ancak (eğer yabancı anahtarlar varsa özellikle önemli) davranışlarında farklılıklar vardır. Ayrıntılar için, bu soruyu “INSERT IGNORE” vs “INSERT … ON DUPLICATE KEY UPDATE” ve INSERT IGNORE arasındaki farklar anlatılmaktadır @Bill Kawin tarafından cevap, INSERT ... ON DUPLICATE KEY ve REPLACE bakın.

    +0

    Fantastik, ancak bunu güncellemeyi başarabildim, eğer sadece güncellemeyi güncellemek istiyorsam, eğer mevcut olanı daha yeniyse, ne eklenmeli? – roadkill247

    +0

    Ve daha yeni değilse, tarihi olduğu gibi bırakın? Ve sadece miktarı değiştirmek? Ya da değiştirilmemiş her ikisini de bırakın (yani bu durumda hiçbir şey yapmayın)? –

    +0

    Merhaba ypercude, eğer tarih daha yeni değilse, o zaman değiştirilmemiş her ikisi de – roadkill247

    4

    Mysql'de replace sözdizimini kullanabilirsiniz.

    Ancak bu, benzersiz olması gereken alanlar üzerinde benzersiz bir dizinle çalışır.

    alter <yourtable> add unique index(name, barcode, item, location, price); 
    

    ardından ekleme/güncelleme sözdizimi saklı ait

    replace into <yourtable> (name, barcode, item, quantity, location, price, date) 
    VALUES('name1', 'barcode1', 2, 'location1', 12.0, '25/12/2012'); 
    

    DÜZENLEME

    Örnek olacaktı:

    Yani böyle benzersiz bir dizin oluşturmak zorundayız prosedür (basitleştirilmiş ve test edilmemiş):

    DELIMITER && 
    DROP PROCEDURE IF EXISTS MyBase.UpdateOrInsert $$ 
    CREATE PROCEDURE MyBase.UpdateOrInsert 
    (
        IN _name VARCHAR(10), 
        IN _barcode VARCHAR(50), 
        IN _quantity INTEGER 
        IN _date DATE 
    ) 
    
    DECLARE existingDate DATE default NULL; 
    BEGIN 
    
    SELECT date 
    INTO existingDate 
    FROM <yourTable> where name = _name and barcode = _barcode; 
    
    if (existingDate IS NULL) then 
        insert into <yourtable> (name, barcode, quantity, date) VALUES(_name, _barcode, _qantity, _date); 
    else 
        if (existingDate < _date) then 
        update <yourtable> 
        set quantity = _quantity, 
         date = _date 
        where name = _name 
        and barcode = _barcode; 
        end if; 
    end if; 
    END && 
    
    +0

    Cevabınız için teşekkür ederiz, başka bir yararlı cevap, ancak buna ek olarak, eğer miktar sadece tarih daha yenise o zaman tablodaki mevcut olanı güncellemeyi eklemek isterse? Bir XML dosyasını ayrıştırırken, bazı veriler yeniden okunıyor – roadkill247

    +0

    @ roadkill247 Bunu bir yudcube cevabı ile yapamazsın ... Saklı bir prosedür için gitmen gerektiğini söylemeliyim. . Ya da, xml dosyanızın ayrıştırılmasında, veritabanına gitmeden önce bunu yönetin ... Neden benzersiz dizini (her iki cevabın da tabanı), "daha büyük"/"düşük" koşullar yerine, tekliği yönetebilir. –

    +0

    Hızlı yanıt için teşekkürler. Bir üçüncü tarafın sağladığı gibi değiştiremediğim XML saklı bir prosedür dediğinizde tam olarak ne demek istiyorsunuz? – roadkill247

    1

    Sonunda bulduğum tüm yardımların yardımı sayesinde sonunda bulduğum her ikisi de çok yakındı. Aşağıdakileri bulunuz:

    INSERT INTO `stock` 
        (name, barcode, item, quantity, location, price, date) 
    VALUES 
        (?,?,?,?,?,?,?)       
    ON DUPLICATE KEY UPDATE 
        quantity = CASE WHEN 
           VALUES(date) < $date 
           THEN quantity + $quantity 
           ELSE quantity 
           END, 
        date = CASE WHEN 
           VALUES(date) < $date 
           THEN VALUES(date) 
           ELSE $date 
           END 
    
    +0

    , bununla birlikte, küçük bir miktar değer kullandığımda ilginç bir şeye rastladım, ancak bu, kullanılan tarihin eşit olduğu tarih olsa bile, büyük miktarlarda miktar güncellenir. – roadkill247