Announcement

Collapse
No announcement yet.

XML in SQL Server Management einlesen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Originally posted by Martin Honnen View Post
    Es ist nicht klar, welche Werte aus dem XML als Zeilen und Spalten ausgegeben werden sollen. Da ja alle Elemente in dem Namensraum sind, ist es vermutlich einfacher, mit WITH XMLNAMESPACES zu arbeiten:

    Code:
    DECLARE @x xml
    SET @x='<collection xmlns="http://www.loc.gov/MARC21/slim">
    <record type="Authority">
    <leader>00000nz a2200000nc 4500</leader>
    <controlfield tag="001">1011387409</controlfield>
    <controlfield tag="003">DE-101</controlfield>
    <controlfield tag="005">20150227101359.0</controlfield>
    <controlfield tag="008">110430n</controlfield>
    <datafield tag="024" ind1="7" ind2=" ">
    <subfield code="a">http://d-nb.info/brd/123</subfield>
    <subfield code="2">uri</subfield>
    </datafield>
    <datafield tag="035" ind1=" " ind2=" ">
    <subfield code="a">(DE-101)105f563</subfield>
    </datafield>
    <datafield tag="035" ind1=" " ind2=" ">
    <subfield code="a">(DE-588)632a452</subfield>
    </datafield>
    </record>
    </collection>';
    
    WITH XMLNAMESPACES ('http://www.loc.gov/MARC21/slim' AS df)
    SELECT
    orga.ref.value('../df:leader[1]','varchar(255)') leader,
    orga.ref.value('../df:controlfield[1]','varchar(255)') controlfield,
    orga.ref.value('@tag','varchar(255)') datafield,
    orga.ref.value('df:subfield[1]','varchar(255)') subfield
    
    FROM @x.nodes('df:collection/df:record/df:datafield') orga(ref)
    GO
    ergibt dann

    Code:
    leader controlfield datafield subfield
    00000nz a2200000nc 4500 1011387409 024 http://d-nb.info/brd/123
    00000nz a2200000nc 4500 1011387409 035 (DE-101)105f563
    00000nz a2200000nc 4500 1011387409 035 (DE-588)632a452
    Andere Frage, wenn ich laange xml habe, wie kann ich das insert machen, könnte man eine Unterabfrage oder so was einbauen?

    Comment


    • #17
      Originally posted by defo2 View Post
      Wenn Du Felder im Select abrufen und ausgeben kannst, sollte das auch für die Filterung funktionieren oder?
      Ich würde einfach mal ne Where Clause dran hängen und passende Kriterien eintragen.
      tja, die Kriterien weiss ich es nicht, wie ich in dieser Sprache formulieren kann,, an sich ist einfach zu sagen:
      wenn datafield tag='024", dann gib mir subfield code="a".

      Comment


      • #18
        Originally posted by Anna85 View Post
        weiss ich es nicht, wie ich in dieser Sprache formulieren kann,, an sich ist einfach zu sagen:
        wenn datafield tag='024", dann gib mir subfield code="a".
        Was meinst du mit "in dieser Sprache"?
        Falls Du XML meinst, das braucht man hier nicht mehr (außer Zugriffspfade/Nodesaufbau zu berücksichtigen.)
        Falls Du SQL meinst, Du weißt aber, was eine "where clause" ist?

        Originally posted by Anna85;
        wenn ich laange xml habe, wie kann ich das insert machen
        Auch hier ist (mir) das Problem unklar.
        Willst Du nicht alles einfügen? Also gemäß Beispiel nicht 3 Datensätze sondern nur 1 Datensatz?

        Wie würdest Du Deine Fähigkeiten einschätzen?
        SQL= JA, XML = Nein

        Du könntest Deine Frage konkreter formulieren, sonst weiß man nicht, was man Dir sagen soll.

        Als allgemeiner Hinweis:
        Wenn Du Deine XML Daten in SQL auslesen kannst (und das kannst Du ja nun), dann geht auch alles andere. Es ist dann eine reine SQL Problematik.
        Als Vereinfachung kannst Du das funktionierende Statement in Klammern setzen und dann per alias ansprechen, als sei es eine Tabelle.

        Also:
        Code:
        select X.leader, X.controlfield, X.datafiedl, X.subfield from
        (..
        SELECT
          orga.ref.value('../df:leader[1]','varchar(255)') leader,
          orga.ref.value('../df:controlfield[1]','varchar(255)') controlfield,
          orga.ref.value('@tag','varchar(255)') datafield,
          orga.ref.value('df:subfield[1]','varchar(255)') subfield
          .. <plus andere felder>
           FROM @x.nodes ..
        ) X
          WHERE datafield ='024'
        Zuletzt editiert von defo2; 12.04.2019, 15:47. Reason: Anführungszeichen für String in WHERE Bedingung korrigiert

        Comment


        • #19
          "Auch hier ist (mir) das Problem unklar.
          Willst Du nicht alles einfügen? Also gemäß Beispiel nicht 3 Datensätze sondern nur 1 Datensatz?"

          Was ich hier gepostet habe ist ein Teil der XML Datei. Die besteht aus 100 Datensätze.
          Ich möchte Sie ablesen mit Bedingungen, aber es geht nicht, was ich schreibe.

          Meine SQL Schätzung ist 4 und XML eine gute 5.
          Ich bin kein Programierer, ich versuche mir alleine alles hier einzulesen etc, was nicht einfach ist. Kannst du mir glauben, dazu noch eine Frau.
          Zuletzt editiert von Anna85; 15.04.2019, 11:17.

          Comment


          • #20
            Originally posted by defo2 View Post

            Code:
            select X.leader, X.controlfield, X.datafiedl, X.subfield from
            (..
            SELECT
            orga.ref.value('../df:leader[1]','varchar(255)') leader,
            orga.ref.value('../df:controlfield[1]','varchar(255)') controlfield,
            orga.ref.value('@tag','varchar(255)') datafield,
            orga.ref.value('df:subfield[1]','varchar(255)') subfield
            .. <plus andere felder>
            FROM @x.nodes ..
            ) X
            WHERE datafield ='024'
            Leider mit der Bedingung geht funktioniert nicht.

            Ich wollte so abfragen, mündlich:
            Gib mir leader, controlfield tag ="001" (was das programm jetzt automatisch macht), datafield tag ="24" mit subfield code ="a",
            datafield tag="040" mit subfield code ="a".

            Hallo, wenn ich die Bedingung schreibe datafield ='024', dann sagte mir "Ungültiger Spaltenname 'datafield'."
            wie kann die die Spaltenname verifizieren/anders definieren???
            Zuletzt editiert von Christian Marquardt; 15.04.2019, 12:15. Reason: Beiträge zusammengeführt

            Comment


            • #21
              Hallo, ich bin schon so weit gekommen, dass ich 1. gewünschte datafield bekomme, da es leicht ist,

              aber ich möchte datafield = 035 noch auch ablesen, allerdings datafield =035 steht nicht immer auf 3. oder 4. Stelle, also ich kann nicht machen datafield[3].
              Ich habe bei cross versucht dort eine Bedingung zu schreiben, aber es geht nicht.

              Hat jemand eine Idee.
              Code:
              select
                  orga.ref.value('declare namespace marc21="http://www.loc.gov/MARC21/slim"; marc21:leader[1]','varchar(255)') leader,
                  orga.ref.value('declare namespace marc21="http://www.loc.gov/MARC21/slim"; marc21:controlfield[1]','varchar(255)') controlfield,
                  orga.ref.value('declare namespace marc21="http://www.loc.gov/MARC21/slim"; marc21:datafield[1]/@tag','varchar(255)') datafield,
                  --orga.ref.value('declare namespace marc21="http://www.loc.gov/MARC21/slim"; marc21:datafield[2]/@tag','varchar(255)') datafield,
                  orga.ref.value('declare namespace marc21="http://www.loc.gov/MARC21/slim"; marc21:datafield[1]/marc21:subfield[1]','varchar(255)') subfield
              
              
              FROM (
              
              --Abfrage auf Import-Tabelle
              
              Select Top 1 xmlData
              
              FROM dbo.orgaImportHistory
              
              --order by loadedDateTime desc
              
              ) xml
              
              --cross apply xml.xmlData.nodes('collection/record') orga(ref)
              --cross apply orga.ref.nodes('declare namespace marc21="http://www.loc.gov/MARC21/slim"; marc21:collection/marc21:record/datafield[@tag="110"]') orga(ref)
              cross apply xml.xmlData.nodes('declare namespace marc21="http://www.loc.gov/MARC21/slim"; marc21:collection/marc21:record') as orga(ref)

              Hätte jemand eine Idee, wo ich die Bedingung einbringen könnte?

              Comment


              • #22
                Ich habe es geschafft:

                Hallo, ich habe es geschaft.
                cross apply orga.ref.nodes('declare namespace marc21="http://www.loc.gov/MARC21/slim"; marc21:datafield[@tag="035"]') data035(ref)

                Allerdings, habe ich z.B. datafield 035 zwei mal, und was ich schreibe liess mir das so ab, das ich zwei Zeilen habe:
                Code:
                1: 2: 3: leader controlfield datafield subfield
                00000nz a2200000nc 4500 1011387409 035 (DE-101)105f563
                00000nz a2200000nc 4500 1011387409 035 (DE-588)632a452
                Was /Wie kann ich sagen, damit es nach komme ließ und damit es so aussieht:
                Code:
                1: 2: leader controlfield datafield subfield
                00000nz a2200000nc 4500 1011387409 035 (DE-101)105f563, (DE-588)632a452

                Comment


                • #23
                  Tja, erstmal als Hinweis zum Forum, das ist leider so kaputt, dass man ältere Threads wie Deinen kaum verfolgen kann.

                  Zu Deinem Problem: Deine 2 Zeilen "entstehen" automatisch, da die varianten Subfelder gemeinsame "Parent" Felder haben. XML kann relationale Daten eindeutig darstellen, in einer Zeilen orientierten Darstellung aus SQL heraus müsstest du eine Aggregation durchführen.

                  Step 1: Du willst die XML Felder separat ansprechen können, am einfachsten so, wie sie im XML stehen, also
                  - '00000nz a2200000nc 4500' as leader,
                  - '1011387409 as controlfieldtag001,
                  dann die subs
                  - '(DE-101)105f563' as datafield35subA
                  usw.
                  also so ungefähr, wie Du es weiter oben über die Namespacedefinitionen gemacht hast. Alles was Du dort im Zugriff in Einzelfelder "zerlegst", kannst Du nachher in sql bequem und wie gewohnt per Feldname ansprechen.

                  Step 2:
                  Diese separaten Felder kannst Du dann wie gewünscht gezielt handhaben und sie im Select Teil direkt nennen oder aggregieren.
                  SQL = ~ select X.leader, X.controlfieldtag001, X.datafield35subA from (XML Aufbereitungs Statement) X
                  ergäbe im wesentlichen erstmal wieder das, was Du bereits erhälst in 2 Zeilen, aber separaten Spalten

                  Zu einer Zeile
                  Aggregat SQL = ~
                  Code:
                  SELECT X.leader, X.controlfieldtag001, STRING_AGG ( X.datafield35subA, ',')
                    FROM (XML Aufbereitungs Statement) X
                   GROUP BY X.leader, X.controlfieldtag001
                  Die 3 Spalten die Du nun erhälst, sollten nur eine Zeile bilden. Die Spalten kannst Du natürlich nach Bedarf zu einem Ausdruck konkatenieren.

                  Comment

                  Working...
                  X