PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Oracle към PostgreSQL — Курсори и ltrees

В последната ни статия за курсорите в PostgreSQL говорихме за често срещаните xpressions (CTE). Днес продължаваме да откриваме нови алтернативи на курсорите, като използваме по-малко известна функция на PostgreSQL.

Ще използваме данните, които импортирахме в предишната статия (с връзка по-горе). Ще изчакам малко да следвате процедурата там.

Разбрахте ли го? Добре.

Данните представляват таксономична диаграма на естествения свят. Като напомняне от основната биология в гимназията, тези данни са организирани от Карл Линей в кралство, тип, клас, ред, семейство, род и видове. Разбира се, науката се е придвижила малко напред през последните 250 години, така че таксономичната диаграма е дълбока 21 нива. Намираме дървото на йерархията в таблица, която (не е изненадващо) се нарича itis.hierarchy .

Темата на тази статия е как да използвате ltrees в PostgreSQL. По-конкретно, как да ги използвате за много ефективно преминаване на сложен набор от записи. В този смисъл можем да ги считаме за друг заместител на курсорите.

Данните не са курирани (за съжаление за нас) във формат ltree, така че ще ги трансформираме малко в името на статията.

Първо, ще трябва да инсталирате ltree в базата данни, която използвате, за да следвате тази статия. Разбира се, трябва да сте супер потребител, за да инсталирате разширения.

СЪЗДАДЕТЕ РАЗШИРЕНИЕ, АКО НЕ СЪЩЕСТВУВА ltree;

Сега ще използваме това разширение, за да предоставим някои много ефективни търсения. Ще трябва да трансформираме данните в справочна таблица. За да извършим тази трансформация, ще използваме CTE техниката, която разгледахме в последната статия. По пътя ще добавим латинските и английските имена към таксономичното дърво. Това ще ни помогне да търсим елементи по номер, латински или английски имена.

-- Нуждаем се от малка помощна функция, за да премахнем незаконните имена на етикети.СЪЗДАДЕТЕ ИЛИ ЗАМЕНЕТЕ ФУНКЦИЯ strip_label(thelabel text)ВЪРНА ТЕКСТ $$ -- уверете се, че всички знаци в етикета са законни SELECT SELECT regexp_replace( regexp_replace( regexp_replace ( regexp_replace( -- премахване на всичко, което не е alnum (да, това може да е много по-точно) thelabel, '[^[:alnum:]]', '_','g'), -- консолидиране подчертава '_+', '_', 'g'), -- водещата/крайната лента подчертава '^_*', '', 'g'), '_*$', '', 'g'); $$LANGUAGE sql;СЪЗДАЙТЕ МАТЕРИАЛИЗИРАН ИЗГЛЕД itis.world_view КАТО С РЕКУРСИВЕН свят КАТО ( -- Започнете с основните царства SELECT h1.tsn, h1.parent_tsn, h1.tsn::text numeric_taxonomy, -- Няма гаранция, че ще има текстово име COALESCE(l1.completename,h1.tsn::text,'')::text latin_taxonomy, -- и отново няма гаранция за общо английско име COALESCE(v1.vernacular_name, lower(l1.completename),h1. tsn::text,'unk')::text english_taxonomy ОТ itis.hierarchy h1 LEFT JOIN itis.longnames l1 ON h1.tsn =l1.tsn LEFT JOIN itis.vernaculars v1 ON (h1.tsn, 'английски') =( v1.tsn, v1.language) WHERE h1.parent_tsn =0 UNION ALL SELECT h1.tsn, h1.parent_tsn, w1.numeric_taxonomy || '.' || h1.tsn, w1.latin_taxonomy || COALESCE '.' || (strip_label(l1.completename), h1.tsn::text,'unk'), w1.english_taxonomy || '.' || strip_label(COALESCE(v1.vernacular_name, lower(l1.completename), h1.tsn::текст, 'unk')) ОТ itis.hie raarchy h1 JOIN world w1 ON h1.parent_tsn =w1.tsn LEFT JOIN itis.longnames l1 ON h1.tsn =l1.tsn LEFT JOIN -- просто променете това на "itis.vernaculars v1", за да разрешите multiples и всички езици. (Милиони записи.) (SELECT tsn, min(national_name) vernacular_name FROM itis.vernaculars WHERE language ='English' GROUP BY tsn) v1 ON (h1.tsn) =(v1.tsn) )SELECT w2.tsn, w2. parent_tsn, w2.numeric_taxonomy::ltree, w2.latin_taxonomy::ltree latin_taxonomy, w2.english_taxonomy::ltree english_taxonomyFROM world w2ORDER BY w2.numeric_taxonomyБЕЗ ДАННИ; 

Нека спрем за момент и да помиришем цветята в тази заявка. За начало го създадохме без да попълваме никакви данни. Това ни дава шанс да се погрижим за всякакви синтактични проблеми, преди да генерираме много безполезни данни. Ние използваме итеративното естество на израза за обща таблица, за да съберем тук доста дълбока структура и лесно бихме могли да я разширим, за да покрием повече езици, като добавим данни към таблицата на местните езикове. Материализираният изглед има и някои интересни характеристики на изпълнение. Той ще съкрати и изгради отново таблицата всеки път, когато REFRESH MATERIALIZED VIEW се нарича.

Това, което ще направим по-нататък, е да обновим светогледа си. Най-вече защото е здравословно да правите това от време на време. Но в този случай това, което всъщност прави, е да попълва материализирания изглед с данни от itis схема.

REFRESH MATERIALIZED VIEW itis.world_view; 

Това ще отнеме няколко минути, за да създадете 600K+ реда от данните.

Първите няколко реда ще изглеждат така:

┌────────────┬─────────┬───────────────────────────────────────────────────────────────────────────────┐
│ parent_tsn │   tsn   │                               english_taxonomy                                │
├────────────┼─────────┼───────────────────────────────────────────────────────────────────────────────┤
│     768374 │ 1009037 │ animals.bilateria.protostomia.ecdysozoa.arthropods.hexapods.insects.winged_in…│
│            │         │…sects.modern_wing_folding_insects.holometabola.ants.ants.aculeata.apoid_wasps…│
│            │         │….cicadakillers.crabroninae.larrini.gastrosericina.gastrosericus.gastrosericus…│
│            │         │…_xanthophilus                                                                 │
│     768374 │ 1009038 │ animals.bilateria.protostomia.ecdysozoa.arthropods.hexapods.insects.winged_in…│
│            │         │…sects.modern_wing_folding_insects.holometabola.ants.ants.aculeata.apoid_wasps…│
│            │         │….cicadakillers.crabroninae.larrini.gastrosericina.gastrosericus.gastrosericus…│
│            │         │…_zoyphion                                                                     │
│     768374 │ 1009039 │ animals.bilateria.protostomia.ecdysozoa.arthropods.hexapods.insects.winged_in…│
│            │         │…sects.modern_wing_folding_insects.holometabola.ants.ants.aculeata.apoid_wasps…│
│            │         │….cicadakillers.crabroninae.larrini.gastrosericina.gastrosericus.gastrosericus…│
│            │         │…_zyx                                                                          │
│     768216 │  768387 │ animals.bilateria.protostomia.ecdysozoa.arthropods.hexapods.insects.winged_in…│
│            │         │…sects.modern_wing_folding_insects.holometabola.ants.ants.aculeata.apoid_wasps…│
│            │         │….cicadakillers.crabroninae.larrini.gastrosericina.holotachysphex              │
│     768387 │ 1009040 │ animals.bilateria.protostomia.ecdysozoa.arthropods.hexapods.insects.winged_in…│
│            │         │…sects.modern_wing_folding_insects.holometabola.ants.ants.aculeata.apoid_wasps…│
│            │         │….cicadakillers.crabroninae.larrini.gastrosericina.holotachysphex.holotachysph…│
│            │         │…ex_holognathus                                                                │
└────────────┴─────────┴───────────────────────────────────────────────────────────────────────────────┘ 

В таксономия графиката би изглеждала по следния начин:

Разбира се, това всъщност ще бъде 21 нива дълбоко и общо 600K+ записа.

Сега стигаме до забавната част! ltrees предоставят начин за извършване на някои много сложни заявки в йерархия. Помощта за това е в документацията на PostgreSQL, така че тук няма да навлизаме много задълбочено. За (много бързо) разбиране всеки сегмент от дървото се нарича етикет. И така, това ltree kingdom.phylum.class.order.family.genus.species има 7 етикета.

Заявките срещу ltree използват специална нотация, която е като регулярни изрази в ограничена форма.

Ето един прост пример:Animalia.*.Homo_sapiens

Така че заявката за намиране на човечеството в света би изглеждала така:

SELECT tsn, parent_tsn, latin_taxonomy, english_taxonomy 
FROM itis.world_view WHERE latin_taxonomy ~ 'Animalia.*.Homo_sapiens'; 

Което води до очакваното:

┌────────┬────────────┬────────────────────────────────────────────────┬─────────────────────────────────────────────┐
│  tsn   │ parent_tsn │                 latin_taxonomy                 │              english_taxonomy               │
├────────┼────────────┼────────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ 180092 │     180091 │ Animalia.Bilateria.Deuterostomia.Chordata.Vert…│ animals.bilateria.deuterostomia.chordates.v…│
│        │            │…ebrata.Gnathostomata.Tetrapoda.Mammalia.Theria…│…ertebrates.gnathostomata.tetrapoda.mammals.…│
│        │            │….Eutheria.Primates.Haplorrhini.Simiiformes.Hom…│…theria.eutheria.primates.haplorrhini.simiif…│
│        │            │…inoidea.Hominidae.Homininae.Homo.Homo_sapiens  │…ormes.hominoidea.Great_Apes.African_apes.ho…│
│        │            │                                                │…minoids.Human                               │
└────────┴────────────┴────────────────────────────────────────────────┴─────────────────────────────────────────────┘ 

Разбира се, PostgreSQL никога не би го оставил така. Има обширен набор от оператори, индекси, трансформации и примери.

Разгледайте огромния набор от възможности, които тази техника отключва.

Сега си представете тази техника, приложена към други сложни типове данни, като номера на части, идентификационни номера на превозни средства, структури на спецификациите или всяка друга система за класификация. Не е необходимо тази структура да се излага на крайния потребител поради твърде сложната крива на обучение, за да се използва директно. Но е напълно възможно да се изгради екран за търсене на базата на структура като тази, която е много мощна и крие сложността на внедряването.

За следващата ни статия от поредицата ще проучим използването на plug-in езици. В контекста на намирането на алтернативи на курсорите в PostgreSQL, ще използваме език по наш избор, за да моделираме данните по най-подходящия начин за нашите нужди. Ще се видим следващия път!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Върнете нула, ако не бъде намерен запис

  2. Използване на INSERT с PostgreSQL база данни с помощта на Python

  3. Име на таблица като параметър на функцията на PostgreSQL

  4. Копирайте няколко от колоните на csv файл в таблица

  5. Проучване на забавянето на PostGIS (издание 2019 г.)