如何使用Oracle在SQL/XML中的XML类型列中插入XML行?

如何使用Oracle在SQL/XML中的XML类型列中插入XML行?,sql,oracle,sql-update,xquery,sqlxml,Sql,Oracle,Sql Update,Xquery,Sqlxml,我试图在OracleSQLDeveloper中编写一个SQL/XML查询来更新数据库表中的某一行。数据库具有以下结构: 属性“Translations”是XML类型。例如,我有一本书名为“Encore une fois”,原文为“法语”,ID为“11”。本书有以下两个版本: ID "17", Year "1997", Price "120", Book "11" Translations: <Translations> <Translati

我试图在OracleSQLDeveloper中编写一个SQL/XML查询来更新数据库表中的某一行。数据库具有以下结构:

属性“Translations”是XML类型。例如,我有一本书名为“Encore une fois”,原文为“法语”,ID为“11”。本书有以下两个版本:

ID "17", Year "1997", Price "120", Book "11"
Translations:  <Translations>
                  <Translation Language="English" Price="120"/>
                  <Translation Language="Russian" Price="110"/>
               </Translations>

但是我更新了两行而不是一行,因为两个版本都放了它,这是错误的。如何仅在第二版中输入该行?

看起来您已经完成了最难的部分-您只需要在UPDATE语句中添加一个条件,指定版本中的一行而不是两行。我建议您使用SELECT语句测试WHERE子句,以确保您得到的是所需的行

SELECT *
FROM BOOKDB.EDITION
WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
这将返回当前正在更新的2行,对吗

那么就在那之后

WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
你可以加上

AND Edition.ID = '18'
AND Edition.Year = '2001'
,或者您可以添加

AND Edition.ID = '18'
AND Edition.Year = '2001'
如果希望更通用的解决方案始终更新最新版本,可以执行子查询以确保选择的是最新版本:

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'

看起来您已经完成了最难的部分-您只需要在UPDATE语句中添加一个条件,该条件在EDITION中指定一行而不是两行。我建议您使用SELECT语句测试WHERE子句,以确保您得到的是所需的行

SELECT *
FROM BOOKDB.EDITION
WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
这将返回当前正在更新的2行,对吗

那么就在那之后

WHERE Edition.Book in (SELECT ID FROM BOOKDB.Book WHERE Title = 'Encore une fois')
你可以加上

AND Edition.ID = '18'
AND Edition.Year = '2001'
,或者您可以添加

AND Edition.ID = '18'
AND Edition.Year = '2001'
如果希望更通用的解决方案始终更新最新版本,可以执行子查询以确保选择的是最新版本:

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
。如果您想在
中使用它,请按
行数中的
顺序使用它

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);

如果只想更新第二版则编写子查询,查找第二个id,并在
in
子句中使用此子查询。我使用
id
进行订购,但您也可以使用
year
。如果您想在
中使用它,请按
行数中的
顺序使用它

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);

谢谢,我刚刚添加了年份约束谢谢,我刚刚添加了年份约束