Передача параметров на вложенном XML на SQL сервере - PullRequest
0 голосов
/ 10 апреля 2020

У меня есть файл xml, как показано ниже. Запрос xml с подробностями учителя основного филиала может быть одним или несколькими объектами. Внутри учительских данных количество учеников представлено в виде b, а список учеников представлен как вложенный объект.

<teacherdetails>
    <teacher>2222</teacher>
    <a>10</a>
    <b>3</b>
    <students>
        <student>
          <stua>2000</stua>
          <dista>1</dista>
        </student>
        <student>
          <stua>20</stua>
          <dista>1</dista>
         </student>
         <student>
          <stua>20</stua>
          <dista>1</dista>
         </student>
         <student>
             <Reportno>1586215497241</Reportno>
             <sal>
                <month>13.245555</month>
                <month>72.234355</month>
             </sal>
</teacherdetails>
<teacherdetails>
      <teacher>2222</teacher>
      <a>10</a>
      <b>3</b>
      <students>
        <student>
          <stua>2000</stua>
          <dista>1</dista>
        </student>
        <student>
          <stua>20</stua>
          <dista>1</dista>
         </student>
        <student>
          <stua>20</stua>
          <dista>1</dista>
         </student>
        <student>
      <Reportno>1586215497241</Reportno>
      <sal>
        <month>13.245555</month>
        <month>72.234355</month>
      </sal>
</teacherdetails>

Я пытаюсь получить доступ к данным учителя, a, b, с помощью SQL. Когда я использую xml.nodes используя какое-то время l oop, я пытаюсь установить значения ниже, которые выдают ошибку

;with numbers as
(
    select number
    from master..spt_values
    where type = 'P'
)
select
    T.N.value('teacher[1]', 'varchar(50)') as teacher,
    T.N.value('(students/student/stua[position()=sql:column("N.Number")])['+ @set +']', 'varchar(max)') as student,
    T.N.value('(students/student/dista[position()=sql:column("N.Number")])['+ @set +']', 'varchar(max)')as distance
from 
    @string.nodes('/teacherdetails') as T(N)
cross join 
    numbers as n
where 
    n.number between 1 and (T.N.value('count(students)', 'int'))

Примечание : когда я жестко кодирую 1 или 2 вместо значения @set работает нормально

Выдается ошибка:

Здесь ожидается строковый литерал ...

Я пытался изменение кавычек делает его динамическим c запросом

1 Ответ

0 голосов
/ 10 апреля 2020
declare @x xml = N'
<teacherdetails>
  <teacher>2222</teacher>
  <a>10</a>
  <b>3</b>
  <students>
    <student>
      <stua>2000</stua>
      <dista>1</dista>
    </student>
    <student>
      <stua>20</stua>
      <dista>2</dista>
    </student>
    <student>
      <stua>30</stua>
      <dista>3</dista>
    </student>
  </students>
  <Reportno>1586215497241</Reportno>
  <sal>
    <month>13.245555</month>
    <month>72.234355</month>
  </sal>
</teacherdetails>
<teacherdetails>
  <teacher>3456</teacher>
  <a>10</a>
  <b>2</b>
  <students>
    <student>
      <stua>789</stua>
      <dista>1</dista>
    </student>
    <student>
      <stua>20</stua>
      <dista>2</dista>
    </student>
  </students>
  <Reportno>1586215343434</Reportno>
  <sal>
    <month>13.245555</month>
    <month>72.234355</month>
  </sal>
</teacherdetails>
';    


select 
    t.tchr.value('./teacher[1]', 'nvarchar(50)') as teacherId,
    s.std.value('./stua[1]', 'nvarchar(50)') as stua,
    s.std.value('./dista[1]', 'nvarchar(50)') as dista  
from @x.nodes('./teacherdetails') as t(tchr) --teacher
cross apply t.tchr.nodes('./students/student') as s(std); --students of each teacher


--for your approach, student[position()= sql:column("n.number")]/stua is always a single element thus [1]
;with numbers as(
select number
from master..spt_values
where type = 'P'
)
select
n.number,
T.N.value('teacher[1]', 'varchar(50)') as teacher,
T.N.value('(./students/student[position()= sql:column("n.number")]/stua)[1]', 'varchar(max)') as student,
T.N.value('(./students/student[position()= sql:column("n.number")]/dista)[1]', 'varchar(max)')as distance
from @x.nodes('/teacherdetails')  as T(N)
cross join numbers as n
where n.number between 1 and (T.N.value('./b[1]','int'));
...