UPDATE bölümünde kaynak tablosundaki değerleri kullanarak ON CONFLICT'li UPSERT


18

Verilen:

CREATE TABLE A (
PK_A INT8 NOT NULL,
A INT8,
PRIMARY KEY (PK_A)
);

CREATE TABLE B (
PK_B INT8 NOT NULL,
B INT8,
PRIMARY KEY (PK_B)
);

Bu sorgu:

insert into table_b (pk_b, b) 
select pk_a,a from table_a 
on conflict (b) do update set b=a;

aşağıdaki hataya neden olur:

ERROR:  column "a" does not exist
LINE 1: ...elect pk_a,a from table_a on conflict (b) do update set b=a;
                                                                 ^
HINT:  There is a column named "a" in table "*SELECT*", but it cannot be referenced from this part of the query.

İçeriğinden bahsederken güncelleme nasıl yapılır table_a?


5
CREATE TABLE A...tablo oluşturur a, değil table_a.
Abelisto

do update set b = a;bulamıyorum "a", "b" Tablosuna olup alt sorgusu için orada referans, denemek çünküdo update set b = (select a from a);
Patrick7

Yanıtlar:


25

Çoklu problemler.
Kurulumunuz genişletildi:

CREATE TABLE a (
  pk_a int PRIMARY KEY 
, a int
, comment text  -- added column to make effect clear
);

CREATE TABLE b (
  pk_b int PRIMARY KEY
, b int 
, comment text
);

INSERT INTO a VALUES (1, 11, 'comment from a')
                   , (2, 22, 'comment from a');

INSERT INTO b VALUES (1, 77, 'comment from b');

Bu çalışıyor:

INSERT INTO b (pk_b, b, comment) 
SELECT pk_a, a, comment
FROM   a 
ON     CONFLICT (pk_b) DO UPDATE  -- conflict is on the unique column
SET    b = excluded.b;            -- key word "excluded", refer to target column

Sonuç:

TABLE b;

 pk_b | b  |    comment
------+----+----------------
    1 | 11 | comment from b   -- updated
    2 | 22 | comment from a   -- inserted

Problemler

  1. Kafa karıştırıcı table_ave Ademo ( @Abelisto yorumladı gibi ).

    Yasal, küçük harfli, alıntılanmamış tanımlayıcıları kullanmak karışıklığı önlemeye yardımcı olur.

  2. Gibi @Ziggy söz , ON CONFLICTsadece gerçek çalışır benzersiz veya dışlama kısıtlama ihlalleri . Kullanım kılavuzu:

    İsteğe bağlı ON CONFLICTmadde, benzersiz bir ihlali veya hariç tutma kısıtlaması ihlali hatasını yükseltmek için alternatif bir işlem belirtir.

    Sonuç olarak, ON CONFLICT (b)çalışamaz, orada bir kısıtlama yoktur. ON CONFLICT (pk_b)İşler.

  3. Gibi @Ziggy ayrıca söz , kaynak tablo adları görünmez içinde UPDATEparçası. Kullanım kılavuzu:

    İçindeki SETve WHEREcümleleri ON CONFLICT DO UPDATEtablonun adını (veya takma adını) kullanarak mevcut satıra ve özel excludedtablo kullanılarak ekleme için önerilen satırlara erişebilir .

    Cesur vurgu benim.

  4. Parçadaki kaynak tablonun sütun adlarını da kullanamazsınız UPDATE. Hedef satırın sütun adları olmalıdır . Yani gerçekten istiyorsun:

    SET    b = excluded.b

    Kılavuz bir kez daha:

    Satır başına tüm BEFORE INSERTtetikleyicilerin etkilerinin hariç tutulan değerlere yansıtıldığına dikkat edin, çünkü bu efektler satırın ekleme dışında bırakılmasına katkıda bulunmuş olabilir.


Bu açıklama için teşekkürler, şimdi neden b = excluded.açalışamadığını biliyorum , resmi Docu'da biraz gizlendi.
Patrick7

"hariç tutulan" gibi aptallar için basit bir astar: eklemek veya tabloya devam etmek istediğiniz yeni gelen verileri gösterir.
user92674

8

PostgreSQL 9.5 ve sonraki sürümlerde üstbilgiler yaparken, diğer ad tarafından hariç tutulan verilere (eklenemeyen) başvurmalısınız excluded. Ayrıca, on conflictseçenek (pk_b)yerine : anahtarına başvurmalıdır (b). Örneğin.

insert into table_b (pk_b, b) 
select pk_a,a from table_a 
on conflict (pk_b) do update set b=excluded.b;

Daha fazla bilgi için resmi belgelere ya da upsert'e bu kolay girişe bakın .


Bu sorgu yok değil çalışır.
shx
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.