Postgresql

如何更新樹(ltree)中所有行的父/子?

  • July 19, 2016

這是我的配置:

數據庫類型:postgresql(9.3,如果有必要)

表名:product_sections

列名:section_id (integer)&section_path (ltree)

表圖像

詳情:

我有一個參考值:section_id: 15& section_path: Automation_Solutionz。因此,當我想重命名Automation_Solutionz為 時Chrome,我希望更新所有引用Automation_Solutionz

從:

Automation_Solutionz
Automation_Solutionz.Test_Case_Creation
Automation_Solutionz.Test_Case_Creation.Automation
Automation_Solutionz.Test_Case_Creation.Manual

到:

Chrome
Chrome.Test_Case_Creation
Chrome.Test_Case_Creation.Automation
Chrome.Test_Case_Creation.Manual

同樣,當我更新中間的值時,它也應該重命名它們。在上述情況下,Test_Case_Creation應重命名為類似TestCase或其他任何內容。任何位於中間、結尾或開頭的項目也是如此。

希望,我正確地解釋了事情。提前致謝 :)

實現這一目標的另一種方法….

如果替換的文本只是一級樹

update product_sections 
set section_path = 'Chrome' 
where section_path = 'Automation_Solutionz'

如果替換的文本在開頭

update product_sections 
set section_path = 'Chrome' || subpath(section_path,1) 
where section_path ~ 'Automation_Solutionz.*'

如果被替換的文本在中間

update product_sections 
set section_path = subpath(section_path, 0, index(section_path, 'Test_Case_Creation')) || 
                  'Testcase' || 
                  subpath(section_path, index(section_path, 'Test_Case_Creation') + 1) 
where section_path ~ '*.Test_Case_Creation.*{1,}';

如果替換的文本在末尾

update product_sections 
set section_path = subpath(section_path, 0, index(section_path, 'Test_Case_Creation')) || 
                  'Testcase' 
where section_path ~ '*.Test_Case_Creation.*{0}';

可以將ltree數據類型視為text具有一些約束的簡單數據類型。這些約束中最重要的是,如果標籤是標籤路徑的一部分,則標籤以點為邊界。顯然,如果它位於任一端,則會失去一個點;獨自一人時,這些點完全消失了。

幸運的是,這兩種類型之間的轉換很容易。通過這種方式,我們可以設置一小組處理替換的規則,lquery用於查找案例:

-- 1. replace when the label is the whole labelpath
replace(section_path::text, 'to_be_replaced', 'replacement') 
   WHERE section_path ~ 'to_be_replaced'::lquery

-- 2. replace when the label is at the end
replace(section_path::text, '.to_be_replaced', '.replacement')
   WHERE section_path ~ '*.to_be_replaced'::lquery

-- 3. replace when the label is at the beginning
replace(section_path::text, 'to_be_replaced.', '.replacement')
   WHERE section_path ~ 'to_be_replaced.*'::lquery

-- 4. replace when the label is in the middle
replace(section_path::text, '.to_be_replaced.', '.replacement.')
   WHERE section_path ~ '*.to_be_replaced.*'::lquery

在案例 2-4 中,請注意 的搜尋和替換值中的點replace()。通過這種方式,您可以確保始終更換整個標籤,而不僅僅是部分標籤。

引用自:https://dba.stackexchange.com/questions/90797