如何使用 Oracle 在 SQL/XML 的 XML 类型列中插入 XML 行?
How to insert an XML row in XML type column in SQL/XML using Oracle?
我正在尝试在 Oracle SQL Developer 中编写一个 SQL/XML 查询来更新数据库 table 中的特定行。数据库具有以下结构,
属性 "Translations" 是 XML 类型。例如,我有一本标题为 "Encore une fois" 和 OriginalLanguage "French" 且 ID 为“11”的书。本书共有2个版本,如下1:
ID "17", Year "1997", Price "120", Book "11"
Translations: <Translations>
<Translation Language="English" Price="120"/>
<Translation Language="Russian" Price="110"/>
</Translations>
第二版是:
ID "18", Year "2001", Price "150", Book "11"
Translations: <Translations>
<Translation Language="English" Publisher="Pels And Jafs" Price="180"/>
<Translation Language="Russian" Price="140"/>
</Translations>
我想在第二版中插入一个新的"Translation"节点。我的意思是我想添加显示
的行
<Translation Language="Norwegian" Publisher="KLC" Price="200"/>
我写了下面的查询
UPDATE BOOKDB.EDITION
SET Translations = XMLQUERY('copy $res := $t
modify insert node element Translation {attribute Language {"Norwegian"}, attribute Publisher {"KLC"}, attribute Price {200}}
as last into $res/Translations
return $res'
PASSING Translations AS "t" RETURNING CONTENT)
WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
但我更新了 2 行而不是 1 行,因为它被放置在两个版本中,这是错误的。怎么只输入第二版的行?
看起来您已经完成了困难的部分 - 您只需向 UPDATE 语句添加一个条件,该条件在 EDITION 中指定单行而不是两行。我建议用 SELECT 语句测试你的 WHERE 子句,以确保你得到你想要的行,例如
SELECT *
FROM BOOKDB.EDITION
WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
这 returns 您当前正在更新的 2 行,对吗?
紧接着
WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
你可以添加
AND Edition.ID = '18'
,或者您可以添加
AND Edition.Year = '2001'
如果您想要一个更 general-purpose 的解决方案来始终更新最新版本,您可以执行子查询以确保您选择的是最新版本:
AND not exists (select 1 from BOOKDB.Edition e
where e.Book = Edition.Book
and e.Year > Edition.Year)
一旦你有一个 WHERE 子句来选择你想要的行,将它添加回你的 UPDATE 语句:
UPDATE BOOKDB.EDITION
SET Translations = XMLQUERY('copy $res := $t
modify insert node element Translation {attribute Language {"Norwegian"}, attribute Publisher {"KLC"}, attribute Price {200}}
as last into $res/Translations
return $res'
PASSING Translations AS "t" RETURNING CONTENT)
WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
AND Edition.ID = '18'
如果您只想更新 second 版本,则编写子查询以查找第二个 id 并在 in
子句中使用此子查询。我使用 id
进行排序,但您也可以使用 year
。如果您想要年份,请在 rownumber
中的 order by
中使用它。
UPDATE EDITION
SET Translations = XMLQUERY('copy $res := $t
modify insert node element Translation {attribute Language {"Norwegian"}, attribute Publisher {"KLC"}, attribute Price {200}}
as last into $res/Translations
return $res'
PASSING Translations AS "t" RETURNING CONTENT)
where (book, id) in (
select book, id
from (
select book.id book, edition.id,
row_number() over (partition by book.id order by edition.id) rn
from book join edition on book.id = edition.book where title = 'Encore une fois')
where rn = 2);
我正在尝试在 Oracle SQL Developer 中编写一个 SQL/XML 查询来更新数据库 table 中的特定行。数据库具有以下结构,
属性 "Translations" 是 XML 类型。例如,我有一本标题为 "Encore une fois" 和 OriginalLanguage "French" 且 ID 为“11”的书。本书共有2个版本,如下1:
ID "17", Year "1997", Price "120", Book "11"
Translations: <Translations>
<Translation Language="English" Price="120"/>
<Translation Language="Russian" Price="110"/>
</Translations>
第二版是:
ID "18", Year "2001", Price "150", Book "11"
Translations: <Translations>
<Translation Language="English" Publisher="Pels And Jafs" Price="180"/>
<Translation Language="Russian" Price="140"/>
</Translations>
我想在第二版中插入一个新的"Translation"节点。我的意思是我想添加显示
的行<Translation Language="Norwegian" Publisher="KLC" Price="200"/>
我写了下面的查询
UPDATE BOOKDB.EDITION
SET Translations = XMLQUERY('copy $res := $t
modify insert node element Translation {attribute Language {"Norwegian"}, attribute Publisher {"KLC"}, attribute Price {200}}
as last into $res/Translations
return $res'
PASSING Translations AS "t" RETURNING CONTENT)
WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
但我更新了 2 行而不是 1 行,因为它被放置在两个版本中,这是错误的。怎么只输入第二版的行?
看起来您已经完成了困难的部分 - 您只需向 UPDATE 语句添加一个条件,该条件在 EDITION 中指定单行而不是两行。我建议用 SELECT 语句测试你的 WHERE 子句,以确保你得到你想要的行,例如
SELECT *
FROM BOOKDB.EDITION
WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
这 returns 您当前正在更新的 2 行,对吗?
紧接着
WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
你可以添加
AND Edition.ID = '18'
,或者您可以添加
AND Edition.Year = '2001'
如果您想要一个更 general-purpose 的解决方案来始终更新最新版本,您可以执行子查询以确保您选择的是最新版本:
AND not exists (select 1 from BOOKDB.Edition e
where e.Book = Edition.Book
and e.Year > Edition.Year)
一旦你有一个 WHERE 子句来选择你想要的行,将它添加回你的 UPDATE 语句:
UPDATE BOOKDB.EDITION
SET Translations = XMLQUERY('copy $res := $t
modify insert node element Translation {attribute Language {"Norwegian"}, attribute Publisher {"KLC"}, attribute Price {200}}
as last into $res/Translations
return $res'
PASSING Translations AS "t" RETURNING CONTENT)
WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
AND Edition.ID = '18'
如果您只想更新 second 版本,则编写子查询以查找第二个 id 并在 in
子句中使用此子查询。我使用 id
进行排序,但您也可以使用 year
。如果您想要年份,请在 rownumber
中的 order by
中使用它。
UPDATE EDITION
SET Translations = XMLQUERY('copy $res := $t
modify insert node element Translation {attribute Language {"Norwegian"}, attribute Publisher {"KLC"}, attribute Price {200}}
as last into $res/Translations
return $res'
PASSING Translations AS "t" RETURNING CONTENT)
where (book, id) in (
select book, id
from (
select book.id book, edition.id,
row_number() over (partition by book.id order by edition.id) rn
from book join edition on book.id = edition.book where title = 'Encore une fois')
where rn = 2);