2

Мне нужно построить часть условий моего запроса sql из xml.Динамические условия построения запросов из XML?

У меня есть XML, как:

<ROOT> 
     <PARAMETROS> 
     <USU_LOGIN>yleon</USU_LOGIN> 
     <USU_NOMBREPRIMERO>Yerusha</USU_NOMBREPRIMERO> 
     <USU_APELLIDOPRIMERO>Leon</USU_APELLIDOPRIMERO> 
     <USU_EMAIL>[email protected]</USU_EMAIL> 
     <USU_FECHACREACION>20130510</USU_FECHACREACION> 
     <USU_CODICIONES1 TIPO="MC">AND USU_ID=4</USU_CODICIONES1> 
     <USU_CODICIONES2 TIPO="MC">AND USU_ID=5</USU_CODICIONES2> 
     <USU_CODICIONES3 TIPO="HG">AND USU_ID=9</USU_CODICIONES3> 
     ... 
     <USU_CODICIONESN TIPO="MC">AND USU_ID=50</USU_CODICIONESN> 
     </PARAMETROS> 
    </ROOT> 

Поэтому мне нужно, чтобы извлечь условия с атрибутом TIPO = "MC"; Я с этим кодом:

SELECT txt = T.Item.value('data(.)', 'varchar(255)') 
FROM @xml.nodes('/ROOT/PARAMETROS/*') AS T(Item) 
WHERE T.Item.value('data(@TIPO)', 'varchar(255)')='MC' 

Теперь предположим, что мой запрос:

Select * from USUARIOS 
where 1=1 USU_CODICIONES1 USU_CODICIONES2 .. USU_CODICIONESn 

мне нужно заменить «@@ USU_CODICIONESX» зацикливание в XML, но не с помощью курсора, может быть КТР.

Ожидаемый результат:

Select * from USUARIOS 
where 1=1 AND USU_ID=4 AND USU_ID=5 .. AND USU_ID=50 

ответ

2

Вам необходимо динамическое создать оператор SQL, а затем использовать эту команду

DECLARE @xml xml = 
    '<ROOT> 
     <PARAMETROS> 
     <USU_LOGIN>yleon</USU_LOGIN> 
     <USU_NOMBREPRIMERO>Yerusha</USU_NOMBREPRIMERO> 
     <USU_APELLIDOPRIMERO>Leon</USU_APELLIDOPRIMERO> 
     <USU_EMAIL>[email protected]</USU_EMAIL> 
     <USU_FECHACREACION>20130510</USU_FECHACREACION> 
     <USU_CODICIONES1 TIPO="MC">AND USU_ID=4</USU_CODICIONES1> 
     <USU_CODICIONES2 TIPO="MC">AND USU_ID=5</USU_CODICIONES2> 
     <USU_CODICIONES3 TIPO="HG">AND USU_ID=9</USU_CODICIONES3> 
     <USU_CODICIONESN TIPO="MC">AND USU_ID=50</USU_CODICIONESN> 
     </PARAMETROS> 
    </ROOT>' 

DECLARE @query nvarchar(max) = 
    'SELECT * FROM USUARIOS where 1=1 USU_CODICIONES1 USU_CODICIONES2 USU_CODICIONESn', 
     @dsql nvarchar(max) 

;WITH cte AS 
(  
    SELECT T.Item.value('fn:local-name(.)', 'varchar(255)') AS cond, 
     T.Item.value('data(.)', 'varchar(255)') AS NewCond, 
     ROW_NUMBER() OVER(ORDER BY 1/0) AS rn 
    FROM @xml.nodes('/ROOT/PARAMETROS/*') AS T(Item) 
    WHERE T.Item.value('data(@TIPO)', 'varchar(255)')='MC' 
), cte2 AS 
(
    SELECT rn, cond, newCond, REPLACE(@query, cond, NewCond) AS NewQuery 
    FROM cte 
    WHERE rn = 1 
    UNION ALL 
    SELECT c.rn, c.cond, c.newCond, REPLACE(c2.NewQuery, c.cond, c.NewCond) 
    FROM cte c JOIN cte2 c2 ON c.rn = c2.rn + 1 
) 
    SELECT TOP 1 @dsql = NewQuery 
    FROM cte2 
    ORDER BY rn DESC 

    --PRINT @dsql 
    EXEC sp_executesql @dsql 

или конкатенации строк с использованием функции COALESCE/ISNULL

DECLARE @xml xml = 
    '<ROOT> 
     <PARAMETROS> 
     <USU_LOGIN>yleon</USU_LOGIN> 
     <USU_NOMBREPRIMERO>Yerusha</USU_NOMBREPRIMERO> 
     <USU_APELLIDOPRIMERO>Leon</USU_APELLIDOPRIMERO> 
     <USU_EMAIL>[email protected]</USU_EMAIL> 
     <USU_FECHACREACION>20130510</USU_FECHACREACION> 
     <USU_CODICIONES1 TIPO="MC">AND USU_ID=4</USU_CODICIONES1> 
     <USU_CODICIONES2 TIPO="MC">AND USU_ID=5</USU_CODICIONES2> 
     <USU_CODICIONES3 TIPO="HG">AND USU_ID=9</USU_CODICIONES3> 
     <USU_CODICIONESN TIPO="MC">AND USU_ID=50</USU_CODICIONESN> 
     </PARAMETROS> 
    </ROOT>' 

DECLARE @query nvarchar(max) = 
    'SELECT * FROM USUARIOS where 1=1 USU_CODICIONES1 USU_CODICIONES2 USU_CODICIONESn', 
     @dsql nvarchar(max) 

    SELECT @dsql = REPLACE(COALESCE(@dsql, @query), 
         T.Item.value('fn:local-name(.)', 'varchar(255)'), 
         T.Item.value('data(.)', 'varchar(255)'))   
    FROM @xml.nodes('/ROOT/PARAMETROS/*') AS T(Item) 
    WHERE T.Item.value('data(@TIPO)', 'varchar(255)')='MC' 
    --PRINT @dsql 
    EXEC sp_executesql @dsql 
+0

Хорошая попытка, но она должна заменить в исходном запросе маркер USU_CODICIONES1..USU _CODICIONESN для элементов xml USU_CODICIONES1..USU_CODICIONESN, они могут быть в другом порядке или в частях исходного запроса. – Artemination

+1

Ответ обновлен. Повторите попытку –

+0

Я думаю, что это как игра с огнем, в запросе может быть много других подвыборов, последняя часть при обратном + charindex + right не будет работать. – Artemination

Смежные вопросы