none
Error al ejecutar consulta con xml RRS feed

  • Pregunta

  • Hola tengo esta consulta!

    declare @idec int, @doc varchar(1000)
    set @doc='
    <ROOT>
    <Caja codcaj="13" nomcaj="contabilidad" />
    <Caja codcaj="14" nomcaj="gerencia" />
    </ROOT>'
    exec sp_xml_preparedocument @idec output,@doc
    declare @codcaj int, @nomcaj varchar(100)
    declare dpto cursor for
    select * from openxml(@idec,'/ROOT/Caja/',2) with(codcaj int, nomcaj varchar(100))
    open dpto;
    fetch next from dpto into @codcaj,@nomcaj while @@FETCH_STATUS=0
    begin
    if exists(select * from Caja where codcaj=@codcaj)
    begin
    update Caja set codcaj=@codcaj, nomcaj=@nomcaj where codcaj=@nomcaj
    end
    else
    insert into Caja(codcaj,nomcaj) values(@codcaj,@nomcaj)
    end
    fetch next from dpto
    close dpto;
    Cuando la ejecuto se queda pensando y cuando le doy a cancelar me dice que no se pueden insertar valores Null en Codcaj.. Si alguien tiene alguna idea

    jueves, 23 de julio de 2015 19:56

Respuestas

  • Que tal,

    He mejorado tu query para leer XML, además he agregado EXEC sp_xml_removedocument @idec; si no agregas esto seguirá consumiendo memoria de SQL Server, también agrega esto al finalizar tus Cursores.

    close dpto;
    deallocate dpto;

    Aqui el script:

    declare @idec int, @doc varchar(1000)
    set @doc=
    '<ROOT>
    	<Caja codcaj="13" nomcaj="contabilidad" />
    	<Caja codcaj="14" nomcaj="gerencia" />
    </ROOT>'
    exec sp_xml_preparedocument @idec output,@doc
    declare @codcaj int, @nomcaj varchar(100)
    
    declare dpto cursor for
    select * from openxml(@idec,'/ROOT/Caja',2) 
    	with(
    		[codcaj] int '@codcaj', 
    		[nomcaj] varchar(100) '@nomcaj'
    		);
    open dpto;
    fetch next from dpto into @codcaj,@nomcaj 
    while @@FETCH_STATUS=0
    begin
    	--select @codcaj,@nomcaj 
    	if exists(select * from Caja where codcaj=@codcaj)
    	begin
    		update Caja set codcaj=@codcaj, nomcaj=@nomcaj where codcaj=@nomcaj
    	end
    	else
    	begin
    		insert into Caja(codcaj,nomcaj) values(@codcaj,@nomcaj)
    	end
    	fetch next from dpto INTO @codcaj,@nomcaj
    end
    close dpto;
    deallocate dpto;
    EXEC sp_xml_removedocument @idec;

    Ingresa aquí en donde muestro otra manera más óptima de leer archivos XML, útil para SQL Server 2008 o superior.

    Leer archivos XML

    Además puedes mejorar el rendimiento de tu script usando Mergue para SQL Server que en una sola sentencia hace INSERT/UPDATE a tu Tabla, así te evitarías hacer uso del IF... ELSE para verificar la existencia del registro: Mergue SQL Server

    Saludos!


    Ayacucho - Perú
    Recuerda si mi solución atiende tu consulta por favor márcala como útil y como respuesta.

    http://litigiouslobo.blogspot.com/
    El Blog de Herbert Mendoza

    • Editado Nathán XS jueves, 23 de julio de 2015 20:47
    • Marcado como respuesta Argenis R R jueves, 23 de julio de 2015 20:54
    jueves, 23 de julio de 2015 20:29

Todas las respuestas

  • Que tal,

    He mejorado tu query para leer XML, además he agregado EXEC sp_xml_removedocument @idec; si no agregas esto seguirá consumiendo memoria de SQL Server, también agrega esto al finalizar tus Cursores.

    close dpto;
    deallocate dpto;

    Aqui el script:

    declare @idec int, @doc varchar(1000)
    set @doc=
    '<ROOT>
    	<Caja codcaj="13" nomcaj="contabilidad" />
    	<Caja codcaj="14" nomcaj="gerencia" />
    </ROOT>'
    exec sp_xml_preparedocument @idec output,@doc
    declare @codcaj int, @nomcaj varchar(100)
    
    declare dpto cursor for
    select * from openxml(@idec,'/ROOT/Caja',2) 
    	with(
    		[codcaj] int '@codcaj', 
    		[nomcaj] varchar(100) '@nomcaj'
    		);
    open dpto;
    fetch next from dpto into @codcaj,@nomcaj 
    while @@FETCH_STATUS=0
    begin
    	--select @codcaj,@nomcaj 
    	if exists(select * from Caja where codcaj=@codcaj)
    	begin
    		update Caja set codcaj=@codcaj, nomcaj=@nomcaj where codcaj=@nomcaj
    	end
    	else
    	begin
    		insert into Caja(codcaj,nomcaj) values(@codcaj,@nomcaj)
    	end
    	fetch next from dpto INTO @codcaj,@nomcaj
    end
    close dpto;
    deallocate dpto;
    EXEC sp_xml_removedocument @idec;

    Ingresa aquí en donde muestro otra manera más óptima de leer archivos XML, útil para SQL Server 2008 o superior.

    Leer archivos XML

    Además puedes mejorar el rendimiento de tu script usando Mergue para SQL Server que en una sola sentencia hace INSERT/UPDATE a tu Tabla, así te evitarías hacer uso del IF... ELSE para verificar la existencia del registro: Mergue SQL Server

    Saludos!


    Ayacucho - Perú
    Recuerda si mi solución atiende tu consulta por favor márcala como útil y como respuesta.

    http://litigiouslobo.blogspot.com/
    El Blog de Herbert Mendoza

    • Editado Nathán XS jueves, 23 de julio de 2015 20:47
    • Marcado como respuesta Argenis R R jueves, 23 de julio de 2015 20:54
    jueves, 23 de julio de 2015 20:29
  • Cual version de sql server usas?

    Pregunto la version porque a partir de la version 2008 contamos con la sentencia MERGE, la cual acorta el codigo.

    1 - No hace falta un cursor para hacer lo que haces.

    2 - Si los codcaj son iguales entonces para que actualizarlos?

    CREATE TABLE #Caja (
    codcaj int NOT NULL PRIMARY KEY,
    nomcaj varchar(100) NULL
    );
    
    INSERT INTO #Caja (codcaj, nomcaj)
    SELECT 13, NULL;
    
    SELECT * FROM #Caja;
    
    DECLARE @idec int, @doc varchar(1000);
    
    SET @doc='
    <ROOT>
    <Caja codcaj="13" nomcaj="contabilidad" />
    <Caja codcaj="14" nomcaj="gerencia" />
    </ROOT>';
    
    EXEC sp_xml_preparedocument @idec OUTPUT,@doc;
    
    -- leer doc xml y volcarlo en una tabla temporal
    SELECT
        *
    INTO
        #T 
    FROM
        OPENXML(@idec,'/ROOT/Caja', 1) 
        WITH(codcaj int, nomcaj varchar(100));
    
    EXEC sys.sp_xml_removedocument @idec;
    
    -- actualizar tabla #Caja con filas en tabla #T
    UPDATE
        C
    SET
        C.nomcaj = T.nomcaj
    FROM
        #Caja AS C
        INNER JOIN
        #T AS T
        ON C.codcaj = T.codcaj
    
    -- insertar en tabla #Caja filas en tabla #T
    INSERT INTO #Caja (codcaj, nomcaj)
    SELECT codcaj, nomcaj
    FROM #T AS T
    WHERE NOT EXISTS (SELECT * FROM #Caja AS C WHERE C.codcaj = T.codcaj);
    
    SELECT * FROM #Caja;
    
    DROP TABLE #Caja, #T;
    GO

    Aca el script usando metodos del tipo de data xml y la sentencia MERGE.

    CREATE TABLE #Caja (
    codcaj int NOT NULL PRIMARY KEY,
    nomcaj varchar(100) NULL
    );
    
    INSERT INTO #Caja (codcaj, nomcaj)
    SELECT 13, NULL;
    
    SELECT * FROM #Caja;
    
    DECLARE @doc varchar(1000);
    
    SET @doc='
    <ROOT>
    <Caja codcaj="13" nomcaj="contabilidad" />
    <Caja codcaj="14" nomcaj="gerencia" />
    </ROOT>';
    
    WITH R AS (
    SELECT
    	N.x.value('@codcaj[1]', 'int') AS codcaj,
    	N.x.value('@nomcaj[1]', 'varchar(100)') AS nomcaj
    FROM
    	(SELECT CAST(@doc AS xml) AS x) AS T
    	CROSS APPLY
    	T.x.nodes('/ROOT/Caja') AS N(x)
    )
    MERGE INTO #Caja AS T
    USING R AS S
    ON T.codcaj = S.codcaj
    WHEN MATCHED THEN
        UPDATE SET T.nomcaj = S.nomcaj
    WHEN NOT MATCHED BY TARGET THEN
        INSERT (codcaj, nomcaj) VALUES(S.codcaj, S.nomcaj);
        
    SELECT * FROM #Caja;
    
    DROP TABLE #Caja;
    GO

    No incorpore loqueo de tabla para evitar que alguien inserte mientras se actualiza.


    AMB

    Some guidelines for posting questions...

    AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas


    jueves, 23 de julio de 2015 20:36