Могу ли я удалить не алфавитно-цифровые символы в случае, когда в SQL? - PullRequest
0 голосов
/ 05 марта 2019

Из-за того, что я не могу создать ни функцию, ни процедуру, у меня возникают проблемы с решением проблем при написании SQL-запросов. Вот как выглядит мой текущий запрос

SELECT      ProductData.Customer_ID, ProductData.Product_Type
                CASE
                    WHEN ProductData.Product_Title = 'A_Title' THEN 'A_Title' ELSE 'R_Title' END AS R_Title
                CASE
                    WHEN ProductData.Product_Title = 'A_Title' AND ProductData.Product_Category != 'A_Category' THEN **(REMOVE Non-alphanumeric Character)**
                    WHEN ProductData.Product_Category = 'A_Category' THEN 'A_Category' ELSE 'R_Category' END AS R_Category,
FROM        ProductData

Я надеюсь, что смогу использовать следующий код в результате первой строки второго CASE WHEN в (REMOVE Non-алфавитно-цифровой символ) выше, но все еще не нашел способ сделать это работа.

while @@rowcount > 0
        update  ProductData
        set     Product_Category = replace(Product_Category, substring(Product_Category, patindex('%[^a-zA-Z ]%', Product_Category), 1), '')

Консультации приветствуются.

Ответы [ 2 ]

2 голосов
/ 05 марта 2019

Взяв замечательную функцию от Алана Бурштейна под названием PatExclude8K , которую я включаю сюда

CREATE FUNCTION dbo.PatExclude8K
(
    @String VARCHAR(8000),
    @Pattern VARCHAR(50)
) 
/*******************************************************************************
 Purpose:
 Given a string (@String) and a pattern (@Pattern) of characters to remove, 
 remove the patterned characters from the string.

Usage:
--===== Basic Syntax Example
 SELECT CleanedString 
 FROM dbo.PatExclude8K(@String,@Pattern);

--===== Remove all but Alpha characters
 SELECT CleanedString 
 FROM dbo.SomeTable st
 CROSS APPLY dbo.PatExclude8K(st.SomeString,'%[^A-Za-z]%');

--===== Remove all but Numeric digits
 SELECT CleanedString
 FROM dbo.SomeTable st
 CROSS APPLY dbo.PatExclude8K(st.SomeString,'%[^0-9]%');

 Programmer Notes:
 1. @Pattern is not case sensitive (the function can be easily modified to make it so)
 2. There is no need to include the "%" before and/or after your pattern since since we 
    are evaluating each character individually

 Revision History:
 Rev 00 - 10/27/2014 Initial Development - Alan Burstein

 Rev 01 - 10/29/2014 Mar 2007 - Alan Burstein
        - Redesigned based on the dbo.STRIP_NUM_EE by Eirikur Eiriksson
          (see: http://www.sqlservercentral.com/Forums/Topic1585850-391-2.aspx)
        - change how the cte tally table is created 
        - put the include/exclude logic in a CASE statement instead of a WHERE clause
        - Added Latin1_General_BIN Colation
        - Add code to use the pattern as a parameter.

 Rev 02 - 11/6/2014
        - Added final performane enhancement (more cudo's to Eirikur Eiriksson)
        - Put 0 = PATINDEX filter logic into the WHERE clause

Rev 03 - 5/16/2015
        - Updated code to deal with special XML characters
*******************************************************************************/
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
E1(N) AS (SELECT N FROM (VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) AS X(N)),
itally(N) AS 
(
  SELECT TOP(CONVERT(INT,LEN(@String),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
  FROM E1 T1 CROSS JOIN E1 T2 CROSS JOIN E1 T3 CROSS JOIN E1 T4
) 
SELECT NewString =
((
  SELECT SUBSTRING(@String,N,1)
  FROM iTally
  WHERE 0 = PATINDEX(@Pattern,SUBSTRING(@String COLLATE Latin1_General_BIN,N,1))
  FOR XML PATH(''),TYPE
).value('.[1]','varchar(8000)'));
GO

Вот адаптация, которую вы можете использовать.

WITH E1(N) AS (
    SELECT N FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS X(N)
)
SELECT      ProductData.Customer_ID,
            CASE
                WHEN ProductData.Product_Title = 'A_Title' AND ProductData.Product_Category != 'A_Category' THEN x.NewString
                WHEN ProductData.Product_Category = 'A_Category' THEN 'A_Category' 
                ELSE 'R_Category' END AS R_Category
FROM        ProductData
CROSS APPLY (SELECT NewString =((SELECT SUBSTRING(Product_Category,N,1)
                                  FROM (
                                      SELECT TOP(CONVERT(INT,LEN(Product_Category),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
                                      FROM E1 T1, E1 T2, E1 T3, E1 T4) AS iTally(N)
                                WHERE 0 = PATINDEX('%[^a-zA-Z ]%',SUBSTRING(Product_Category COLLATE Latin1_General_BIN,N,1))
                                FOR XML PATH(''),TYPE).value('.[1]','varchar(8000)'))) AS x;

Как уже упоминали Шон и, возможно, другие, вам следует постоянно очищать данные, а не чистить каждый раз, когда вы их потребляете. Предыдущий оператор SELECT может быть легко преобразован в ОБНОВЛЕНИЕ.

WITH E1(N) AS (
    SELECT N FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) AS X(N)
)
UPDATE ProductData SET 
    Product_Category = CASE
                WHEN ProductData.Product_Title = 'A_Title' AND ProductData.Product_Category != 'A_Category' THEN x.NewString
                WHEN ProductData.Product_Category = 'A_Category' THEN 'A_Category' 
                ELSE 'R_Category' END 
FROM        ProductData
CROSS APPLY (SELECT NewString =((SELECT SUBSTRING(Product_Category,N,1)
                                  FROM (
                                      SELECT TOP(CONVERT(INT,LEN(Product_Category),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
                                      FROM E1 T1, E1 T2, E1 T3, E1 T4) AS iTally(N)
                                WHERE 0 = PATINDEX('%[^a-zA-Z ]%',SUBSTRING(Product_Category COLLATE Latin1_General_BIN,N,1))
                                FOR XML PATH(''),TYPE).value('.[1]','varchar(8000)'))) AS x;

SELECT * FROM ProductData;
1 голос
/ 05 марта 2019

Ваш код обновления работает нормально, вам просто нужно обработать цикл следующим образом:

declare @i int
set @i = 1

while @i is not null
begin
declare @ids table (id int);
delete from @ids
set @i = null
        update  tb
        set val = replace(val, substring(val, patindex('%[^a-zA-Z ]%', val), 1), '')
        OUTPUT INSERTED.id INTO @ids
        where patindex('%[^a-zA-Z ]%', val) > 0

select  top 1 @i = id
from    @ids
end
...