veritabanında benzersiz endeksli sütunu değerleri takas

oy
47

Bir veritabanı tablosu ve alanlar (değil birincil anahtar) üzerinde benzersiz bir dizin yaşıyor birine sahip. Şimdi iki satırlar için bu sütunu altında değerleri takas etmek istiyorum. Bu nasıl yapılabilir? Bildiğim İki kesmek şunlardır:

  1. Her iki satırları silin ve bunları yeniden takmak
  2. diğer bazı değer ve takas ile satırları güncelleyin ve daha sonra gerçek değerine güncelleyin.

Ama onlar sorununa uygun çözüm gibi görünmüyor gibi bunlar için gitmek istemiyorum. Birisi bana yardım edebilir mi?

Oluştur 03/08/2008 saat 10:55
kaynak kullanıcı
Diğer dillerde...                            


12 cevaplar

oy
21

Sihirli kelime DEFERRABLE burada:

DROP TABLE ztable CASCADE;
CREATE TABLE ztable
    ( id integer NOT NULL PRIMARY KEY
    , payload varchar
    );
INSERT IGNORE  INTO ztable(id,payload) VALUES (1,'one' ), (2,'two' ), (3,'three' );
SELECT * FROM ztable;


    -- This works, because there is no constraint
UPDATE ztable t1
SET payload=t2.payload
FROM ztable t2
WHERE t1.id IN (2,3)
AND t2.id IN (2,3)
AND t1.id <> t2.id
    ;
SELECT * FROM ztable;

ALTER TABLE ztable ADD CONSTRAINT OMG_WTF UNIQUE (payload)
    DEFERRABLE INITIALLY DEFERRED
    ;

    -- This should also work, because the constraint 
    -- is deferred until "commit time"
UPDATE ztable t1
SET payload=t2.payload
FROM ztable t2
WHERE t1.id IN (2,3)
AND t2.id IN (2,3)
AND t1.id <> t2.id
    ;
SELECT * FROM ztable;

SONUÇ:

DROP TABLE
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "ztable_pkey" for table "ztable"
CREATE TABLE
INSERT IGNORE  0 3
 id | payload
----+---------
  1 | one
  2 | two
  3 | three
(3 rows)

UPDATE 2
 id | payload
----+---------
  1 | one
  2 | three
  3 | two
(3 rows)

NOTICE:  ALTER TABLE / ADD UNIQUE will create implicit index "omg_wtf" for table "ztable"
ALTER TABLE
UPDATE 2
 id | payload
----+---------
  1 | one
  2 | two
  3 | three
(3 rows)
Cevap 15/09/2012 saat 13:38
kaynak kullanıcı

oy
8

Sana benim bildiğim herhangi bir SQL varyantında hayır 'takas' işlevi yoktur çözümü 2. gitmek gerektiğini düşünüyorum.

Düzenli olarak bunu yapmak gerekirse, ben yazılımın diğer kısımları bu verileri kullanarak nasıl bağlı çözüm 1 düşündürmektedir. Eğer dikkatli olmazsa her kilitleme sorunları olabilir.

Ama kısacası: Sağladığınız olanlardan daha başka bir çözüm yoktur.

Cevap 03/08/2008 saat 13:26
kaynak kullanıcı

oy
5

Geçici tablo UPDATE açıklamada kendisine katılmak kullanın: SQL Server ile çalışan başka bir yaklaşım vardır.

Sorun aynı değere sahip iki satır olmasından kaynaklanır aynı anda , ancak (yeni, benzersiz değerlere) seferde hem satırları güncellemek, hiçbir kısıtlama ihlali yoktur.

Sözde kod:

-- setup initial data values:
insert into data_table(id, name) values(1, 'A')
insert into data_table(id, name) values(2, 'B')

-- create temp table that matches live table
select top 0 * into #tmp_data_table from data_table

-- insert records to be swapped
insert into #tmp_data_table(id, name) values(1, 'B')
insert into #tmp_data_table(id, name) values(2, 'A')

-- update both rows at once! No index violations!
update data_table set name = #tmp_data_table.name
from data_table join #tmp_data_table on (data_table.id = #tmp_data_table.id)

Bu teknikle için Zengin H teşekkürler. - İşaret

Cevap 04/04/2012 saat 20:40
kaynak kullanıcı

oy
5

Andy Irving'in cevabı Ek

Bu bir kompozit anahtara sahip benzer bir durumda (SQL Server 2005) benim için çalıştı ve ben eşsiz kısıtlama parçası olan bir alan takas gerekir.

Anahtar: PID, LNUM rec1: 10, 0 REC2: 10, 1 rec3: 10, 2

ve ben sonucudur ki LNUM takas gerekir

Anahtar: PID, LNUM rec1: 10, 1 REC2: 10, 2 rec3: 10, 0

SQL gerekli:

UPDATE    DOCDATA    
SET       LNUM = CASE LNUM
              WHEN 0 THEN 1
              WHEN 1 THEN 2 
              WHEN 2 THEN 0 
          END
WHERE     (pID = 10) 
  AND     (LNUM IN (0, 1, 2))
Cevap 10/12/2008 saat 13:19
kaynak kullanıcı

oy
2

Ben aynı sorun var. İşte PostgreSQL benim önerdiği yaklaşım. Benim durumumda, benim benzersiz dizin benim satırlarda açıkça kullanıcı düzeni tanımlayan bir dizi değerdir. Kullanıcı daha sonra Değişiklikleri göndermek, bir web-app etrafında satırları olarak karıştırılır.

Ben tetik "önce" eklemeyi planlıyorum. Benim eşsiz indeks değeri her güncellendiğinde o tetik olarak, ben başka bir satır zaten benim yeni değeri tutan olmadığını görmek için bakacağız. Eğer öyleyse, ben onlara benim eski değer vermek ve onlarla etkili off değeri çalacak.

Ben PostgreSQL beni önce tetikleyici bu karıştır yapmanızı sağlayacaktır umuyorum.

Geri göndermek ve sen benim kilometre bildireceğiz.

Cevap 24/06/2009 saat 04:58
kaynak kullanıcı

oy
2

Eğer bu SQL Server çalışır güncelleştirmek istediğiniz iki sıra ve ... PK biliyorum varsayarsak, diğer ürünler için konuşamıyor. SQL deyimi düzeyinde atom (olması gereken):

CREATE TABLE testing
(
    cola int NOT NULL,
    colb CHAR(1) NOT NULL
);

CREATE UNIQUE INDEX UIX_testing_a ON testing(colb);

INSERT IGNORE  INTO testing VALUES (1, 'b');
INSERT IGNORE  INTO testing VALUES (2, 'a');

SELECT * FROM testing;

UPDATE testing
SET colb = CASE cola WHEN 1 THEN 'a'
                WHEN 2 THEN 'b'
                END
WHERE cola IN (1,2);

SELECT * FROM testing;

böylece gelen gidecek:

cola    colb
------------
1       b
2       a

için:

cola    colb
------------
1       a
2       b
Cevap 16/09/2008 saat 15:57
kaynak kullanıcı

oy
2

Ayrıca 2. Ben bu durumda bir şey bir işlemde sarmak için emin, buna rağmen iyi bahistir yanlış orta güncelleştirme gider diye düşünüyorum.

farklı değerlerle Benzersiz Endeksi değerlerini güncelleyerek için (madem sordun) alternatif diğer sıranın buna sıralar halinde diğer tüm değerleri güncelleştirmek olacaktır. Bunu yapmanız yalnız Benzersiz Endeksi değerlerini terk anlamına gelir ve sonunda, istediğiniz veriler oluşursa. durumda bir yabancı anahtar ilişkisi içinde diğer bazı tablo bu tabloyu, DB ilişkilerin tüm olduğu gibi durduğunu olsa dikkatli olun.

Cevap 03/08/2008 saat 14:22
kaynak kullanıcı

oy
1

1) adı kimlikleri geçiş

id    student 

1     Abbot   
2     Doris  
3     Emerson 
4     Green  
5     Jeames  

örnek girişi için, çıkış:

id öğrenci

1     Doris   
2     Abbot   
3     Green   
4     Emerson 
5     Jeames  

"Satır vaka n sayısında yönetecek nasıl ......"

Cevap 06/11/2018 saat 08:56
kaynak kullanıcı

oy
1

Oracle için orada bir seçenek, ERTELENEN olduğunu, ancak kısıtlama eklemek gerekir.

SET CONSTRAINT emp_no_fk_par DEFERRED; 

tüm oturum boyunca ertelenebilir olan TÜM kısıtlamaları erteleme için, ALTER SESSION SET kısıtlamaları = ERTELENEN deyimi kullanabilirsiniz.

Kaynak

Cevap 27/04/2016 saat 14:15
kaynak kullanıcı

oy
1

De SQL Server, MERGE deyimi normalde EŞSİZ ANAHTAR / INDEX kıracak satırları güncelleyebilirsiniz. (Merak ettim çünkü Sadece bu test etti.)

Ancak, gerekli sıralar w / MERGE tedarik etmek bir geçici tablo / değişkeni kullanmak zorunda olurdu.

Cevap 20/04/2012 saat 20:12
kaynak kullanıcı

oy
1

Oracle tam olarak bu çözer bütünlük denetimi ertelenmiş, ancak SQL Server veya MySQL ya mevcut değildir.

Cevap 19/03/2010 saat 20:29
kaynak kullanıcı

oy
0

Genellikle Kesinlikle benim tabloda hiçbir indeks olabilecek bir değerin düşünüyorum. Genellikle - benzersiz sütun değerleri için - bu gerçekten çok kolay. Örneğin, sütun position (birkaç elemanlarının sırası hakkında bilgi) değerleri için durum 0.

Sonra, bir değişkene değer A kopyalamak için değişkenden değer B ve daha sonra belirlenen değer B ile güncelleyebilirsiniz. İki sorgular, olsa daha iyi bir çözüm biliyorum.

Cevap 18/03/2017 saat 18:00
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more