none
Remover texto de cadena en base a un caracter RRS feed

  • Pregunta

  • Que tal como estan les comento tengo un cadena por ejemplo

    <return : text1 text2 <person : text3 tex4 <comments : text5

    en un campo de mi tabla, lo que quiero hacer es poder remplazar o remover todas las palbras que contengan el caracter < para que el resultado sea

    : text1 text2 : text3 tex4 : text5

    Lo unico que he logrado es quitar el caracter <  o una palabra completa

    REPLACEcampo1, '<:', '')
    REPLACE(campo1, '<RETURN:', '')

    como podria obtener que cualquier texto que contenta este caracter < sea remplazado?

    De antemano gracias por la ayuda...

    Saludos!!

    jueves, 30 de marzo de 2017 14:46

Respuestas

  • Eduardo Hinojosa,

    Si este tipo de actualizaciones es constante y la cantidad de filas es inmensa te recomiendo que utilices las librerías del marco de trabajo de .NET para afrontar el caso, por ejemplo, mediante el uso de expresiones regulares es simple y rápido reemplazar un patrón por una cadena de longitud cero o cualquier otra cadena.

    En t-sql se me ocurre trozar la cadena, filtrar las filas que no contengan el patrón '<%' y finalmente convertir a fila el conjunto, por ejemplo:

    - Función para trozar la cadena:

    CREATE FUNCTION [dbo].[fnSplit]
    (
    	 @Texto nvarchar(4000),
    	 @Delimitador nvarchar(10)
    )
    RETURNS @T table (id int IDENTITY(1, 1), Palabra nvarchar(4000))
    AS
    BEGIN
        DECLARE @xml xml
        SET @xml = N'<root><r>' + REPLACE(@Texto, @Delimitador,'</r><r>') + '</r></root>'
    
        INSERT INTO @T(Palabra)
        SELECT
    	   v.value('.','varchar(max)')
        FROM 
    	   @xml.nodes('//root/r') AS Valor(v)
        
        RETURN
    END

    - Ejercicio

    DECLARE @NombreTabla table (id int, Texto varchar(100))
    INSERT INTO @NombreTabla VALUES 
    (1, '<return : text1 text2 <person : text3 tex4 <comments : text5'),
    (2, '<return : text5 text6 <person : text7 tex8 <comments : text9');
    
    WITH T AS
    (
        SELECT 
    	   t1.id, s.Palabra    
        FROM
    	   @NombreTabla t1
    	   CROSS APPLY (SELECT * FROM dbo.fnSplit(REPLACE(t1.Texto, '<', '@'), ' ')) s
        WHERE
    	   LEFT(s.Palabra, 1) <> '@'
    )
    SELECT 
        STUFF((SELECT ' ' + t2.Palabra FROM T t2 WHERE t2.id = t1.id
    	   FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(4000)'), 1, 1, '')
    FROM 
        T t1
    GROUP BY
        t1.id
    GO

    - Resultado:


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    • Propuesto como respuesta HunchbackMVP viernes, 31 de marzo de 2017 13:50
    • Marcado como respuesta Joyce_ACModerator jueves, 6 de abril de 2017 16:56
    jueves, 30 de marzo de 2017 17:36
  • Willams,

    Muy buena sugerencia.

    Dos cositas, la una que la funcion no toma en cuenta caracteres especiales dentro de un documento XML como "&" y segundo que debes adicionar la clausula ORDER BY donde haces la agregacion de cadena para garantizar que el texto final quede en el mismo orden que lo desmembrastes.

    Por ejemplo, si usas la funcion "inline_split_me" que aparece en este gran articulo, escrito por Erland Sommarskog, la cual usa una tabla auxiliar de numeros entonces pudieras garantizar ese orden.

    http://www.sommarskog.se/arrays-in-sql-2005.html

    -- Itzik's VATN
    CREATE FUNCTION [dbo].[ufn_GetNums](@low AS bigint, @high AS bigint) 
    RETURNS table
    AS
    RETURN (
    WITH
    L0 AS (SELECT c FROM (VALUES(1),(1)) AS D(c)),
    L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
    L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
    L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
    L4 AS (SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
    L5 AS (SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
    Nums AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum FROM L5)
    SELECT TOP(@high - @low + 1) @low + rownum - 1 AS n
    FROM Nums
    ORDER BY rownum
    );
    GO
    CREATE FUNCTION [dbo].[ufn_inline_split_me](@param nvarchar(MAX), @delimiter nchar(1) = N',')
    RETURNS table AS
    RETURN (
    SELECT
        ROW_NUMBER() OVER(ORDER BY n) AS pos,
        LTRIM(RTRIM(CONVERT(nvarchar(4000),
            SUBSTRING(@param, n,
                CHARINDEX(@delimiter COLLATE Slovenian_BIN2, @param + CONVERT(nvarchar(MAX), @delimiter), n) - n)))) AS Value
    FROM
        dbo.ufn_GetNums(1, LEN(@param))
    WHERE
        SUBSTRING(CONVERT(nvarchar(MAX), @delimiter) + @param, n, 1) = @delimiter COLLATE Slovenian_BIN2
    );
    GO
    DECLARE @NombreTabla table (id int, Texto varchar(100));
    
    INSERT INTO @NombreTabla 
    	(id, Texto)
    VALUES 
    	(1, '<return : text1 text2 <person : text3 & tex4 <comments : text5 <extra : text6'),
    	(2, '<return : text5 text6 <person : text7 tex8 <comments : text9');
    
    SELECT
    	T.id,
    	R.col1.value('(./text())[1]', 'varchar(4000)') AS Texto
    FROM
    	@NombreTabla AS T
    	CROSS APPLY
    	(
    	SELECT
    		': ' + T2.value
    	FROM
    		(SELECT T.Texto) AS T0
    		CROSS APPLY
    		dbo.ufn_inline_split_me(T0.Texto, '<') AS T1
    		CROSS APPLY
    		dbo.ufn_inline_split_me(T1.value, ':') AS T2
    	WHERE
    		T2.pos > 1
    	ORDER BY
    		T1.pos
    	FOR XML PATH(''), TYPE
    	) AS R(col1);
    GO



    AMB

    Some guidelines for posting questions...

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



    viernes, 31 de marzo de 2017 13:47

Todas las respuestas

  • Saludos

    SELECT REPLACE('text1 text2 <person : text3 tex4 <comments : text5', '<', '')

    jueves, 30 de marzo de 2017 15:42
  • Eduardo Hinojosa,

    Si este tipo de actualizaciones es constante y la cantidad de filas es inmensa te recomiendo que utilices las librerías del marco de trabajo de .NET para afrontar el caso, por ejemplo, mediante el uso de expresiones regulares es simple y rápido reemplazar un patrón por una cadena de longitud cero o cualquier otra cadena.

    En t-sql se me ocurre trozar la cadena, filtrar las filas que no contengan el patrón '<%' y finalmente convertir a fila el conjunto, por ejemplo:

    - Función para trozar la cadena:

    CREATE FUNCTION [dbo].[fnSplit]
    (
    	 @Texto nvarchar(4000),
    	 @Delimitador nvarchar(10)
    )
    RETURNS @T table (id int IDENTITY(1, 1), Palabra nvarchar(4000))
    AS
    BEGIN
        DECLARE @xml xml
        SET @xml = N'<root><r>' + REPLACE(@Texto, @Delimitador,'</r><r>') + '</r></root>'
    
        INSERT INTO @T(Palabra)
        SELECT
    	   v.value('.','varchar(max)')
        FROM 
    	   @xml.nodes('//root/r') AS Valor(v)
        
        RETURN
    END

    - Ejercicio

    DECLARE @NombreTabla table (id int, Texto varchar(100))
    INSERT INTO @NombreTabla VALUES 
    (1, '<return : text1 text2 <person : text3 tex4 <comments : text5'),
    (2, '<return : text5 text6 <person : text7 tex8 <comments : text9');
    
    WITH T AS
    (
        SELECT 
    	   t1.id, s.Palabra    
        FROM
    	   @NombreTabla t1
    	   CROSS APPLY (SELECT * FROM dbo.fnSplit(REPLACE(t1.Texto, '<', '@'), ' ')) s
        WHERE
    	   LEFT(s.Palabra, 1) <> '@'
    )
    SELECT 
        STUFF((SELECT ' ' + t2.Palabra FROM T t2 WHERE t2.id = t1.id
    	   FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(4000)'), 1, 1, '')
    FROM 
        T t1
    GROUP BY
        t1.id
    GO

    - Resultado:


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    • Propuesto como respuesta HunchbackMVP viernes, 31 de marzo de 2017 13:50
    • Marcado como respuesta Joyce_ACModerator jueves, 6 de abril de 2017 16:56
    jueves, 30 de marzo de 2017 17:36
  • Willams,

    Muy buena sugerencia.

    Dos cositas, la una que la funcion no toma en cuenta caracteres especiales dentro de un documento XML como "&" y segundo que debes adicionar la clausula ORDER BY donde haces la agregacion de cadena para garantizar que el texto final quede en el mismo orden que lo desmembrastes.

    Por ejemplo, si usas la funcion "inline_split_me" que aparece en este gran articulo, escrito por Erland Sommarskog, la cual usa una tabla auxiliar de numeros entonces pudieras garantizar ese orden.

    http://www.sommarskog.se/arrays-in-sql-2005.html

    -- Itzik's VATN
    CREATE FUNCTION [dbo].[ufn_GetNums](@low AS bigint, @high AS bigint) 
    RETURNS table
    AS
    RETURN (
    WITH
    L0 AS (SELECT c FROM (VALUES(1),(1)) AS D(c)),
    L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
    L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
    L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
    L4 AS (SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
    L5 AS (SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
    Nums AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum FROM L5)
    SELECT TOP(@high - @low + 1) @low + rownum - 1 AS n
    FROM Nums
    ORDER BY rownum
    );
    GO
    CREATE FUNCTION [dbo].[ufn_inline_split_me](@param nvarchar(MAX), @delimiter nchar(1) = N',')
    RETURNS table AS
    RETURN (
    SELECT
        ROW_NUMBER() OVER(ORDER BY n) AS pos,
        LTRIM(RTRIM(CONVERT(nvarchar(4000),
            SUBSTRING(@param, n,
                CHARINDEX(@delimiter COLLATE Slovenian_BIN2, @param + CONVERT(nvarchar(MAX), @delimiter), n) - n)))) AS Value
    FROM
        dbo.ufn_GetNums(1, LEN(@param))
    WHERE
        SUBSTRING(CONVERT(nvarchar(MAX), @delimiter) + @param, n, 1) = @delimiter COLLATE Slovenian_BIN2
    );
    GO
    DECLARE @NombreTabla table (id int, Texto varchar(100));
    
    INSERT INTO @NombreTabla 
    	(id, Texto)
    VALUES 
    	(1, '<return : text1 text2 <person : text3 & tex4 <comments : text5 <extra : text6'),
    	(2, '<return : text5 text6 <person : text7 tex8 <comments : text9');
    
    SELECT
    	T.id,
    	R.col1.value('(./text())[1]', 'varchar(4000)') AS Texto
    FROM
    	@NombreTabla AS T
    	CROSS APPLY
    	(
    	SELECT
    		': ' + T2.value
    	FROM
    		(SELECT T.Texto) AS T0
    		CROSS APPLY
    		dbo.ufn_inline_split_me(T0.Texto, '<') AS T1
    		CROSS APPLY
    		dbo.ufn_inline_split_me(T1.value, ':') AS T2
    	WHERE
    		T2.pos > 1
    	ORDER BY
    		T1.pos
    	FOR XML PATH(''), TYPE
    	) AS R(col1);
    GO



    AMB

    Some guidelines for posting questions...

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



    viernes, 31 de marzo de 2017 13:47
  • Muy buena observación Alejandro, de hecho la propuesta también.

    Slds.


    viernes, 31 de marzo de 2017 15:23