демо: дБ <> скрипка
Тест XML:
<products>
<product>
<code>0001</code>
<name>Prod1</name>
<active>t</active>
<barcodes>
<barcode>0001666</barcode>
<barcode>6660001</barcode>
</barcodes>
</product>
<product>
<code>0002</code>
<name>Prod2</name>
<active>f</active>
<barcodes>
<barcode>0000420</barcode>
</barcodes>
</product>
</products>
Запрос:
WITH xmldata AS (
SELECT '<products><product><code>0001</code><name>Prod1</name><active>t</active><barcodes><barcode>0001666</barcode><barcode>6660001</barcode></barcodes></product><product><code>0002</code><name>Prod2</name><active>f</active><barcodes><barcode>0000420</barcode></barcodes></product></products>'::xml
), insert_products AS (
INSERT INTO products (code, name, active)
SELECT
unnest(xpath('//product/code/text()', xml)),
unnest(xpath('//product/name/text()', xml)),
unnest(xpath('//product/active/text()', xml))::text = 't'
FROM xmldata
RETURNING code -- 1
)
INSERT INTO barcodes (barcode, product_code)
SELECT
unnest(xpath('//barcode/text()', xd.barcodes)), -- 4
ip.code
FROM (
SELECT
unnest(xpath('//product/code/text()', xml))::text as code, -- 2
unnest(xpath('//product/barcodes', xml)) as barcodes
FROM xmldata
)xd
JOIN insert_products ip -- 3
ON xd.code = ip.code
С помощью CTE можно создать два цепных оператора INSERT
. Таким образом, вы можете получить код как RETURNING
значение первого оператора.
При этом вы можете искать правильные штрих-коды для каждого кода продукта, чтобы создать данные вставки для второго оператора INSERT
.
- Вставьте данные о продукте, как вы сделали. Но возвращаем код товара.
- Снова выберите код продукта и данные штрих-кода в формате XML.
- Соединение вставленных товаров с данными о происхождении для назначения вставленных кодов нужным штрих-кодам.
- Извлечение данных штрих-кода и вставка их в таблицу штрих-кодов.
Результат
Table products:
code name active
0001 Prod1 t
0002 Prod2 f
----------------------
Table barcodes:
barcode product_code
0001666 0001
6660001 0001
0000420 0002
Технически вы могли бы сохранить присоединяющуюся часть, если у вас нет каких-либо фильтров во вкладке вашего продукта, потому что на обоих этапах вы работаете со всеми данными одного и того же XML. Объединение имеет смысл только в том случае, если вы хотите отфильтровать некоторые продукты и не хотите хранить отфильтрованные штрих-коды.
демо: дб <> скрипка без соединения
демо: дБ <> скрипка с соединением и фильтром
Обратите внимание как вы можете решить вашу boolean
проблему:
unnest(xpath('//product/active/text()', xml))::text = 't'
Преобразуйте содержимое XML в тип text
и сравните его с вашим значением TRUE
. Сравнение выдает boolean
.
Редактировать: В вашем случае это может быть сделано еще проще: вам не нужно сравнение, а только второе приведение:
unnest(xpath('//product/active/text()', xml))::text::boolean