DBA: синхронизатсия ва воридотро босалоҳият ташкил кунед

Барои коркарди мураккаби маҷмӯи додаҳои калон (гуногун Равандҳои ETL: воридот, табдилдиҳӣ ва ҳамоҳангсозӣ бо манбаи беруна) аксар вақт эҳтиёҷ вуҷуд дорад муваккатан «дар хотир» ва фавран кор карда баромадан чизи ҳаҷм.

Вазифаи маъмулии ин гуна одатан чунин садо медиҳад: "Дар ҳамин ҷо шуъбаи бухгалтерй аз банки муштарй холй карда шудааст пардохтҳои охирини гирифташуда, шумо бояд онҳоро зуд ба вебсайт бор кунед ва онҳоро ба ҳисобҳои худ пайваст кунед."

Аммо вақте ки ҳаҷми ин "чизе" бо садҳо мегабайт чен карда мешавад ва хидмат бояд бо пойгоҳи додаҳо 24x7 кор кунад, таъсири зиёди тарафҳо ба вуҷуд меоянд, ки ҳаёти шуморо хароб мекунанд.
DBA: синхронизатсия ва воридотро босалоҳият ташкил кунед
Барои мубориза бо онҳо дар PostgreSQL (ва на танҳо дар он), шумо метавонед баъзе оптимизатсияҳоро истифода баред, ки ба шумо имкон медиҳанд ҳама чизро зудтар ва бо истеъмоли камтари захираҳо коркард кунед.

1. Ба куҷо фиристодан мумкин аст?

Аввалан, биёед муайян кунем, ки мо маълумотеро, ки мо мехоҳем "коркард" кунем, дар куҷо бор карда метавонем.

1.1. Ҷадвалҳои муваққатӣ (Ҷадвали муваққатӣ)

Аслан, барои PostgreSQL ҷадвалҳои муваққатӣ мисли ҳама гуна дигаранд. Аз ин рӯ, хурофот ба монанди "Ҳама чиз дар он ҷо танҳо дар хотира нигоҳ дошта мешавад ва он метавонад хотима ёбад". Аммо инчунин якчанд фарқиятҳои назаррас вуҷуд доранд.

"Фазои ном" -и шахсии шумо барои ҳар як пайвастшавӣ ба пойгоҳи додаҳо

Агар ду пайвастшавӣ кӯшиш кунед, ки дар як вақт пайваст шаванд CREATE TABLE x, он гоҳ касе бешубҳа ба даст меорад хатогии ғайримуқаррарӣ объектҳои базаи маълумотҳо.

Аммо агар ҳарду кӯшиш кунанд, ки иҷро кунанд CREATE TEMPORARY TABLE x, он гоҳ ҳарду онро ба таври муқаррарӣ иҷро мекунанд ва ҳама ба даст меоянд нусхаи шумо ҷадвалҳо. Ва дар байни онҳо ҳеҷ чизи умумӣ нахоҳад буд.

Ҳангоми ҷудошавӣ "худ несту нобуд"

Вақте ки пайвастшавӣ баста мешавад, ҳамаи ҷадвалҳои муваққатӣ ба таври худкор нест карда мешаванд, бинобар ин дастӣ DROP TABLE x ҳеҷ маъное нест, ҷуз...

Агар шумо кор карда истода бошед pgbouncer дар ҳолати транзаксия, он гоҳ базаи маълумот боварӣ дорад, ки ин пайвастшавӣ ҳоло ҳам фаъол аст ва дар он ин ҷадвали муваққатӣ ҳанӯз вуҷуд дорад.

Аз ин рӯ, кӯшиши аз нав сохтани он аз пайвасти дигар ба pgbouncer боиси хатогӣ мегардад. Аммо бо истифода аз ин метавон канорагирӣ кард CREATE TEMPORARY TABLE IF NOT EXISTS x.

Дуруст аст, ки ба ҳар ҳол ин корро накунед, зеро он гоҳ шумо метавонед "ногаҳон" маълумоти боқимондаи "соҳиби қаблӣ"-ро дар он ҷо пайдо кунед. Ба ҷои ин, беҳтар аст, ки дастурро хонед ва бубинед, ки ҳангоми сохтани ҷадвал илова кардан мумкин аст ON COMMIT DROP - яъне вақте ки муомилот анҷом мешавад, ҷадвал ба таври худкор нест карда мешавад.

Набудани такрорӣ

Азбаски онҳо танҳо ба пайвасти мушаххас тааллуқ доранд, ҷадвалҳои муваққатӣ такрор намешаванд. Аммо ин зарурати сабти дукаратаи маълумотро аз байн мебарад дар heap + WAL, бинобар ин INSERT/UPDATE/DELETE ба он тезтар аст.

Аммо азбаски ҷадвали муваққатӣ то ҳол ҷадвали "қариб оддӣ" аст, онро дар нусхабардорӣ низ сохтан мумкин нест. Ҳадди аққал ҳоло, гарчанде ки ямоқи мувофиқ муддати тӯлонӣ паҳн шудааст.

1.2. ЉАДВАЛИ БОШАД

Аммо чӣ бояд кард, масалан, агар шумо як намуди мураккаби ETL дошта бошед, ки онро дар як транзаксия иҷро кардан ғайриимкон аст, аммо шумо ба ҳар ҳол доред pgbouncer дар ҳолати транзаксия? ..

Ё ҷараёни маълумот он қадар калон аст, ки Дар як пайваст фарохмаҷрои кофӣ нест аз пойгоҳи додаҳо (хондан, як раванд барои як CPU)?..

Ё баъзе амалиётҳо идома доранд асинхронӣ дар робитаҳои гуногун?..

Дар ин ҷо танҳо як вариант вуҷуд дорад - муваккатан ҷадвали ғайримуваққатӣ эҷод кунед. Пун, ҳа. Яъне:

  • Ҷадвалҳои "худии ман"-ро бо номҳои ҳадди аксар тасодуфӣ сохтанд, то бо касе бурида нашавад
  • Эзоҳ: онҳоро бо маълумот аз манбаи беруна пур кард
  • Трансформатор: табдил дода шудааст, дар майдонҳои пайвасткунандаи калидӣ пур карда шудааст
  • сарборӣ: маълумоти тайёрро ба ҷадвалҳои мақсаднок рехтанд
  • ҷадвалҳои "ман" -ро нест карданд

Ва ҳоло - магасе дар равғани атрафшон. Дар асл, ҳама навиштаҷот дар PostgreSQL ду маротиба рӯй медиҳанд - аввал дар WAL, баъд ба бадани ҷадвал/indeks. Ҳамаи ин барои дастгирии ACID ва дуруст дидани маълумот байни анҷом дода мешавад COMMIT' чормагз ва ROLLBACK'муомилоти беэътибор.

Аммо ба мо ин лозим нест! Мо тамоми равандро дорем Ё комилан муваффақ буд ё не.. Фарқ надорад, ки чӣ қадар транзаксияҳои фосилавӣ вуҷуд доранд - мо ба "давом додани раванд аз миёна" манфиатдор нестем, хусусан вақте ки маълум нест, ки он дар куҷо буд.

Барои ин, таҳиягарони PostgreSQL, дар версияи 9.1, чунин чизеро ҷорӣ карданд Ҷадвалҳои UNLOGGGED:

Бо ин нишондод, ҷадвал ҳамчун сабтнашуда сохта мешавад. Маълумоте, ки ба ҷадвалҳои сабтнашуда навишта шудааст, аз журнали пешакии навиштан намегузарад (ниг. Боби 29), ки чунин ҷадвалҳоро ба вуҷуд меорад назар ба мукаррарй хеле тезтар кор мекунанд. Бо вуҷуди ин, онҳо аз нокомӣ эмин нестанд; дар сурати нокомии сервер ё қатъи фавқулодда, ҷадвали сабтнашуда ба таври худкор бурида мешавад. Илова бар ин, мундариҷаи ҷадвали сабтнашуда такрор нашудааст ба серверҳои ғулом. Ҳама шохисҳое, ки дар ҷадвали сабтнашуда сохта шудаанд, ба таври худкор хориҷ карда мешаванд.

Мухтасар гуем, хеле тезтар мешавад, аммо агар сервери базаи маълумотҳо "афтад", он ногувор хоҳад буд. Аммо ин чанд вақт рух медиҳад ва оё раванди ETL-и шумо медонад, ки чӣ гуна онро пас аз "эҳё кардани" базаи маълумот "аз миёна" дуруст ислоҳ кунед?..

Агар не, ва ҳолати дар боло овардашуда ба кори шумо монанд бошад, истифода баред UNLOGGED, аммо ҳеҷ гоҳ ин хосиятро дар ҷадвалҳои воқеӣ фаъол накунед, маълумоте, ки аз он барои шумо азиз аст.

1.3. ДАР БОРАИ КОМИТЕТ { ХОЗ КАРДАНИ САТРХО | ТАРТ}

Ин конструксия ба шумо имкон медиҳад, ки рафтори автоматиро ҳангоми анҷом додани транзаксия ҳангоми сохтани ҷадвал муайян кунед.

ба ON COMMIT DROP Ман аллакай дар боло навишта будам, он тавлид мекунад DROP TABLE, балки бо ON COMMIT DELETE ROWS вазъият ҷолибтар аст - он дар ин ҷо тавлид мешавад TRUNCATE TABLE.

Азбаски тамоми инфрасохтори нигоҳдории мета тавсифи ҷадвали муваққатӣ комилан ба ҷадвали муқаррарӣ монанд аст, пас Сохтани доимӣ ва нест кардани ҷадвалҳои муваққатӣ боиси «варамкунии» шадиди ҷадвалҳои система мегардад pg_class, pg_attribute, pg_attrdef, pg_depend,…

Акнун тасаввур кунед, ки шумо коргаре доред, ки ба пойгоҳи додаҳо пайвасти мустақим дорад, ки ҳар сония транзаксияи нав мекушояд, ҷадвали муваққатиро месозад, пур мекунад, коркард мекунад ва нест мекунад... Дар ҷадвалҳои система партовҳои зиёдатӣ ҷамъ мешаванд ва ин боиси тормози иловагӣ барои ҳар як амалиёт мегардад.

Умуман, ин корро накунед! Дар ин ҳолат он хеле самараноктар аст CREATE TEMPORARY TABLE x ... ON COMMIT DELETE ROWS онро аз давраи транзаксия хориҷ кунед - пас дар оғози ҳар як амалиёти нав ҷадвалҳо аллакай ҳастанд вуҷуд хоҳад дошт (зангро захира кунед CREATE), аммо холй мешавад, ба шарофати TRUNCATE (мо инчунин занги онро захира кардем) ҳангоми анҷом додани амалиёти қаблӣ.

1.4. МИСЛИ... аз ҷумла...

Ман дар аввал қайд кардам, ки яке аз ҳолатҳои маъмулии истифодаи ҷадвалҳои муваққатӣ навъҳои гуногуни воридот аст - ва таҳиякунанда бо хастагӣ рӯйхати майдонҳои ҷадвали мақсаднокро ба эъломияи муваққатии худ нусхабардорӣ мекунад...

Аммо танбалӣ муҳаррики пешрафт аст! Барои ҳамон сохтани ҷадвали нав "дар асоси намуна" он метавонад хеле соддатар бошад:

CREATE TEMPORARY TABLE import_table(
  LIKE target_table
);

Азбаски шумо метавонед дар ин ҷадвал маълумоти зиёде тавлид кунед, ҷустуҷӯи он ҳеҷ гоҳ зуд нахоҳад буд. Аммо роҳи ҳалли анъанавии ин вуҷуд дорад - индексҳо! Ва, ҳа, Ҷадвали муваққатӣ инчунин метавонад индексҳо дошта бошад.

Азбаски аксар вақт индексҳои зарурӣ бо индексҳои ҷадвали мақсаднок мувофиқат мекунанд, шумо метавонед танҳо нависед LIKE target_table INCLUDING INDEXES.

Агар ба шумо хам лозим бошад DEFAULT-арзишҳо (масалан, барои пур кардани арзишҳои асосии калидӣ), шумо метавонед истифода баред LIKE target_table INCLUDING DEFAULTS. Ё оддӣ - LIKE target_table INCLUDING ALL — нусхабардории пешфарзҳо, индексҳо, маҳдудиятҳо,...

Аммо дар ин ҷо шумо бояд фаҳмед, ки агар шумо эҷод кунед Ҷадвалро фавран бо индексҳо ворид кунед, пас боркунии маълумот вақти зиёдтар мегирадАгар шумо аввал ҳама чизро пур кунед ва танҳо пас аз он индексҳоро ҷамъ кунед - бубинед, ки ин чӣ гуна ин корро мекунад. pg_dump.

Дар кӯтоҳ, RTFM!

2. Чӣ тавр бояд навишт?

Биёед танҳо бигӯям - онро истифода баред COPY- ҷараён ба ҷои "пакет" INSERT, суръатбахшии баъзан. Шумо ҳатто метавонед бевосита аз файли пешакӣ тавлидшуда.

3. Чӣ тавр коркард карда мешавад?

Пас, биёед интро ба ин монанд кунем:

  • шумо ҷадвале доред, ки маълумоти муштарӣ дар базаи шумо нигоҳ дошта мешавад 1 миллион сабт
  • ҳар рӯз як муштарӣ ба шумо як нав мефиристад пурра "тасвир"
  • аз тачриба медонй, ки дам ба дам на бештар аз 10K сабтҳо тағир дода мешаванд

Мисоли классикии чунин вазъият аст Пойгоҳи KLADR — умуман адресхо бисьёранд, вале дар хар хафта боркашй тагьиротхо (номи посёлкахо, якчоя кардани кучахо, намуди хонахои нав) хатто дар микьёси республика хеле кам дида мешаванд.

3.1. Алгоритми синхронизатсияи пурра

Барои содда, биёед бигӯем, ки шумо ҳатто ба таҷдиди сохтори маълумот ниёз надоред - танҳо ҷадвалро ба шакли дилхоҳ оваред, яъне:

  • хориҷ кунед ҳама чизе, ки дигар вуҷуд надорад
  • навсозӣ хамаи он чи ки аллакай мавчуд буд ва бояд нав карда шавад
  • гузоред ҳама чизе, ки ҳанӯз рӯй надодааст

Чаро амалиётҳо бояд бо ин тартиб анҷом дода шаванд? Зеро ин аст, ки андозаи ҷадвал ҳадди аққал афзоиш меёбад (дар бораи MVCC дар хотир доред!).

НАЗОР КАРДАН АЗ dst

Не, албатта, шумо метавонед танҳо бо ду амалиёт муваффақ шавед:

  • хориҷ кунед (DELETE) хама чиз умуман
  • гузоред ҳама аз тасвири нав

Аммо дар айни замон, ба шарофати MVCC, Андозаи миз дуруст ду баробар зиёд мешавад! Гирифтани +1 миллион тасвири сабтҳо дар ҷадвал аз ҳисоби навсозии 10К, то ҳадде зиёдатист...

TRUNCATE дст

Таҳиягари ботаҷриба медонад, ки тамоми планшетро хеле арзон тоза кардан мумкин аст:

  • равшан аст (TRUNCATE) тамоми ҷадвал
  • гузоред ҳама аз тасвири нав

Усули самаранок аст, баъзан комилан татбиқшаванда, аммо мушкиле вуҷуд дорад... Мо муддати тӯлонӣ сабтҳои 1M-ро илова мекунем, аз ин рӯ мо наметавонем тамоми ин вақт ҷадвалро холӣ гузорем (чунон ки бидуни печонидани он дар як транзаксия рӯй медиҳад).

Ки маънои:

  • сар мекунем муомилоти дарозмуддат
  • TRUNCATE вогузор мекунад Дастрасӣ ба истисноӣ- блокировка
  • мо воридкуниро барои муддати тӯлонӣ анҷом медиҳем ва ҳама дар ин вақт ҳатто наметавонад SELECT

Чизе хуб намешавад...

ТАҒИРИ ЉАДВАЛ… ДИГАР НОМИ…/ЉАДВАЛРО ТАРК КАРДАН…

Алтернатива ин аст, ки ҳама чизро ба ҷадвали нави алоҳида пур кунед ва сипас онро ба ҷои ҷадвали кӯҳна иваз кунед. Якчанд чизҳои ночиз:

  • ҳанӯз ҳам Дастрасӣ ба истисноӣ, гарчанде ки вақт хеле камтар аст
  • ҳама нақшаҳои дархост/омори ин ҷадвал аз нав барқарор карда мешаванд, ANALYZE-ро иҷро кардан лозим аст
  • ҳама калидҳои хориҷӣ шикастаанд (ФК) ба миз

Як ямоқи WIP аз Саймон Риггс мавҷуд буд, ки пешниҳод кард, ки сохтани он ALTER-амалиёт барои иваз кардани ҷисми ҷадвал дар сатҳи файл, бе даст нарасондан ба омор ва FK, аммо кворум ҷамъоварӣ накард.

ТОҶИКИСТОН, НАВӢ, ДОДАН

Ҳамин тавр, мо ба варианти баста нашудани се амалиёт қарор медиҳем. Кариб се... Ин корро чй тавр самаранок ичро кардан мумкин аст?

-- все делаем в рамках транзакции, чтобы никто не видел "промежуточных" состояний
BEGIN;

-- создаем временную таблицу с импортируемыми данными
CREATE TEMPORARY TABLE tmp(
  LIKE dst INCLUDING INDEXES -- по образу и подобию, вместе с индексами
) ON COMMIT DROP; -- за рамками транзакции она нам не нужна

-- быстро-быстро вливаем новый образ через COPY
COPY tmp FROM STDIN;
-- ...
-- .

-- удаляем отсутствующие
DELETE FROM
  dst D
USING
  dst X
LEFT JOIN
  tmp Y
    USING(pk1, pk2) -- поля первичного ключа
WHERE
  (D.pk1, D.pk2) = (X.pk1, X.pk2) AND
  Y IS NOT DISTINCT FROM NULL; -- "антиджойн"

-- обновляем оставшиеся
UPDATE
  dst D
SET
  (f1, f2, f3) = (T.f1, T.f2, T.f3)
FROM
  tmp T
WHERE
  (D.pk1, D.pk2) = (T.pk1, T.pk2) AND
  (D.f1, D.f2, D.f3) IS DISTINCT FROM (T.f1, T.f2, T.f3); -- незачем обновлять совпадающие

-- вставляем отсутствующие
INSERT INTO
  dst
SELECT
  T.*
FROM
  tmp T
LEFT JOIN
  dst D
    USING(pk1, pk2)
WHERE
  D IS NOT DISTINCT FROM NULL;

COMMIT;

3.2. Пас аз коркарди воридот

Дар ҳамон KLADR, ҳамаи сабтҳои тағирёфта бояд ба таври иловагӣ тавассути коркарди пас аз коркард иҷро карда шаванд - ба эътидол овардан, калимаҳои калидӣ таъкид ва ба сохторҳои зарурӣ кам карда шаванд. Аммо шумо аз куҷо медонед - маҳз чӣ тағйир ёфтбе мураккаб кардани коди синхронизатсия, идеалӣ бе даст нарасондан ба он?

Агар дар вақти ҳамоҳангсозӣ танҳо раванди шумо дастрасии навиштан дошта бошад, пас шумо метавонед триггерро истифода баред, ки ҳамаи тағиротҳоро барои мо ҷамъ мекунад:

-- целевые таблицы
CREATE TABLE kladr(...);
CREATE TABLE kladr_house(...);

-- таблицы с историей изменений
CREATE TABLE kladr$log(
  ro kladr, -- тут лежат целые образы записей старой/новой
  rn kladr
);

CREATE TABLE kladr_house$log(
  ro kladr_house,
  rn kladr_house
);

-- общая функция логирования изменений
CREATE OR REPLACE FUNCTION diff$log() RETURNS trigger AS $$
DECLARE
  dst varchar = TG_TABLE_NAME || '$log';
  stmt text = '';
BEGIN
  -- проверяем необходимость логгирования при обновлении записи
  IF TG_OP = 'UPDATE' THEN
    IF NEW IS NOT DISTINCT FROM OLD THEN
      RETURN NEW;
    END IF;
  END IF;
  -- создаем запись лога
  stmt = 'INSERT INTO ' || dst::text || '(ro,rn)VALUES(';
  CASE TG_OP
    WHEN 'INSERT' THEN
      EXECUTE stmt || 'NULL,$1)' USING NEW;
    WHEN 'UPDATE' THEN
      EXECUTE stmt || '$1,$2)' USING OLD, NEW;
    WHEN 'DELETE' THEN
      EXECUTE stmt || '$1,NULL)' USING OLD;
  END CASE;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Акнун мо метавонем пеш аз оғози ҳамоҳангсозӣ триггерҳоро истифода барем (ё онҳоро тавассути ALTER TABLE ... ENABLE TRIGGER ...):

CREATE TRIGGER log
  AFTER INSERT OR UPDATE OR DELETE
  ON kladr
    FOR EACH ROW
      EXECUTE PROCEDURE diff$log();

CREATE TRIGGER log
  AFTER INSERT OR UPDATE OR DELETE
  ON kladr_house
    FOR EACH ROW
      EXECUTE PROCEDURE diff$log();

Ва он гоҳ мо оромона тамоми тағиротҳои ба мо лозимиро аз ҷадвалҳои гузоришҳо хориҷ мекунем ва онҳоро тавассути коркардкунандагони иловагӣ иҷро мекунем.

3.3. Воридоти маҷмӯаҳои алоқаманд

Дар боло мо ҳолатҳоеро баррасӣ кардем, ки сохторҳои додаҳои манбаъ ва макони таъинот якхела бошанд. Аммо чӣ мешавад, агар боргузорӣ аз системаи беруна формати аз сохтори нигоҳдории пойгоҳи додаи мо фарқкунанда дошта бошад?

Биёед мисоли нигоҳдории муштариён ва ҳисобҳои онҳоро гирем, варианти классикии "бисёр ба як":

CREATE TABLE client(
  client_id
    serial
      PRIMARY KEY
, inn
    varchar
      UNIQUE
, name
    varchar
);

CREATE TABLE invoice(
  invoice_id
    serial
      PRIMARY KEY
, client_id
    integer
      REFERENCES client(client_id)
, number
    varchar
, dt
    date
, sum
    numeric(32,2)
);

Аммо зеркашӣ аз манбаи беруна ба мо дар шакли "ҳама дар як" меояд:

CREATE TEMPORARY TABLE invoice_import(
  client_inn
    varchar
, client_name
    varchar
, invoice_number
    varchar
, invoice_dt
    date
, invoice_sum
    numeric(32,2)
);

Аён аст, ки маълумоти муштарӣ метавонад дар ин версия такрор карда шавад ва сабти асосӣ "ҳисоб" аст:

0123456789;Вася;A-01;2020-03-16;1000.00
9876543210;Петя;A-02;2020-03-16;666.00
0123456789;Вася;B-03;2020-03-16;9999.00

Барои модел, мо танҳо маълумоти санҷишии худро ворид мекунем, аммо дар хотир доред - COPY самараноктар!

INSERT INTO invoice_import
VALUES
  ('0123456789', 'Вася', 'A-01', '2020-03-16', 1000.00)
, ('9876543210', 'Петя', 'A-02', '2020-03-16', 666.00)
, ('0123456789', 'Вася', 'B-03', '2020-03-16', 9999.00);

Аввало, биёед он «буриш»-ҳоеро, ки «далелҳои» мо ба онҳо ишора мекунанд, қайд кунем. Дар ҳолати мо, ҳисобнома-фактураҳо ба мизоҷон муроҷиат мекунанд:

CREATE TEMPORARY TABLE client_import AS
SELECT DISTINCT ON(client_inn)
-- можно просто SELECT DISTINCT, если данные заведомо непротиворечивы
  client_inn inn
, client_name "name"
FROM
  invoice_import;

Барои дуруст пайваст кардани ҳисобҳо бо ID-и муштарӣ, мо аввал бояд ин идентификаторҳоро пайдо кунем ё тавлид кунем. Биёед майдонҳоро дар зери онҳо илова кунем:

ALTER TABLE invoice_import ADD COLUMN client_id integer;
ALTER TABLE client_import ADD COLUMN client_id integer;

Биёед усули ҳамоҳангсозии ҷадвали дар боло тавсифшударо бо як ислоҳи хурд истифода барем - мо ҳеҷ чизро дар ҷадвали мақсаднок нав намекунем ё нест намекунем, зеро мо муштариёнро "танҳо барои замима" ворид мекунем:

-- проставляем в таблице импорта ID уже существующих записей
UPDATE
  client_import T
SET
  client_id = D.client_id
FROM
  client D
WHERE
  T.inn = D.inn; -- unique key

-- вставляем отсутствовавшие записи и проставляем их ID
WITH ins AS (
  INSERT INTO client(
    inn
  , name
  )
  SELECT
    inn
  , name
  FROM
    client_import
  WHERE
    client_id IS NULL -- если ID не проставился
  RETURNING *
)
UPDATE
  client_import T
SET
  client_id = D.client_id
FROM
  ins D
WHERE
  T.inn = D.inn; -- unique key

-- проставляем ID клиентов у записей счетов
UPDATE
  invoice_import T
SET
  client_id = D.client_id
FROM
  client_import D
WHERE
  T.client_inn = D.inn; -- прикладной ключ

Дар асл, ҳама чиз аст invoice_import Ҳоло мо майдони тамосро пур кардаем client_id, ки бо он мо ҳисобнома-фактураро ворид мекунем.

Манбаъ: will.com

Илова Эзоҳ