in

UGISS Community

Il sito della community dello User Group Italiano di SQL Server

Leggere un file XML da un campo text per scomporlo tramite OPENXML (SQL Server 2000)

Last post 05-17-2008 13.46 by dmauri. 2 replies.
Page 1 of 1 (3 items)
Sort Posts: Previous Next
  • 05-15-2008 16.59

    • pscorca
    • Top 150 Contributor
    • Joined on 10-11-2007
    • Posts 2
    • Points 40

    Leggere un file XML da un campo text per scomporlo tramite OPENXML (SQL Server 2000)

    Debbo importare in SQL Server 2000 dei file XML.

    Per farlo utilizzerò il comando OPENXML per prendere i dati che mi servono.I file XML che mi verranno forniti probabilmente conterranno più di 8000 caratteri e quindi pensavoin prima battuta di copiare il contenuto di ogni file in un campo text di una tabella apposita,usando UPDATETEXT.Poi, però, per impiegare la stored procedure sp_xml_preparedocument debbo valorizzareuna variabile con il contenuto del campo text. Da quello che ho visto READTEXT consentedi leggere il contenuto di un text a partire da un puntatore (specificando un offset ed una lunghezza),ma non ho compreso se sia possibile o meno valorizzare una variabile con il contenuto nel text.Ovviamente, l’obiettivo finale è utilizzare una SELECT con OPENXML per estrarre i dati che mi interessano

    dal file XML.

    Qualche suggerimento in merito?

    • Post Points: 20
  • 05-15-2008 18.05 In reply to

    • sgovoni
    • Top 10 Contributor
      Male
    • Joined on 10-18-2007
    • Posts 147
    • Points 2.230

    Re: Leggere un file XML da un campo text per scomporlo tramite OPENXML (SQL Server 2000)

    Ciao,

    ho affrontato anch'io un problema simile (su SQL Server 2000), posto di seguito la stored procedure che ho sviluppato. Permette di importare un file XML di lunghezza variabile all'interno di una tabella del DB.

    Esempio del file Tabella1.xml

    <?xml version="1.0" ?>
    - <DATA IDENTIFIER="Tabella1">
    - <RECORD>
      <Campo1>valore</Campo1>
       <Campo2>valore</Campo2>
    </RECORD>
    </DATA>

    IF OBJECT_ID('USP_IMPORT_XML_INTO_SQL', 'P') IS NOT NULL

      DROP PROCEDURE DBO.USP_IMPORT_XML_INTO_SQL

    GO

     

    CREATE PROCEDURE DBO.USP_IMPORT_XML_INTO_SQL

      (@P_STR_PATH VARCHAR(512),

       @P_STR_FILENAME VARCHAR(56),

       @P_STR_TABLENAME VARCHAR(32))

    AS BEGIN

      -------------------------------------------------------------------

      -- Utilizzo      : Legge un file @Path + @FileName (file/stream) --

      --                 XML ed importa i dati in @TableName           --

      -------------------------------------------------------------------

      SET NOCOUNT ON

      DECLARE @strCommand VARCHAR(1024)

      IF(RIGHT(@P_STR_PATH, 1) <> '\')

        SET @P_STR_PATH = @P_STR_PATH + '\'

      -- Lettura file XML ed importazione dei dati all'interno di una tabella

      -- temporanea

      -- Creazione tabella temporanea

      CREATE TABLE #tmpFileLines

        (rowID INTEGER IDENTITY,

         LineData VARCHAR(255))

      -- Insert linea from files into temp table (utilizzo xp_cmdshell)

      SET @strCommand = 'TYPE ' + @P_STR_PATH + @P_STR_FILENAME

      INSERT #tmpFileLines EXEC master.dbo.xp_cmdshell @strCommand

      DECLARE @strXMLText VARCHAR(8000),

              @strCur_Line_XML VARCHAR(8000),

              @strCur_Line_XML_Reverse VARCHAR(8000),

              @str_Line_XML_To_Insert VARCHAR(8000),

              @str_Line_XML_Res VARCHAR(8000),

              @i INTEGER,

              @j INTEGER,

              @z INTEGER,

              @hDoc INTEGER,

              @str_TMP VARCHAR(512)

      -- Lettura dei dati XML dalla tabella temporanea ad una variabile stringa

      -- La variabile stringa verrà utilizzata con la OPENXML

      DECLARE Cur_Read_Line_XML CURSOR

      FOR SELECT ISNULL(RTRIM(LineData), '')

          FROM #tmpFileLines ORDER BY rowID ASC

      OPEN Cur_Read_Line_XML

      FETCH NEXT FROM Cur_Read_Line_XML INTO @strCur_Line_XML

      WHILE @@FETCH_STATUS = 0

      BEGIN  

        SET @i = CHARINDEX('DATA IDENTIFIER="' + @P_STR_TABLENAME + '"',

                           @strCur_Line_XML)

        IF (@i > 0)

        BEGIN

          SET @str_TMP = 'DATA IDENTIFIER="' + @P_STR_TABLENAME + '"'

          SELECT @strCur_Line_XML = REPLACE(@strCur_Line_XML,

                                            @str_TMP,

                                            'DATA')

        END

        SET @strCur_Line_XML_Reverse = REVERSE(@strCur_Line_XML)

        SET @j = CHARINDEX('>DROCER/<', @strCur_Line_XML_Reverse)

        IF (@j = 0)

        BEGIN

          SET @str_Line_XML_Res = @strCur_Line_XML

          FETCH NEXT FROM Cur_Read_Line_XML INTO @strCur_Line_XML

          SET @strCur_Line_XML = @str_Line_XML_Res + @strCur_Line_XML

          CONTINUE

        END

        --PRINT LEN(@strCur_Line_XML)

        SET @z = (LEN(@strCur_Line_XML) - @j + 1)

        SET @str_Line_XML_To_Insert = SUBSTRING(@strCur_Line_XML, 1, @z)

        SET @str_Line_XML_Res = SUBSTRING(@strCur_Line_XML, @z+1, LEN(@strCur_Line_XML))

        -- Preparazione documento per utilizzo della OPENXML

        IF (CHARINDEX('</DATA>', UPPER(@str_Line_XML_To_Insert)) > 0)

          EXEC sp_xml_preparedocument @hDoc OUTPUT, @str_Line_XML_To_Insert

        ELSE BEGIN

          SET @str_Line_XML_To_Insert = @str_Line_XML_To_Insert + '</DATA>'

          EXEC sp_xml_preparedocument @hDoc OUTPUT, @str_Line_XML_To_Insert

        END

        -- Inserimento utilizzando OPENXML

        --PRINT (@str_Line_XML_To_Insert)

        -- Import Tabella1 (esempio)

        IF (UPPER(@P_STR_TABLENAME)=UPPER('Tabella1'))

          INSERT INTO Tabella1

            SELECT *

            FROM OPENXML(@hDOC, '/DATA/RECORD', 2)

            WITH Tabella1

        -- Import Tabella2 (esempio)

        ELSE IF (UPPER(@P_STR_TABLENAME)=UPPER('Tabella2'))

          INSERT INTO Tabella2

            SELECT *

            FROM OPENXML(@hDOC, '/DATA/RECORD', 2)

            WITH Tabella2

        --ELSE... Import Tabella3 (esempio)

        ELSE

          PRINT 'L''Import della tabella ' + @P_STR_TABLENAME + ' non è gestito.'

        EXEC sp_xml_removedocument @hdoc

        FETCH NEXT FROM Cur_Read_Line_XML INTO @strCur_Line_XML

        SET @strCur_Line_XML = '<DATA>' + @str_Line_XML_Res + @strCur_Line_XML

      END

      CLOSE Cur_Read_Line_XML

      DEALLOCATE Cur_Read_Line_XML

      DROP TABLE #tmpFileLines

      SET NOCOUNT OFF

    END

    La seguente chiamata eseguirà l'importazione del file Tabella1.xml all'interno dell'omonima tabella.

    -- Import Tabella1

    DELETE FROM Tabella1

     

    EXEC DBO.USP_IMPORT_XML_INTO_SQL 'C:\XML\In', 'Tabella1.xml', 'Tabella1'

     

    SELECT * FROM Tabella1 

    L'utilizzo del cursore "danneggia" le prestazioni, ma nel mio caso le performance sono accettabili perchè c'è solo un utente (alla volta) che esegue l'importazione.

    Spero possa essere utile.

    Ciao!

    Sergio

    • Post Points: 20
  • 05-17-2008 13.46 In reply to

    • dmauri
    • Top 10 Contributor
      Male
    • Joined on 05-14-2007
    • Novate Milanese
    • Posts 1.028
    • Points 13.275

    Re: Leggere un file XML da un campo text per scomporlo tramite OPENXML (SQL Server 2000)

    Ciao Sergio

    perchè non ne fai un semplice articoletto da mettere nella sezione "Scripts" di UGISS?

    :-)

    Davide Mauri
    Microsoft MVP - SQL Server, MCP, MCAD, MCDBA, MCT - http://www.davidemauri.it
    Socio Fondatore e Mentor di Solid Quality Learning Italy - http://www.solidq.com
    Presidente di UGISS: User Group Italiano Sql Server - http://www.ugiss.org
    • Post Points: 5
Page 1 of 1 (3 items)
(C) 2007 User Group Italiano di SQL Server