mysql データベースを postgres に移行していて、いくつかの基本的な xml 機能に関する障害に遭遇しました。MySql には、xml ドキュメント内のノードを置き換えるストアド プロシージャがありましたが、postgres でそれを行う方法が見つかりません。
mysql からのストアド プロシージャは次のとおりです。
CREATE DEFINER=`root`@`localhost` PROCEDURE `SP_UpdateExamFilesXmlNode`(examFileId int, xPathExpression varchar(128), xmlNode longtext)
BEGIN
DECLARE xmlData longtext;
DECLARE newXmlData longtext;
DECLARE xmlNodeCount int;
SET xmlData = NULL;
SELECT xml_data INTO xmlData FROM sonixhub.exam_files WHERE id = examFileId;
IF xmlData IS NOT NULL THEN
-- check if the node already exists and if it does then simply update it
SET xmlNodeCount = ExtractValue(xmlData, CONCAT('count(',xPathExpression,')'));
IF xmlNodeCount > 0 THEN
SET newXmlData = UpdateXML(xmlData, xPathExpression, xmlNode);
-- if node doesn't exist then we have to add it manually
ELSE
SET newXmlData = REPLACE(xmlData, '</ImageXmlData>', CONCAT(xmlNode, '</ImageXmlData>'));
END IF;
UPDATE sonixhub.exam_files SET xml_data = newXmlData WHERE id = examFileId;
ELSE
-- there is no xml found so create xml from scratch and insert the node
SET xmlData = CONCAT('<ImageXmlData>',xmlNode,'</ImageXmlData>');
UPDATE sonixhub.exam_files SET xml_data = xmlData WHERE id = examFileId;
END IF;
END
ロジックをアプリケーション自体に移動する代わりに、postgres 関数でこの機能を複製する方法はありますか?
編集 - 私の問題の解決策を見つけました
postgres xml と文字列フォーマット関数を組み合わせて使用するソリューションを見つけました。
ExamFileId は、xml で更新する行を見つけるために使用されます。テーブル情報でコードを変更すると、私の場合はハードコードされたルート ノードになりますが、好きなように変更できます。
関数を呼び出す方法は次のとおりです。
-- this adds <DicomTags> node to your xml value in the table, if <DicomTags> already exists then it's replaced by the one passed in
select update_exam_files_xml_node(1, '/ImageXmlData/DicomTags', '<DicomTags><DicomTag>xxx</DicomTag></DicomTags>');
-- this adds <Settings> node to your xml value in the table, if <Settings> already exists then it's replaced by the one passed in
select update_exam_files_xml_node(1, '/ImageXmlData/Settings', '<Settings>asdf</Settings>');
CREATE OR REPLACE FUNCTION update_exam_files_xml_node(examFileId int, xPathExpression text, xmlNode text)
RETURNS void AS
$BODY$
DECLARE xmlData xml;
DECLARE newXmlData xml;
DECLARE xmlNodeCount int;
DECLARE replaceTag text;
BEGIN
SELECT xml_data INTO xmlData FROM exam_files WHERE id = examFileId;
IF xml_is_well_formed(xmlNode) = false THEN
PERFORM add_error_log('update_exam_files_xml_node', 'xmlNode is not well formed xml');
RETURN;
END IF;
IF xmlData IS NOT NULL THEN
-- check if the node already exists and if it does then simply update it
IF xmlexists(xPathExpression PASSING BY REF xml(xmlData)) = true THEN
-- get the node name
replaceTag := regexp_replace(xPathExpression, '/.*/', '');
-- replace the existing node with the newly passed in node
newXmlData := xml(regexp_replace(xmlData::text, '<'||replaceTag||'>.*</'||replaceTag||'>', xmlNode));
-- if node doesn't exist then we have to add it manually
ELSE
newXmlData := xml(REPLACE(xmlData::text, '</ImageXmlData>', xmlNode||'</ImageXmlData>'));
END IF;
UPDATE exam_files SET xml_data = newXmlData WHERE id = examFileId;
ELSE
-- there is no xml found so create xml from scratch and insert the node
xmlData := '<ImageXmlData>'||xmlNode||'</ImageXmlData>';
UPDATE exam_files SET xml_data = xmlData WHERE id = examFileId;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;